I have the following models:
class Label < ActiveRecord::Base
has_many :releases
end
class Release < ActiveRecord::Base
belongs_to :label
has_many :products
has_and_belongs_to_many :tracks
def self.releases_count
self.count(:all)
end
end
class Product < ActiveRecord::Base
belongs_to :release
has_many :releases_tracks, :through => :release, :source => :tracks
has_and_belongs_to_many :tracks
def self.products_count
self.count(:all)
end
end
On my label/index view i'm able to display a count of the Releases absolutely fine using:
<%= label.releases.releases_count %>
I'm trying to do the same for Products using:
<%= label.releases.products.products_count %>
But get a NoMethodError:
undefined method `products' for #<Label:0x10ff59690>
Any ideas?
I have lots of other aggregations I want to perform (Track Counts etc) so some guidance on where I'm going wrong would be really appreciated.
You need define your production/Label association
class Label < ActiveRecord::Base
has_many :releases
has_many :products, :through => :releases
end
Related
I'm trying to build a method that pulls an array of arrays, much like nested loops in the view.
I am trying to build a method on my User model that does this:
#past_parties = User.parties
<%= #past_parties.each do |past_party| %>
<%= past_party.guests("email").uniq.each do |guest| %>
<%= guest.name %> <%= guest.email %>
<% end %>
<% end %>
These are my models:
class User < ActiveRecord::Base
has_many :hosts, dependent: :destroy
has_many :parties, through: :hosts
def past_guests
self.parties.guests
end
end
class Host < ActiveRecord::Base
belongs_to :user
has_many :parties, dependent: :destroy
has_many :guests, through: :parties
end
class Party < ActiveRecord::Base
belongs_to :host
has_many :guests, dependent: :destroy
end
class Guest < ActiveRecord::Base
belongs_to :party
end
I can get the loop to work in the view, but when I try to build it as a method (so I can call current_user.past_guests, if current_user is an instance of User.), I get this error
undefined method `guests' for #<ActiveRecord::Associations::CollectionProxy []>
How do I get all of the guests that a user has ever invited without building the loop in the view?
The problem is that you're trying to access an array from another array:
self.parties.guests
self.parties returns an #<ActiveRecord::Associations::CollectionProxy []>, so if you want to get the guests of the parties you have to loop over the elements.
But since you want only the guests, you can simply change your user class to:
class User < ActiveRecord::Base
has_many :hosts, dependent: :destroy
has_many :parties, through: :hosts
has_many :guests, through: :parties
# Call your guests
def past_guests
self.guests
end
end
Each party is going to have collection of guests. You need to do this in your method definition:
def past_guests
self.parties.collect(&:guests)
end
I have 3 models as below:
class Kick < ActiveRecord::Base
has_many :offs
has_many :retailers, :through => :off
end
class Retailer < ActiveRecord::Base
has_many :offs
has_many :kicks, :through => :off
end
class Off < ActiveRecord::Base
belongs_to :kicks
belongs_to :retailers
end
And I'm trying to display the name of the retailer in my 'show Kick view' as below:
<% #kick.off.each do|off| %>
<%= off.name %>
<%= off.retailers.name %>
<% end %>
Off.name displays fine but I cannot seem to index the retailer's name from this view. What am I missing?
Error:
undefined method `name' for nil:NilClass
class Kick < ActiveRecord::Base
has_many :offs
has_many :retailers, :through => :offs
end
class Retailer < ActiveRecord::Base
has_many :offs
has_many :kicks, :through => :offs
end
class Off < ActiveRecord::Base
belongs_to :kick
belongs_to :retailer
end
also make sure you properly indexed the models in db
class Kick < ActiveRecord::Base
has_many :offs
has_many :retailers, :through => :offs
end
class Retailer < ActiveRecord::Base
has_many :offs
has_many :kicks, :through => :offs
end
class Off < ActiveRecord::Base
belongs_to :kick
belongs_to :retailer
end
#kick = Kick.includes(:retailers => :offs).where('kicks.id' => 1).select('retailers.name, kicks.*')
In the view it should be kick.offs not kick.off
<% #kick.offs.each do|off| %>
<%= off.name %>
<%= off.retailers.name %>
<% end %>
My code works when I run the action like this,
def interest
#interest = Interest.new
#interest.user_id = current_user.id
#interest.idea_id = #idea.id
#interest.save
#ideas = Idea.take(10)
flash[:notice] = "A message has been sent to the poster."
render "ideas/forum"
end
But,why do I get an undefined method for 'interest' when I use this line in my Interest action?
#interest = current_user.ideas.interest.create(params[:interest])
Here's my Idea model
class Idea < ActiveRecord::Base
belongs_to :user
:title
:category
:content
:user_id
:createdDate
:updatedDate
Here's my User model (Devise)
class User < ActiveRecord::Base
has_many :ideas
has_many :interests
end
Here is the button_to tag
<%= button_to "I'm Interested", ideas_interest_path(:id => idea.id, :idea_id => idea.id, :user_id => idea.user_id) ,class: 'btn btn-primary' %>
And my route,
resources :ideas do
resources :interests
end
Interest Model
class Interest < ActiveRecord::Base
belongs_to :user
belongs_to :idea
has_many :users
:idea_id
:user_id
end
NoMethodError - undefined method `interest' for #<Idea::ActiveRecord_Associations_CollectionProxy:0x007f9e5189bab0>:
activerecord (4.2.0)
I think you messed up the association, I'd do:
class User < ActiveRecord::Base
has_many :interests
has_many :ideas, through: :interests
end
class Interest < ActiveRecord::Base
belongs_to :user
belongs_to :idea
# user_id, idea_id
end
class Idea < ActiveRecord::Base
has_many :interests
has_many :users, through: :interests
end
Then I guess the rest would work.
I basically followed the ROR guide, http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association, to create the relationship models as shown below.
Because of the through association, I figured that #user.trips would give you both the trips that the user created and the trips that belong to the user. However, when I do #user.trips.count in console, the result was only the number of trips that the users created; the trips that belonged to the user through the 'group' association was not counted.
Question: How do I get my view to display both the trips that the user created and the trips that the user belongs to through 'group'?
user/show.html.erb
<% unless #user.all_trips.empty? %>
<% #user.all_trips.each do |trip| %>
<!-- Content -->
<% end %>
<% end %>
user.rb
class User < ActiveRecord::Base
has_many :group_trips, :through => :groups,
:source => :trip
has_many :trips, :dependent => :destroy
has_many :groups
def all_trips
self.trips | self.group_trips
end
end
trip.rb
class Trip < ActiveRecord::Base
belongs_to :user
belongs_to :traveldeal
has_many :groups
has_many :users, :through => :groups
end
group.rb
class Group < ActiveRecord::Base
belongs_to :trip
belongs_to :user
end
Thanks!
Edit: Modified code per TSherif's partial solution.
Edit 2: Fixed up the all_trips method. Everything appears to work for me at this point.
Oh! I think I get what you're trying to do and why it's a problem. I was wondering why has_many :trips was called twice. But from what I understand, you have two different User-Trip relationships. These two can't have the same name, otherwise one will hide the other. Try something like this:
class User < ActiveRecord::Base
has_many :group_trips, :through => :groups,
:class_name => "Trip"
has_many :trips, :dependent => :destroy
has_many :groups
def all_trips
Trip.joins(:groups).where({:user_id => self.id} | {:groups => {:user_id => self.id}})
end
end
Or if you're using an older version of Rails that doesn't have MetaWhere:
def all_trips
Trip.joins(:groups).where("(trips.user_id = ?) OR (groups.user_id = ?)", self.id, self.id)
end
I have the following models:
class Release < ActiveRecord::Base
has_many :products, :dependent => :destroy
has_and_belongs_to_many :tracks
end
class Product < ActiveRecord::Base
belongs_to :release
has_many :releases_tracks, :through => :release, :source => :tracks
has_and_belongs_to_many :tracks
before_save do
self.track_ids = self.releases_track_ids
end
end
class Track < ActiveRecord::Base
has_and_belongs_to_many :releases
end
class ReleaseTracks < ActiveRecord::Base
belongs_to :release
belongs_to :track
end
class ProductsTracks < ActiveRecord::Base
belongs_to :product
belongs_to :track
end
At the moment I can create a release and add tracks to it. When I then create a product it inherits the tracks from the release.
What I want to do is be able to delete individual tracks at the product level, but not the track entry itself, so delete the association in ProductsTracks.
How would I go about writing the appropriate destroy method, which controller should it reside in and how should the link_to be structured?
Have you tried just destroying the tracks at the product level? I believe the default behavior is to destroy the relationship, and not the record at the other end of the relationship.