1

I want to derive a field from a series of relations in my Rails 5 application (I want to know all the possible uniform colors associated with a player). I have these models ...

class Player < ApplicationRecord
    ...
    belongs_to :team, :optional => true


class Team < ApplicationRecord
    ...
    has_many :uniforms, :dependent => :destroy


class Uniform < ApplicationRecord
    ...
    has_many :colors, :dependent => :nullify

I want to get all colors associated with the Player model, so I constructed this scope ...

class Player < ApplicationRecord
...
  scope :with_colors, lambda {
    joins(:team => { :uniforms => :resolutions })
  }

However, when I construct an object and attempt to reference the derived field with my scope, I get a method undefined error ...

[12] pry(main)> p.with_colors
NoMethodError: undefined method `with_colors' for #<Player:0x00007fa5ab881f50>

What's the proper way to access the field?

satish
  • 703
  • 5
  • 23
  • 52
  • An includes would work better in this case. Take a look at https://stackoverflow.com/a/24397716/5671433 – Moiz Mansur May 21 '20 at 21:37
  • Your scope is defined in `Player` but `p` is `Players`. – Schwern May 21 '20 at 21:38
  • @MoizMansur, I notice in that answer the "includes" is applied at the class level (Event), but I wish to derive my data from the specific instance. Maybe I wasn't looking at the proper part of your link? – satish May 21 '20 at 21:46
  • You can always add the query `.find_by(id: id)` at the end of the includes. Although this would give you a nested object with player data and uniform data which you might not be looking for. What @Yshmarov is a better option and more rails like – Moiz Mansur May 22 '20 at 23:27

1 Answers1

0

The models should look like:

class Player < ApplicationRecord
    ...
    belongs_to :team, :optional => true


class Team < ApplicationRecord
    ...
    has_many :players
    has_many :colors, through: :uniforms
    has_many :uniforms, :dependent => :destroy


class Uniform < ApplicationRecord
    belongs_to :team
    has_many :colors, :dependent => :nullify

class Color < ApplicationRecord
    belongs_to :uniform

Note that the Team has_many :colors, through: :uniforms. This way you can just call @player.team.colors and get all the available colors that uniforms of a team have.

More details on has_many through https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

Yshmarov
  • 3,450
  • 1
  • 22
  • 41
  • Thanks, although in my particular case, it is not an option to add "has_many :players" to my Team model. How would I reference the colors keeping my models as I have them? – satish May 22 '20 at 00:35
  • why is it "not an option to add "has_many :players" to my Team model"? That is very strange – Yshmarov May 22 '20 at 07:15