Scopes with has many through association - ruby-on-rails

I have 2 models Widget and Feature which have a has many through association using WidgetFeature model.
class Widget < ActiveRecord::Base
has_many :widget_features
has_many :features, :through => :widget_features
end
class WidgetFeature < ActiveRecord::Base
belongs_to :feature
belongs_to :widget
attr_accessible :children_features, :widget_id, :feature_id
end
class WidgetFeature < ActiveRecord::Base
belongs_to :feature
belongs_to :widget
attr_accessible :children_features, :widget_id, :feature_id
end
I have a widget_id.
So i do Widget.find_by_id(widget_id)
Now i want to find all the features for this widget where widget_features.children_features IS NULL.
I dont know how to do this, help me out.

Try
#widget = Widget.find_by_id(widget_id)
#features = #widget.features.conditions("widget_features.children_features IS nil")
EDITED
Ref this
has_many :features, :through => :widget_features, :conditions=>["widget_features.children_features is nil"]
AND then
#widget = Widget.find_by_id(widget_id)
#features = #widget.features

Feature.all(:joins => :widget_features, :conditions => ["widget_id = ? and children_features is null", some_id])

I worked my way around named_scope and found an elegant solution. So, I am posting it here so that others stuck with the same problem can also get help.
My solution gives you a way to access any column of the join model in the has many through association.
Here's the solution for my problem above:
class Widget < ActiveRecord::Base
has_many :widget_features
has_many :features, :through => :widget_features
def leaf_features
widget_features.leaf_features.map{|widget_feature|widget_feature.feature}
end
end
class WidgetFeature < ActiveRecord::Base
named_scope :leaf_features, :conditions => 'children_features IS NULL'
belongs_to :feature
belongs_to :widget
attr_accessible :children_features, :widget_id, :feature_id
end
Now, Widget.find_by_id(widget_id).leaf_features
will give you only those features where
children_features column is NULL.

Related

how to give query in has_many through association Rails

I have following association
Mobile.rb
has_many :mobile_networks, :dependent => :destroy
has_many :networks, :through => :mobile_networks
Network.rb
has_many :mobiles, :through => :mobile_networks
MobileNetwork.rb
belongs_to :mobile
belongs_to :network
I want to query all mobile_networks of mobile and after that I want to check all network whether it is active or not something like I have written this code in my helper where I am getting mobile
def mobile_state(mobile)
mobile.mobile_networks.each do |e|
e.network.is_checked #true
end
end
So i need to do this in a query. Please guide me how to do this.
You could do the following:
Mobile.joins(:networks).where(id: params[:id]).each do |m|
m.networks.map(&:is_checked?)
end
MobileNetwork.mobiles(params[:id]).joins(:network).merge(Network.checked)
class Network < ActiveRecord::Base
scope :checked -> {
where(is_checked: true)
}
end
class MobileNetwork < ActiveRecord::Base
scope :mobiles, ->(*m) {
where(mobile_id: m.flatten.compact.uniq)
}
end

map method in many_to_many relationship

I have the following 3 models in my application:
class Submission < ActiveRecord::Base
has_many :linkedsubmissions
end
class Linkedsubmission < ActiveRecord::Base
belongs_to :submission
has_many :lnksubtypes
end
class Lnksubtype < ActiveRecord::Base
belongs_to :linkedsubmission
end
In the code below '#submission.linkedsubmissions.lnksubtypes' is incorrect.
#history = Audit.find(:all, :conditions => ["auditable_id IN (?)",#submission.linkedsubmissions.lnksubtypes.map{|b| b.LSU_ID} ])
I need to find all audits with 'auditable_id' in #submission.linkedsubmissions.lnksubtypes
You need to add the following has_many relationship to your Submission model.
class Submission < ActiveRecord::Base
has_many :linkedsubmissions
has_many :lnksubtypes, :through => :linkedsubmissions
end
Now, you'll be able to reformat your query like this
#history = Audit.find(:all, :conditions => ["auditable_id IN (?)", #submission.lnksubtypes.map(&:LSU_ID) ])
Audit.find(:all, :conditions => ["auditable_id IN (?)",#submission.linkedsubmissions.map{|b| b.lnksubtypes.map{&:LSU_OID) }.flatten ])
But there should be a better way to get those LSU_OID with sql only.
#history = Audit.where(:auditable_id => #submission.lnksubtypes.map(&:LSU_ID))
slightly shorter

How to save data with has_many :through

I have many-to-many relationship between Game and Account models like below:
class Account < ActiveRecord::Base
has_many :account_games, :dependent => :destroy
has_many :games, :through => :account_games
end
class Game < ActiveRecord::Base
has_many :account_games, :dependent => :destroy
has_many :accounts, :through => :account_games
end
class AccountGame < ActiveRecord::Base
belongs_to :account
belongs_to :game
end
Now I know let's say I want to create a record something like:
#account = Account.new(params[:user])
#account.games << Game.first
#account.save
But how am I supposed to update some of the attributes in AccountGame while I'm doing that? Lets say that AccountGame has some field called score, how would I update this attribute? Can you tell me about the best way to do that? To add any field in the through table while I'm saving the object.
#account = Account.new(params[:user])
#accountgame = #account.account_games.build(:game => Game.first, :score => 100)
#accountgame.save
Though I'd strongly recommend that if you start adding columns to your join-model that you call it something different eg "subscription" or "membership" or something similar. Once you add columns it stops being a join model and starts just being a regular model.
This should work:
class AccountGame < ActiveRecord::Base
belongs_to :account
belongs_to :game
attr_accessible :account_id, :game_id #<======= Notice this line
end

Combining Polymorphic Associations with Rich Many-to-Many Associations

Right now I have a rich many-to-many association with VideoVote as the independent record.
class VideoVote < ActiveRecord::Base
belongs_to :user
belongs_to :video
end
class User < ActiveRecord::Base
has_many :video_votes
has_many :voted_videos,
:through => :video_votes,
:source => :video
end
class Video < ActiveRecord::Base
has_many :video_votes
has_many :voted_users,
:through => :video_votes,
:source => :user
end
However, I want to trasform this into a polymorphic association where comments can also have many VideoVotes (I realize this is confusing, so I should probably change it to Votes). (also, a video will have many comments.) How should I do this?
You first want to add voteable_id:integer and voteable_type:string to your video_votes table.
Then your models will look like:
class VideoVote < ActiveRecord::Base
belongs_to :voteable, :polymorphic => true
end
class Comment < ActiveRecord::Base
has_many :video_votes, :as => :voteable
#code
end
class Video < ActiveRecord::Base
has_many :video_votes, :as => :voteable
#code
end
Then you can access them just like any other has_many:
#video.video_votes
#comment.video_votes
#etc.

Recursive :include in Rails ActiveRecord

Say I have these models
class Project < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :project
belongs_to :user
end
class User < ActiveRecord::Base
has_many :comments
end
So that I can do
p = Project.find(1, :include => :comments)
p.comments.collect(&:user).collect(&:name) # this executes select for each user
How do I say I want to also include comment's user?
I believe :include => {:comments => :user} should work.

Resources