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.
Related
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])}
I am following this tutorial http://guides.rubyonrails.org/v3.2.13/getting_started.html to build my rails app in version 3.2.13 . If you go to the section 6.9 you will find controller and view for creating new posts . Here I do not get how #post variable is passed from new action to create action and where is create function called ? Also , I faced the same problem while working on edit and update actions . Please guide me through this .
It's not passed to create action, it's instantiated again with params you pass from the form displayed with new action.
create action is called with POST request to the path specified in config/routes.rb, leading to specific controller and action.
#post is not passed from new to create the params hash is passed into the create method #post is then set using the new method of the model not the controller. create calls new and then save and returns the object. new returns the object without saving and then save returns the validity of the object. That is why the create method in the controller calls new and then has a conditional statement for save. It is basically saying initialize this object then if it is a valid object do one thing if it is not do another. The create action is not called because of this check.
#this will return true if valid or false if invalid
Post.new(params[:post]).save
#this will always return the Post object which conditionally is true in Ruby
Post.create(params[:post])
#To use the create in a conditional statement it would be
Post.create(params[:post]).valid? || Post.create(param[:post]).save
The last line is unnecessarily redundant and thus why the example uses new followed by save.
create method for a Model is more succinct but probably best to use when you know the object is valid.
Hope this gives you a better understanding but if you are still confused please let me know and I will try to explain further.
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.
I created a static scaffolding for my domain class and got a controller for that domain class. The create action of the controller looks like:
def create() {
[userInstance: new User(params)]
}
I wonder why the line:
[userInstance: new User(params)]
has been added. Obviously when the create action is invoked, there wont be any params - so why would this line have been added?
Obviously when the create action is invoked, there wont be any params
Not necessarily - imagine a situation where you want to pre-populate a couple fields in the form of the create view. You could use:
/app/user/create?username=myusername
Which would result in the view's userInstance having a populated username field for display in the form.
This is fundamentally by Spring, the action is called 'binding' and is the action of tie form elements from one jsp(gsp in this case) to the properties of an object and viceversa.
To tie an object to a form, well, you should create it first, how can ypu tie a null object? it's not possible, that is why the new ClassObject(...)
After that in Groovy we have POGO's, and one feature of POGO's is the ability of initialize them with a map, for example:
new User(name:'John',lastname:'Zuñiga')
But in this case there's a lil' of groovy magic with that 'params' object. That comes from Groovy Servlets or Groovlets. How can you obtain a param with Java incoming from a form? Well, with request.getParam("param_name"), but in this case with Groovy you receive a params object, this params object is a map, a Groovy map...Uhm, one second...
If POGO's in Groovy is able to receive a Map as constructor, and the params object is a Map...maybe...oh coolness I can put that map in the constructor of my object, and after Spring do the binding to the form with this new Object, so this object is travelling in actions from this controller so it comes with the properties populated.
I hope this explanation be clear, if you have questions, I'm here...
Regards
There could be params, although in general there wouldn't be.
It allows pre-loading of values, which may be helpful sometimes, including re-displaying the create form.
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.