RoR Lookup example - ruby-on-rails

I have a very simple problem but cannot find a nice solution. I have a lookup code in ruby (for example, Students that live in a State):
# State lookup (id, name)
class State < ActiveRecord::Base
has_many :students
end
# Class that belogs to a state
class Student< ActiveRecord::Base
belongs_to :state
end
and in the view/students/new.html.erb view, I display the states as a drop down:
<p>
<%= f.label :state %><br />
<%= f.collection_select :state, State.find(:all),
:id, :name, :prompt => "Select a State" %>
</p>
so far, so good, but when I hit save I got an error:
State(#37872860) expected, got String(#21001240)
what seems reasonable, as I'm sending a string instead of a State object to the Student.create method.
Which is the best way of handling this in RoR? I'm getting the State object in the controller by hand and replacing it in the parameters hash, but I think should be a better way.
Thanks very much.
Fernando

<%= f.collection_select :state_id, State.find(:all), :id, :name, :prompt => "Select a State" %>
:state_id not :state

State.find(:all) should really be something that happens in your controller not your view. I don't even think its possible to access a model in the view, which may be your problem. If you do something like this in your controller:
#states = State.find(:all)
Then you use the #states variable in the view:
"Select a State" %>
I hope that helps.

Related

undefined method `map' for "MD":String

I'm struggling to create a dynamic dropdown box arrangement. Thanks to StackExchange Ruby community, I was able to create the first dropdown box. What I'd like to do, is have the user select a group of banks in a particular state, but keep getting the following error message from my f.grouped_collection_select form: undefined method `map' for "MD":String. I looked at ActionView::Helpers::Forms and this video, but nothing seems to work. Any help you could provide would be greatly appreciated. I think I also have to add jquery code too? Here is my current view code:
<%= form_for #boli do |f| %>
<%= f.label :state %>
<%= f.collection_select :state, (Boli.order(:state).select("DISTINCT ON (state) id, state")), :id, :state, include_blank: true %>
<div>
<%= f.label :bank %>
<%= f.grouped_collection_select :bank, Boli.order(:bank), :state, :name, :id, :name, include_blank: true %>
</div>
<% end %>
You need to group banks by state. This implies that there is either a one-to-many (one state to many banks) or a many-to-many relationship between them.
The one-to-many relationship implies Bank is a model that either has state as an attribute or references another model State.
The many-to-many relationship implies that both Bank and State are models joined by another table.
With both bank and state as attributes of another model it's unfeasible to model the relationship between them.
In order to use grouped_collection_select you should have both as models.

fields_for builder .object method does not allow me to retrieve object values

I've got 3 models that comprise a has-many-through association.
Model code as follows:
ItemAttrVal Model (the transition table)
class ItemAttrVal < ActiveRecord::Base
belongs_to :attr_name
belongs_to :registry_item
end
RegistryItem Model
class RegistryItem < ActiveRecord::Base
has_many :item_attr_vals
has_many :attr_names, :through => :item_attr_vals
accepts_nested_attributes_for :item_attr_vals, :allow_destroy => :true
end
AttrName Model
class AttrName < ActiveRecord::Base
has_many :item_attr_vals
has_many :registry_items, :through => :item_attr_vals
end
The RegistryItem uses a fields_for as follows:
<%= item.fields_for :item_attr_vals do |iav| %>
<%= render 'item_attr_val_fields', :f => iav %>
<% end %>
In the partial, it looks like this:
<% logger.debug "object type is: #{f.object}"%>
<% logger.debug "some details are: #{f.object.attr_name_id}--"%>
<%= f.select :attr_name_id, options_from_collection_for_select(AttrName.all,"id","description"), :selected => f.object.attr_name_id, :prompt => "Select an attribute" %>
<%= f.text_field :raw_value %> <br />
The 1st 2 debug lines are the bit that my question is about, but it first relates to the 3rd line.
There, I am attempting to provide the dropdown select field with a "pre-selected" value. This is so that when the user is editing the RegistryItem, their previously selected AttrName will be displayed.
I'm attempting to use the f.object.attr_name_id to set that value, however it does not actually properly select the previously selected value, and instead, just goes to the 1st.
The 1st two debug lines were then me trying to make sure that my f.object method worked...
When I looked in my logs, I see the following:
object type is: #<ItemAttrVal:0x007fb3ba2bd980>
some details are: --
Basically, the 1st line shows me that I am getting the ItemAttrVal
The second line does not seem to retrieve any information for it.
I've also used the debugger to check, and in there, I am able to use display f.object.attr_name_id to show me the exact value that I'm expecting...
This kind of comes down to two questions...
Why can't I retrieve the values of f.object?
Am I trying to do line 3 (<%= f.select :attr_name_id, options_from_collection_for_select(AttrName.all,"id","description"), :selected => f.object.attr_name_id, :prompt => "Select an attribute" %>) wrong, and there's actually a better way to do it?
Thanks in advance!
you need to use params[:attr_name_id] into your options_from_collection_for_select
<%= f.select :attr_name_id, options_from_collection_for_select(AttrName.all,"id","description", params[:attr_name_id].to_i), :prompt => "Select an attribute" %>
hope it helps
Turns out I'd placed the :selected in the wrong location...
Original:
<%= f.select :attr_name_id, options_from_collection_for_select(AttrName.all,"id","description"), :selected => f.object.attr_name_id, :prompt => "Select an attribute" %>
Should be:
<%= f.select :attr_name_id, options_from_collection_for_select(AttrName.all,"id","description", f.object.attr_name_id), :prompt => "Select an attribute" %>
Fixing that solved my problem, the attribute names are now appearing as expected for previously saved attributes.
It still doesn't answer my original query about why I'm not able to get the values for f.object printed out, but at least the original-original problem was resolved.

Rails MetaSearch Associations Undefined Method

I am working with a rails app and have begun to work on a search function using metasearch but I am having troubles getting the correct method for the search.
For example I have a model (Proposal) that has a field cost.
..model/proposal.rb
class Proposal < ActiveRecord::Base
belongs_to :user
has_many :users, :through => :invitations
attr_accessible :cost, :user_id
For which this code works fine with meta search
..views/homes/live_requests.html.erb
<%= form_for #search, :url => "/live_requests", :html => {:method => :get} do |
<%= f.label :cost_greater_than %>
<%= f.text_field :cost_greater_than %><br />
<!-- etc... -->
<%= f.submit %>
Yet with a more complicated association I can not manage to get the meta search path correct.
I am trying to search over:
Proposal.last.user.suburb.name #Returns the name of the suburb as expected
I have tried many associations but cannot find the right one.
Proposal has a user_id field which maps to user
So Proposal.user returns a User
User then has a suburb_id which returns a suburb
Suburb has a field called name which returns a string
How would I work this into a metasearch form?
<%= f.text_field :user_user_suburb_name %>
or
<%= f.text_field :user_id_suburb_id_name %>
I cannot come to a solid conclusion.
Thanks for your help in advance.
Was simply following the correct names as declared by the models.
Ie. in the model above, ensuring that it was User, not users etc.

Rails - Accepts_nested_attributes_for mass assignment error

I am currently trying to set up a form with nested fields on a belongs_to relationship, but I am running into a mass assignment error. My code so far is as follows (some html removed):
Sale model:
class Sale < ActiveRecord::Base
attr_accessible :customer_attributes
belongs_to :customer
accepts_nested_attributes_for :customer
end
new.html.erb:
<div class="container">
<%= form_for :sale, :url => sales_path do |sale| -%>
<%= sale.fields_for :customer do |customer_builder| %>
<%= render :partial => "customers/form", :locals => {:customer => customer_builder, :form_actions_visible => false} %>
<% end -%>
<% end -%>
customers/_form.html.erb
<fieldset>
<label class="control-label">Customer Type</label>
<%= collection_select(:customer, :customer_type_id, CustomerType.all, :id, :value, {}, {:class => "chzn-select"}) %>
</fieldset>
I believe this should allow me to create a Sale object, and a nested Customer object. The parameters being sent are (note some unrelated params are included):
{"utf8"=>"✓",
"authenticity_token"=>"qCjHoU9lO8VS060dXFHak+OMoE/GkTMZckO0c5SZLUU=",
"customer"=>{"customer_type_id"=>"1"},
"sale"=>{"customer"=>{"features_attributes"=>{"feature_type_id"=>"1",
"value"=>"jimmy"}}},
"vehicle"=>{"trim_id"=>"1",
"model_year_id"=>"1"}}
The error I am getting is:
Can't mass-assign protected attributes: customer
I can see why this might be the case, since :customer is not in the attr_accessible list for Sale - though shouldn't the form be sending customer_attributes instead of customer?
Any help / advice appreciated.
EDIT 1: As far as I can tell, attr_accessible in the Sale model should be covered with :customer_attributes - if anyone says different, please let me know.
EDIT 2: I have tried various permutations, but I can not seem to get the parameters to send customer_attributes instead of simply customer - perhaps I have missed a tag or used an incorrect tag somewhere in the forms above?
EDIT 3: I have found another question on SO that indicated a problem with the :url => part on the form_for tag - the question was referring to a formtastic setup, but I'm wondering if that could be what is causing the problem here?
This might be the problem... from the API docs:
Using with attr_accessible
The use of attr_accessible can interfere with nested attributes if
you’re not careful. For example, if the Member model above was using
attr_accessible like this:
attr_accessible :name
You would need to modify it to look like this:
attr_accessible :name, :posts_attributes
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#label-Using+with+attr_accessible
I got to the answer here eventually. The key was this line:
<%= collection_select(:customer, :customer_type_id, CustomerType.all, :id, :value, {}, {:class => "chzn-select"}) %>
which needed to be changed to:
<%= customer.collection_select(:customer_type_id, CustomerType.all, :id, :value, {}, {:class => "chzn-select"}) %>
Once this was changed, everything fell into place.

Rails Select Association with Model in nested form

How can i associate item with the association. Here an example and here the models
-Customer
-Phone
-PhoneType
Customer Phone PhoneType
Id Id Id
First Number Description
Last Phone_Type_Id
Email isViewed
Password
...
The relationship his has follow
Customer
has_many phone
accepts_nested_attributes_for :phone, allow_destroy: :true
Phone
belongs_to :customer
has_one :phone_type
accepts_nested_attributes_for :phone, allow_destroy: :true
PhoneType
belongs_to :phone
The way my form view work his has follow in
Customer#edit view
I render a general form which consist of other fields and inside of it I have the following code
<%= f.fields_for :phones do |b| %>
<fieldset>
<%= b.label :number %>
<%= b.select :PhoneType %> ## issues is here
<%= b.label :isViewed %>
</fieldset>
<% end %>
Thanks in advance!
try
:phone_type
instead of using camelcase (PhoneType) in the form. Your association in the phone model expects a field called :phone_type so you need to fix the case.
Also, what is being rendered in your views with the way they are now? Are you getting any errors?
So you want go give the user the option to select a phone type by choose a description from the dropdown? You might try something like
<%= select(:phone_type, :phone_type_id, PhoneType.all, :id, :description) %>
Finally, you might want to take a look at the simple form gem....
https://github.com/plataformatec/simple_form/

Resources