Rails: how to retrieve the params for child objects in nested form - ruby-on-rails

I have a wizard situation where I create a Parent object, and then build a form with 2 nested children.
The parameters that get submitted look like this:
Parameters: {"room"=>
{"parents_attributes"=>
{"0"=>{"name"=>"r2", "phone"=>"07443107986"},
"1"=>{"name"=>"", "phone"=>""}}},
"commit"=>"Go!", "id"=>"step03"}
(the commit and id are from the wicked wizard step)
If the user refreshes the page, the id's for these children change and the parameters look like this:
Parameters: {"room"=>
{"parents_attributes"=>
{"1"=>{"name"=>"r2", "phone"=>"07443107986"},
"2"=>{"name"=>"", "phone"=>""}}},
"commit"=>"Go!", "id"=>"step03"}
Since the id's are generated by the fields_for.
My controller code retrieves the data like this (the room is saved in the session on a previous step):
#room = Room.find(session[:room_id])
#room.parents.build(room_params[:parents_attributes]['0'])
#room.parents.build(room_params[:parents_attributes]['1'])
This obviously only works if the user does not refresh the page. Also, if validations fire the id's of the children change too.
What is a better way to retrieve these parent_attributes from the params hash?
EDIT
In the wizard step, the child objects are built like this:
when :step03
#room = Room.find(session[:room_id])
2.times{ #room.parents.build }

You can try following to extract hash keys dynamically:
room_params[:parents_attributes].each {|k,_| #room.parents.build(room_params[:parents_attributes][k])}

Related

Getting params from URL in model's create method

Is there a way to get the params from URL in the create method?
My URL for the "new" view is:
/model_name/new?other_model_id=100
I would like to be able to alter the model with ID 100 when I create a new model. I've tried calling params[:other_model_id] in my "create" method, which returned nil and I tried setting the following variable in my "new" method:
#other_model = Model.find(params[:other_model_id])
I have a field called "other_versions" in my model, which is an array of model IDs. When I create a new model I want to add the new model's ID to the array of model IDs in the old model.
Why don't you use the after_createfilter (http://guides.rubyonrails.org/active_record_callbacks.html) and just add the "other_model" id on an hidden field on your create/edit form?
Please make sure, if you are using Rails >4, to add that parameter on your strong parameters (http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html) otherwise it will always be empty when you check on params.

Adding a form input that is excluded from params hash

I've got a form with some check_box_tags. Some of these checkboxes do not belong to the model and need to be removed from the params hash. I know i can use the exclude method, but the problem is that these fields have dynamic ids that I can't know in advance.
My question is:
Is there a way of excluding a form field so it doesn't enter the params hash in the first place?
Many thanks!
Uri
Anytime you submit a form to a controller and the input fields have a name, those K:V pairs will be added to the params request assuming they are white listed by your strong parameters (rails4 only). Your best option would be to use JavaScript. Something like this would filter those fields based on class, data attr, or any other parameter you would like to filter by:
$('.new_resource_form').onSubmit(function(e) {
e.preventDefault();
$('.fields_for_removal').remove();
$(this).submit();
});

Create a field in ruby not associated with a model

I am wondering how can i create a field not associated to the models, the only reason i need the field is to determine which actions to do on it.
Lets say i have a model article, and when creating a new article, i would like a hidden field that would have 0,1,2 and in the controller new, i would see if the params is equal to 0, then do this set of logic or 1 then this set of logic.
Thank you, I also know that defining a set of action for each action won't work.
In a form you can declare both hidden and visible fields that are not directly associated with your models. When you submit the form, in the form's action you can manipulate the attributes in the params that are not related to the model.
When you declare form fields you can use those that end with _tag like email_field_tag, radio_button_tag, and regarding your question, hidden_field_tag. Example:
<% hidden_field_tag 'this_is_hidden' %>
Try it out and inspect what comes into the action: raise params.inspect. In doing so you'll notice the params now includes keys for the attributes you declared that are not related to your model (like the attribute :this_is_hidden)
Try doing it with a hidden_field_tag. (recommendation: put it just before the submit button inside the form tag.)
http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-hidden_field_tag
hidden_field_tag 'decide', '0'
Then in the new action of the controller you can catch it inside the params hash, and compare it with params[:decide].to_i
most easiest way is to have a hidden field as #Zippie, mentioned. However it has some risks as end user could modify the value in the hidden field and your program could behave differently.
What i personally believe is to have a some kind of a methodology to identify from the passing parameters
Ex: if it is a new object then it should go to method A etc...
By that way end use will not have a chance to modify the workflow.

Instance variable in rails - apart from views where can we use it and for how long is it available

I have created a instance variable in rails project, which gets its value from a url parameter like example.com/value. This variable is created in new action, now can it also be used in create action, of the same model.
The value is a id of another model altogether and both the models are associated, I need to create the instance variable in former model.
I need to know, for how long the instance variable is available, and can be use the instance variable of one model in another model.
Clarification with real example
Supposingly there are two models, one is User model and other is Referral model. The root is root :to => 'users#new. Now the user will coming here via example.com/value, where value is the id for Referral model. Now using this value I have to increment two fields: One is visits, which shows how many visits did that particular url bring. Other is signup, which will increment if there is a signup using that value.
I have passed this value via routes in users#new, which I use to increment the visits column of Referral model. Now if the users signup, the users#create would be executed, and I want to be able to use the value in the create action as well, to increment the signup column in Referral model.
As of now, I understand that the instance variable I created in new action to store the value cannot be used in create action. Now how can I achieve this.
In general instance variables only last as long as the user's HTTP request, so they can not be created in one action and used in another.
You could try storing the variable in the session, a hidden input field on the HTML form generated by the new action, or in the urls of links generated by the new action.
I don't know exactly what you are doing, but from the names of your two actions it sounds like there is probably an HTML form involved, so I think the best thing is to use a hidden input, something like this:
<input type="hidden" name="model_id" value="<%= #model_id %>" />
Instance variables only last for that call and in the class they are defined, with the exception of the views. If you have a controller with two methods where one method is your route and another is used internally, then it will be available to both, it is also available to your views.
e.g.
test_controller.rb
def index
something_else
p #variable #outputs "foo" in the terminal
end
def something_else
#variable = "foo"
end
However it would not be available between create and new as these would be called in different requests.

Performing AJAX calls on the "new" controller

In my rails app, I want to have a sortable list as part of an object creation. The best practice suggested in Railscast adds the acts_as_list plugin and then initiates AJAX calls to update item position. However, AJAX calls won't work on an unsaved model, which is the situation with new.
One solution would be to save the model immediately on new and redirect to edit. This would have a nice side effect of persisting any change so the user could resume work should he be interrupted.
However, this solution adds the unwanted complexity of saving an invalid model, compromising rails' validation processes. Is there any better way to allow AJAX + validations without going into too much work?
Your new action has the same access to parameters that any other action has. You could pass parameters for the unsaved object back to the new action and an object re-initialized with attributes set could be returned back to the view. For instance:
controller:
class WidgetsController < ApplicationController
def new
#widget = params.has_key?(:widget) ? Widget.new(params[:widget]) : Widget.new
end
..
end
Then in your view you'd have to send params to the new action via a link or a form post.
you can temporary store unsaved object in a 'session'.
like (this code must be in controller)
my_model = MyModel.new(params[:my_model])
session[:my_model_tmp] = my_model

Resources