Search code examples
ruby-on-railsscoperuby-on-rails-5finder

In Rails 5, can I construct a scope to get fields of my relation?


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?


Solution

  • 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