Search code examples
ruby-on-railsruby-on-rails-3activerecordhas-manymodel-associations

how to write a condition for has_many association that joins two tables?


I have a user model:

class User < ActiveRecord::Base
  has_many :profile_label_values
  belongs_to :company
end

a profile label value model:

class profileLabelValue < ActiveRecord::Base
  belongs_to :profile_label
  belongs_to :user
end

and a profile label model:

class ProfileLabel < ActiveRecord::Base
  belongs_to :company
end

ProfileLabel has two attributes is_deleted and visible. How can I have my has_many association on ProfileLabelValue to only return those values whose ProfileLabels is_deleted = false and visible = true?

How can I do a condition in my has_many :profile_label_values statement that also checks for these two attributes on ProfileLabel?


Solution

  • You are trying to create a M-M relationship between User and ProfileLabel model using the join model ProfileLabelValue. In order to do that I would suggest you to modify your models as below:

    class User < ActiveRecord::Base
      ## For Rails 4.x
      ## has_many :profile_label_values, -> { joins(:profile_label).where("profile_labels.is_deleted = ? and profile_labels.visible = ?", false, true ) } 
      ## For Rails 3.x
      has_many :profile_label_values, include: :profile_label, :conditions => "profile_labels.is_deleted = 'f' and profile_labels.visible = 't'"
      has_many :profile_labels, through: :profile_label_values
      belongs_to :company
    end
    
    class ProfileLabelValue < ActiveRecord::Base  ## ProfileLabelValue and not profileLabelValue
      belongs_to :profile_label
      belongs_to :user
    end
    
    class ProfileLabel < ActiveRecord::Base
      belongs_to :company
      has_many :profile_label_values
      has_many :users, through: :profile_label_values
    end
    

    Now whenever you invoke profile_label_values method on an instance of User, you would receive all the ProfileLabelValue records whose associated profile_label record has is_deleted = false and visible = true.

    For example:

    user = User.find(1) ## Get a user record with id 1
    user.profile_label_values