Rails MetaSearch Associations Undefined Method - ruby-on-rails

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.

Related

Rails 4 - simple_form and pre-populating fields from url

I'm using simple_form and I'd like to pre-populate several fields in my form. In the link to the form I'm passing several values to params in the URL. The trouble comes in when I either try to pass a value to a field that is an integer or an association. In either case, the field does not pre-populate.
Example below...the first two fields populate fine, but I had to force them to be text fields. Maybe that's ok to push the strings from the url into the field, but ideally I'd be able to use either the integer (f.input) or association (f.association). The second two fields don't pull in the param values from the URL.
Any ideas? Thanks in advance!
NOTE - this is for generating a NEW record in the database and not for editing an existing record.
URL: http://localhost:5000/list/new?event_id=4&user_id=11
<!-- These two fields pre-populate -->
<%= f.text_field :event_id, :value => params[:event_id] %>
<%= f.text_field :user_id, :value => params[:user_id] %>
<br>
<!-- These two fields do NOT pre-populate -->
<%= f.association :event_id, :value => params[:event_id] %>
<%= f.input :event_id, :value => params[:event_id], label: 'Event' %>
PS - I'm listening to GusGus' new album on Spotify while working on this and it's helping a lot. :)
Best practice is pre-populate form not with params directly but with ActiveRecord object.
For example you have an AR class:
class Party < ActiveRecord::Base
belongs_to :event
belongs_to :user
end
Then in your controller:
def new
#party = Party.new(party_params)
end
# use strong params to make your parameter more secure;)
def party_params
params.permit(:event_id, :user_id)
end
and then in your edit view:
<%= simple_form_for #party do |f| %>
<%= f.association :event %>
<%= f.association :user %>
<% end %>

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 - 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/

Add star ratings to my model rails3

I have a model called teacher that I'd like to add ratings to (5 star). Currently, I implement this by adding a ratings nested route (resource rating) inside of my teacher resource. Then I created a model: rating with (id, user_id, teacher_id, ratings, ...). Then I created a form with hidden fields, one of which is called stars. When a user clicks on a star, I use jQuery to send an AJAX request to create/update the rating for that user and teacher.
My confusion is this: I'm having two separate forms on the page. I have a form for writing the reviewers comments. This form has two fields: title, comments (and submit). Then I have the ratings form with hidden fields. Is this the right way to go about something like this? It seems to me that I should really have the ratings model fields somehow embedded in the main review form.
Any help highly appreciated. Thank you.
[EDIT]
I've updated my application so that instead of rating a teacher object, users now rate a comment on a teacher
my setup is something like this:
routes
resources :comments as :teacher_comments do
resource :rating
end
models
comment
has_one :rating
attr_accessible :body, :rating_attributes
accepts_nested_attributes_for :rating
rating
belongs_to :comment
attr_accessible :stars, :user_id, :teacher_id, :comment_id
view
<%= form_for( #comment, :remote => true, :url => teacher_comments_path ) do |tc| %>
<%= tc.text_area :body, :maxlength => 450 %>
<%= tc.fields_for :rating do |builder| %>
<%= builder.text_field :stars %>
<% end %>
<% end %>
I don't see the text_field for the stars. It's just not showing up. Is there something I missed?
Indeed, it's generally better to have all these fields in a single form (good for user experience).
Edit:
You might use the method accepts_nested_attributes_for (as you suggested in the comments below). Put the following in your parent Model (teacher); then you should be able to create a single form to handle inputs for both Models:
in the model:
class Comment < ActiveRecord::Base
has_one :rating
accepts_nested_attributes_for :rating
end
in the controller:
def new
#comment = Comment.new
#comment.rating = Rating.new
end
Ryan Bates gives a detailed screencast on the use of these concepts here: Nested Model Form. I recommend it for users who want to know more ins and outs.
Original:
This means that you'll need to point the form to an action that can handle both types of input. You can still use form_for if you like, but specify an action other than your default (or change the code within the default action in your teacher_controller.rb file):
<%= form_for #teacher, :url => {:action => 'create_and_rate'} do |f| %>
Since rating is a Model distinct from teacher (whose form we just created), you'll want to use the generic _tag form helpers for the rating fields.
<%= text_field_tag :rating, :name %> # rating's fields should use the generic form helper
<%= f.text_field :name %> # teacher's fields can use the specific form helper
Since you are pointing to a non-RESTful action, add it to your routes file.
resources :teacher do
:collection do
post 'create_and_rate' # this will match /teachers/create_and_rate to TeachersController#create_and_rate
end
end

Resources