Reputation: 1761
I'm have a few collections in a controller like so:
def show
@cave = Cave.includes(cubs: :mamabear).where(id: params[:id]).first
@cubs = @cave.cubs
@papabear = Papabear.first
@dens = Den.where(papabear_id: @papabear.id)
end
and now I'm trying to sort cubs by dens so I can display the cubs with
@dens.each do |d|
d.cubs
end
so I wrote the following:
def show
....
@dens.each do |den|
den.cubs = [] ## < --- Den does not have an association with Cub ##
@cubs.each do |cub|
den.cubs << cub if cub.mamabear.den_id == den.id
end
end
#reject dens if they don't have cubs
@dens = @dens.reject { |den| den.cubs.all?(&:blank?) }
end
But now I'm getting an undefined method 'cubs for Den' error because Den doesn't have an association with Cub. How do I assign an array of Cubs to each Den without an association?
Upvotes: 0
Views: 391
Reputation: 1263
Have you considered using a "has many through"-association in regards to cubs -> dens and dens -> cubs?
http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
Examples:
class Den
has_many :mamabears
has_many :cubs, through: :mamabears
end
class Cup
belongs_to :mamabear
has_one :den, through: :mamabear
end
Then you should be able to do something like:
den.cups #=> [<Cup ...>]
cup.den #=> <Den ...>
Upvotes: 1
Reputation: 3268
Association is the best way to handle such scenarios if you want to fetch those cubs
belonging to den
at multiple places. if you dont want to implement association. you can try this solution
@den_cubs = []
@dens.each do |den|
cub_for_den= {} #here we are initializing hash each time for new den
@cubs.each do |cub|
cub_for_den[cub.id] = cub if cub.mamabear.den_id == den.id
end
@den_cubs << cub_for_den #put the hash in array
end
@den_cubs = @den_cubs.reject { |dc| dc.blank? }
on the show page you can do this
@den_cubs.each do |dc|
dc.each do |k,v|
# now here you can display all attributes for the cubs
end
end
Upvotes: 1
Reputation: 2450
1: I would create a standard association of Cubs for den. Probably a standard has_many On dens, so each cub has a den_id.
You're messing about re-inventing the wheel, otherwise.
2: you'll probably find that the undefined method is 'cubs=' as opposed to 'cubs'. It's an important distinction as it says what the code is doing when the error is thrown.
3: if you really want to ignore point 1 and make your own which fills an arbitrary attribute from the controller, you can add this to the Den model.
attr_accessor :cubs
Upvotes: 1