Reputation: 334
I'm building an application (web/iOS) that allows a user to set a series of preference options. The models/tables required include:
Model Specs:
class User < ActiveRecord::Base
has_many :user_prefs
has_many :prefopts, through: :user_prefs
end
class Pref < ActiveRecord::Base
has_many :prefopts
has_many :user_prefs
accepts_nested_attributes_for :prefopts
validates :name, presence: true
end
class Prefopt < ActiveRecord::Base
belongs_to :pref
has_many :user_prefs
has_many :users, through: :user_prefs
accepts_nested_attributes_for :user_prefs
end
class UserPref < ActiveRecord::Base
belongs_to :user
belongs_to :prefopt
end
For now, I want to set the user's preferences/options on the user "show" page, so when I pull up a user's record, I see a listing of all the preferences and for each a drop-down list of the available preferences for each option.
I have updated the Users controller to query back the preferences...
# GET /users/1
# GET /users/1.json
def show
@prefs = Pref.all
end
Also, I added to the routes file references under users:
resources :users do
resources :prefs do
get 'prefopts', on: :member
end
end
And this works fine: on a user's "show" page I can see all the available preferences when using this syntax:
<p>
<H2>Preferences</H2>
<ul>
<% @prefs.each do |pref| %>
<li><%= pref.name %></li>
<ul>
</ul>
<% end %>
</ul>
</p>
But when I add the code to loop over each "prefopt" for each pref, I get an error.
<p>
<H2>Preferences</H2>
<ul>
<% @prefs.each do |pref| %>
<li><%= pref.name %></li>
<ul>
<% @pref.prefopts.each do |prefopt| %>
<li><strong>Option: </strong><%= prefopt.name %></li>
<% end %>
</ul>
<% end %>
</ul>
</p>
Error message:
undefined method `prefopts' for nil:NilClass
Now, I've updated the pref scaffolding's show page to allow me to add and list prefopt records for each preference, and I'm using the same syntax from that view here.
If I take the error message at face value, it looks as if it thinks the "pref" is nil, but if that's the case why is the pref's name showing up correctly before I add in the prefopt?
Is there something I need to do in the view to pre-populate each pref's options? Or am I going about this all wrong? It there a best practice that I haven't found yet?
I've done extensive searching and have found some tips on working with many-to-many relationships, including:
I can see how I can save one user record sending a long a bunch of nested attributes, if only I can get the options to display.
I've also searched for best practices in saving user preferences and none of the examples I've found allow for the flexibility to dynamically add user preferences in the future by storing them in a separate model/table. I'm tempted to simply create one table for each preference and one join table for each user and each preference, but that's not a DRY approach. I can see how to save these nested attributes, if I can only list the options available to the user for each preference.
Thanks for any thoughts on this!
Upvotes: 0
Views: 753
Reputation: 1723
The error message you receive is because @pref is not set. Rewrite your view like this:
<% @prefs.each do |pref| %>
<li>
<%= pref.name %>
<ul>
<% pref.prefopts.each do |prefopt| %>
<li><strong>Option: </strong><%= prefopt.name %></li>
<% end %>
</ul>
</li>
<% end %>
(Note I removed the @-sign before pref
on line 5)
Upvotes: 2