Skip to main content
Rails Concepts:

The Params Hash

62

Episode 4 · July 2, 2014

A glimpse into the "magic" behind the params hash and the various ways it gets populated

Basics


Transcripts

The params hash in your Rails application is a concept that a lot of people have trouble with, so I'm going to talk about it and try to debunk the magic that sort of happens with it, because it's actually really simple.

The params hash is a collection of data that has come through your application in that request. This data might come from various places, we might submit a form and that sends over some data, your URL might contain a chunk of the URL that has some data that you want, and you also might have at the end of the URL "GET request parameters", so those are the common ways to get data into the params hash, and Rails just knows to collect those things and put it in there nicely for you to work with. So let's talk about how we go about doing that.

The simplest thing that we can take a look at is GET request parameters, in our config/routes.rb we'll delete the comments and add a simple route

    get "/blog", to: "blog#index"

I don't have a blog controller yet, or an index action, so we'll need to create that real quick, so let's do that

app/controllers/blog_controller.rb

class BlogController < ApplicationController
    def index 
    end
end 

app/views/blog/index.html.erb

<h1>Blog!</h1>

So when we visit our /blog route, when we visit our Rails application we will see that file. So we'll run our Rails server, and then open up in our browser, localhost:3000/blog and this will show us the blog path.

So we got the view that we created, and we're able to see it and you can see in our logs that we have "Started GET /blog", that's all working correctly. Now a get request parameter is what you might have seen before in like the Google URLs and different things around the web where there's a question mark and then there is a variable, something like test= 1, the page request is actually localhost:3000/blog but then this (?test=1) extra information is our query parameters. So this query parameters basically give more extra data, it might use this to render your page, you might not, you can totally ignore it, just like this page did. It didn't blow up or anything, because it can ignore this information unless you want to use it. If you look at your Rails logs again, now we have

Parameters: {"test"=>1}

and in our previous request, we didn't have any parameters, so Rails is taking these parameters and pulling them out. Now when it writes the word parameters and gives you this hash, this is actually exactly what's in your params hash. So when you go into your blog_controller.rb, if you have the word params in your action, that's accessing this variable, so they show you exactly what's there so that you can work with it. This is not magic by any means, when you say:

def index 
    params[:test]
end 

it's going to pull the string of "1" out, and if we say

def index 
    @test = params[:test]
end

we can say @test and pass this into our view, we can go to blog/index.html.erb and print out:

<h1>Blog!</h1>

<%= @test %> 

