Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialJon Moss
1,150 PointsURL Parameters in Rails
Hi, I am trying to pass a string into a Rails form through the URL
EX: Entry model has entry_type:string, so --> domain.com/entries/new?entry_type=test
How do I link this up to my controller and my form?
4 Answers
Brandon Barrette
20,485 PointsSo two things need to happen here:
For the new action, you have it right (although I've posted the shortcut below):
def new
@entry = Entry.new(name: params[:name])
end
For the form, I'm not sure what you have, I assume you are trying to save a new entry.
<%= form_for(@entry) do |f| %>
<%= f.hidden_field :name, params[:name] %>
#other stuff that's omitted
<% end %>
Then in your create method in your controller, you do need to permit the name attribute if you are making it part of the entry, otherwise merge it to the entry_params (this is definitely not recommended for security reasons):
def create
@entry = Entry.new(entry_params.merge(name: params[:name]))
if @entry.save
go here
else
render action: 'new'
end
end
private
def entry_params
params.require(:entry).permit(:name)
end
I think what might be going wrong is the name attribute is not being recognized as being part of entry. So it's not making it through strong parameters. Could you post your entire form?
EDIT Now seeing your post above, notice that "name" is not part of entry. So it's not making it through. I've edited my answer above.
Ethan Lowry
Courses Plus Student 7,323 PointsHi Jon,
At any time in your Rails controller you can access any params passed in with the last request (whether they're embedded in the URL via GET request, or via a POST request such as from a submitted form) using the params
hash. So, for your example above you might use something like this to get the value passed in:
type = params["entry_type"]
Of course, you can then do whatever you wish with this value.
Other than that just make sure you have created a correct controller action such as index, show, etc. and that it's been hooked up in your routes
file. (If you generated your controllers etc. via rails generate
then this should have been done for you.)
Hope that helps and good luck.
Jon Moss
1,150 PointsSo like this:
def new
@entry = current_user.entries.build
@entry.type = params["entry_type"]
end
Ethan Lowry
Courses Plus Student 7,323 PointsJon Moss yep, that should work as far as I can see.
Jon Moss
1,150 PointsTo sum up... (Bear with me, I changed the name of the attribute)
(controller)
def new
@entry = Entry.new
@entry.name = params["name"]
end
(form)
<%= hidden_field_tag :name, params[:name] %>
However, this doesn't save and the attribute ends up blank, but when I view the HTML source for /entries/new?name=test
<input id="name" name="name" type="hidden" value="test" />
Suggestions
J Scott Erickson
11,883 PointsEthan's answer is correct about accessing params. However you're missing one step in the chain of accessing params in rails. You will want to create a 'whitelist' of params. previous versions on rails used attr_accessor. However Rails is now using 'Strong params', this allows you to filter the input coming into the controller and keep out unwanted attributes that could be harmful or unnecessary.
class MyClassController < ApplicationController
def new
... code here
end
def create
... code here
end
def show
@my_instance = MyClass.find(my_class_params[:id])
end
.
.
private
def my_class_params #this can really be whatever you want to call it
params.require(:my_class).permit(:attribute, :attribute, :attribute)
end
end
Jon Moss
1,150 PointsWould I still need to do that if I'm only using the URL params for the new action?
Ethan Lowry
Courses Plus Student 7,323 PointsGood point, but I believe you only need to do this when the params are being passed in to either update
or create
an instance of the model - if you're just using the params for your own original use here (using it to help in setting up the new
form, rather than in the create
action itself) then you probably don't need to.
J Scott Erickson
11,883 PointsIf you are just using it in the new action you actually don't need the params at all. (depending.... if you're presetting some of your params in your new record then maybe you will need to give it some attributes prior to displaying the new view.
def new
@my_instance = MyClass.new
end
Will work just fine, and doesn't require you to grab any params. if however you are redirect during the create method and want to be able to show errors before a save then:
def create
@my_instance = MyClass.new(my_class_params)
if @my_instance.save
render @my_instance # the show path of this model if that how you're directing
else
render action: 'new' # renders the new.html.erb view using the @my_instance variable that has the params
# this allows you to show the errors specific to the object based on the params supplied in the view
end
end
Jon Moss
1,150 PointsYep, the idea was that the type would be preset through the URL
J Scott Erickson
11,883 PointsIs it a sub-class? or just a class that has different types based on user input? Basically, when the model is called in the new view will you know what 'type' it will be, or is that info furnished by the user?
Jon Moss
1,150 PointsYou would know what type it would be via the URL, no form input.
Ex: domain.com/entries/new?entry_type=test
Ethan Lowry
Courses Plus Student 7,323 PointsI think we've gotten off course a bit here - do you actually have a failure or error with what you're trying to do right now? It sounds like you understand what's up.
Jon Moss
1,150 PointsTo sum up... (Bear with me, I changed the name of the attribute)
(controller)
def new
@entry = Entry.new
@entry.name = params["name"]
end
(form)
<%= hidden_field_tag :name, params[:name] %>
However, this doesn't save and the attribute ends up blank, but when I view the HTML source for /entries/new?name=test
<input id="name" name="name" type="hidden" value="test" />
Suggestions?
Ethan Lowry
Courses Plus Student 7,323 PointsJon Moss All right, interesting. Could you check the development server log in your terminal, immediately after submitting that form?
Just scroll up it for a bit and keep an eye out for anything interesting or out of place looking, particularly anything that might mention parameters, if there is anything like that.
Jon Moss
1,150 PointsTerminal: (keep in mind I also have a caption:string attribute which is not typed in via params)
Started GET "/entries/new?name=asdf1" for 127.0.0.1 at 2014-10-04 20:32:40 -0400
Processing by EntriesController#new as HTML
Parameters: {"name"=>"asdf1"}
Rendered entries/_form.html.erb (2.3ms)
Rendered entries/new.html.erb within layouts/application (10.4ms)
Completed 200 OK in 133ms (Views: 131.4ms | ActiveRecord: 0.0ms)
Started POST "/entries" for 127.0.0.1 at 2014-10-04 20:32:44 -0400
Processing by EntriesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Bde6nEjdGJFTg6Xt39TIzZRlNanvjsKLKWYDCHMsOSc=", "name"=>"asdf1", "entry"=>{"caption"=>"asdf"}, "commit"=>"Create Entry"}
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "entries" ("caption", "created_at", "updated_at") VALUES (?, ?, ?) [["caption", "asdf"], ["created_at", "2014-10-05 00:32:44.072674"], ["updated_at", "2014-10-05 00:32:44.072674"]]
(89.8ms) commit transaction
Redirected to http://localhost:3000/entries/4
Completed 302 Found in 94ms (ActiveRecord: 90.2ms)
Jared Kimball
6,896 PointsBoth Ethan and J have good answers. I believe you only need to use strong parameters when you are going to be making an HTTP request for POST, PUT/PATCH, or DELETE. This is because you are actually trying to manipulate or change information in a database instead of just GETting data back from it. So if you were building a search field or just getting a list of Entry.where(entry_type: "something").all then you're fine without using strong params. I see above you are creating a new action in your controller. If you'll be using Rails' create or update method, then yeah, just simply pass it through your strong params.
Jon Moss
1,150 PointsJon Moss
1,150 PointsGetting error:
Controller:
Form field for this:
<%= hidden_field_tag :name, params[:name] %>