and when we show our page, we can see that it's "1". If we change the URL to "2", it changes, so what this is doing, is it's reading from the params hash the test variable and pulling out the value for that key, the test key, and then we're just going to save it in a variable so you can use the square brackets and a symbol to math the name and that will return the correct value. So it's really really simple for GET parameters to be doing that, to pass in the params hash and there you go, you have data. So this is really useful when you wan to say /blog?page=3, and so on. This allows you to filter out what the page displays, you're not really changing what this page does, but you might filter out how this page works. So this are really good for filters, and that is a GET request parameter, so the next one we'll take a look at is the route parameters. If we go into our routes.rb file and we add a new route and we say `get "/blog/:id", we put the colon to indicate Rails that the part that's typed into the URL should be taken and saved into the params hash as the ID name.

So when we say we want to view individual blog posts, so we have get "/blog/:id", to: "blog#show", and with this URL, we can take that stuff that's passed in that section after blog, save it to the ID key inside of the params hash, and then go look it up. So if we go into our blog_controller.rb and we add a show and let's just not actually do a lookup in the database, let's just make this very simple, so we'll have:

app/views/blog/show.htm.erb

<h1>Here's my blog post!</h1>

When we visit "/blog/(insert anything here)", you can put in numbers, you could put in words, you name it, they will get passed in to your Rails application, so now you can see that the parameters have the id key and value and ID now is "blabla", and when we passed in "1", it was "1", so you can use this basically to say in this case, we don't want the user to put in "id=1", we actually want the URL to look prettier, so we want it to be more purposeful and this tells the browser and google and other things that this is a different page, there's something else that they're looking at for every one of these, and when you add a query parameter on there, like "page=1", the search engine knows that you're still on the blog like the index page, but you're just looking at a few other different posts on that page, so it's still generally the same page, they've just decided to split it up, and when you do separate URL's, these signify that they're separate pages and they're completely different, so this is good for us for when we pass in the ID or the name of the blog post we can just do a lookup in our database with ActiveRecord, pull that out and display it on the page, so you can edit those, or access those rather in your blog controller in the exact same way, so if you want params[:id], which you'll see often in your Rails examples, if you have a blog post model, which I haven't created one, you could find one though, doing this, and that would just load up your params id number into the .find method and that will go look up the database record based upon the number in the URL, so by default they use numbers, eventually you'll probably change them over to using words and looking them up by slugs, but we can see this just by naming a variable called ID and an instance variable, and then we can print it out here on the page as well just like we did before with tests. So in this case, we can see the number "1", we can change this to "asdf", and so on.

Now here's something interesting, we can have multiple ones, so you can have test in here as well, and you can have the test query parameter in there too, you can have @test = 1, and if we decide to print out test, we can see both of them. So both are filtering in, Rails knows that if they come from a query parameter, we should put that in, and if they come in from a route parameter, we should put those into the params hash as well. And you can see the parameters are now {test => 1, id => "asdf"}, so they're both being funneled into that which is awesome.

The last way we get data into our application params is by submitting data through some sort of other requests. So we've talked about get requests so far, and you can put stuff in the URL's, and that's pretty much how you get data into a GET request. Now POST, PATCH, UPDATE and DELETE requests are all designed so that you submit data to the server and they will take that and automatically put it into the params hash. Rails knows to basically use these three things.

We're going to use an example of a new blog post, so we're going to say that if you post to the blog URL, we're going to go to the "blog#create" action, so this should create a blog post, or at least that is our intention. What we need now is to create a forum that submits a POST request to this URL, and I'm going to do this on the blog/index.html.erb, so we're just going to create a regular form tag here:

<h1>Blog!</h1>

<%= @test %> 

<%= form_tag blog_path do %> 
<div>
    <%= text_field_tag :title %> 
</div>
<div>
    <%= text_area_tag :body %>
</div>
    <%= submit_tag %>
<% end %> 

If we refresh the blog page now we have a title field and a body field, I didn't put labels on it because it's simple and we're just submitting data over to the server, so if we actually just call these "Post Title" and "Post body", so when we create this post, or submit the form, it's going to send a post request and we're going to get "unknown action". First thing we need to do is go into the controllers/blog_controller.rb, create an action called "create",

def create 
    redirect_to action: :index 
end 

It's not going to do anything, we're going to be able to see the request in the logs, when we resubmit it, so we'll come back to the same page, and we'll be able to look at the logs to see what's happened. "Started POST "/blog"" is our POST request to the blog path, and it went there, it created the POST request, it submitted data just like we set it to, and when we created the form here, and I said title and body, I made those up, so I wanted to have a params value title and a params value of body and that's what it did. You just dive these names, so ideally with Rails you make these names match what's in your database models, so that it can automatically match them up and you don't have to do it yourself, but for this example, we're just submitting over data and you can see now that the names are going to affect how it shows up in the params hash. So if we modified :title for :post_title, we can see that if we were to refresh this page and put in different text, in our logs we can see that this time post_title comes across, so you are free to name these anything you want, the utf8 and authenticity_token are automatically included with Rails form tags, and they allow it to force your browser into using utf-8, because they use a check mark utf-8 character and then the authenticity token is to allow CSRF protection, basically to keep your forms a little safer. So the ones that we're interested in are the ones we submitted, and the commit here is actually the text for the button that we created ("Create Post"), so if you actually need that information, you can see that the value of a commit button or submit button is going to be the text that is displayed, so that allows you to actually do stuff based upon the button that is submitted if you need it, it's unlikely you do, but it's there in case.

Submitting data in a form is very simple, it's very similar to what the other ID URL things, and the query parameters are, so you're just naming things whatever you want to name them, submitting them to the server, and Rails knows those locations to pull them out, and then cleanly organize them in your params hash. So every time that a request comes over and you're missing data or something, check what params are listed here so that you can see that it really did come over. Maybe you missed it, or maybe it's ignoring it after it came over. So it really came over but you did something wrong in your code. The way that the params hash works is actually very simple, there's the three typical methods of data coming into your server, and that just aggregates all of them together, so generally try not to duplicate names, you don't want to have body in the URL and in your POST form, so you will probably get something overridden, and that will be bad, so don't duplicate the names, but aside from that, there's really nothing to worry about. This is very simple and you can access all of these variables really easily.

Transcript written by Miguel

Loading...

Subscribe to the newsletter

Join 18,000+ developers who get early access to new screencasts, articles, guides, updates, and more.

By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

More of a social being? We're also on Twitter and YouTube.