- Read Tutorial
- Watch Guide Video
Moving down our list of tasks we can see the last one here is called "working with strong parameters." Technically, we've been working with strong parameters ever since we built our first scaffold. I opened up the blogs controller and if you come all the way down to the bottom you can see this nice little method called blogs param.
If you open up the portfolio controller and scroll down you can see we didn't implement the method but we're going to do that in this guide. Additionally, we are going to see how we can refactor it because right now we have these params require portfolio and all of our permissions here.
Before we get into that I want to talk about what this is actually doing. Our comment here, this is what rails provide, is actually kind of helpful and says "Never trust parameters from the scary internet only allow the whitelist through." That tells us that what we're essentially doing here and I love the method names, permit says very clearly these are the items that we are permitting inside of our forms. This is what the form is going to be able to pass through to the controller.
If a hacker who passed in some other form element and that's something that from a hacking perspective is actually very easy to do then they might be able to throw some malicious code on the server and they could have a pretty nasty type of hack on your system. Whitelisting is definitely a good idea.
With that being said I want to show you that this is not required it's simply something that is recommended. I'm going to come down to config
application.rb remember this is our route application this is where it all starts from a code perspective. You can see the name is Devcamp portfolio which is the name of our application. When the application gets created this is essentially where it all starts. If we want to set any kind of settings or anything like that usually we're going to put that in the initializers, however, right now because we're not actually going to implement this I'm just going to walk you through it so you can see what it does. I'm going to put it here.
The code to put here is
config.action_controller.permit_all_paramters = true and action controller is something you see right up here. This is a mini framework inside of rails, this is how we get all of our cool new types of controller methods and things like that. We're saying config and action controller permit all parameters equals true. This is going to override the defaults. In other words, before we had to have this permit method here and if we did not have the permit with this whitelist the system would throw an error like we saw it would not allow those items in and gives a little error with unpermitted parameters.
This is exactly what we implemented when we built our devise whitelist. Usually, it's in a controller but because the devise is really its own entity, we had to create a module for it. I think it's logical to have the whitelist for a specific controller inside of that controller.
If I delete this and remove those parameters this is now possible because of what we did here with this config action controller.
When we say permit all parameters
and set this to true, it's going to override the requirement. We don't have to go and fix and change the other items. It's perfectly fine to still pass the whitelist in. This is just a way of saying as an application I'm not going to require this.
So let's switch to the app itself, if I click new blog and come here to create a new blog entry create. Everything works even though we turned those off.
Here it took in an id of this value and this is something that's also kind of important to know, see what the parameters look right here this is the param it's passing because of our slug and with our friendly I.D. If you look up here this shows the the full set of the parameters. We have the body we have the blog the title, everything like that.
That is how you can do that if you want to for some reason turn it off. The times where I've turned this off are so rare I'm having a hard time thinking of a use case on when this happened. I think at one point there was an application that I built that had to be incredibly flexible and gave the ability to create things like custom fields and custom form elements on the fly. In that case, I turned off the whitelist and it was an admin site so in terms of hacker internally trying to do something was much less. I don't really recommend turning this off unless you have a very special reason to.
I'm going to delete everything there and come back and put those items in. The last thing we're going to do is let's refactor our code to have this set up in our portfolio controller. I do not like how right now we have a lot of duplicate code. You can see that we have params require a portfolio. Then we have their permit statements.
Think of a few reasons why this is bad, say that we go in we add something else to our programs here. So say that when we get to the point we're adding images not only would we have to go and add the parameters in one spot. We'd also have to do it here in the second spot for update.
The more times you have duplicate code the more chance you're going to forget to make a change in one spot and then you're going to have some weird bugs popping up. So let's get rid of all of that code. Notice we have these portfolio items here, when we built this out and we built the three times portfolio item see how we actually have something different in our create and update already? That's kind of on purpose because we haven't created our form and shared it.
I'm going to come into create because this is the one that's the most up to date with our attributes. Let's just create the method here.
@portfolio_item = Portfolio.new(portfolios_params)
We can do the same thing in the update action right here. This will be portfolio params. Now all we have to do is actually create the method.
Coming down to the very bottom the file be below destroy but above the final end statement for the class, I'm going to type out private, if you are relatively new to ruby, this means it's a way of organizing our methods and it communicates that the methods that we're creating here are only to be used inside of this call.
So all of these other methods can be called from other modules so you might call the angular action or the new action or create. So those are fine to call from outside the class. However, this one is only to be used inside of this specific class, which makes perfect sense. Imagine our portfolio params, there's not really any need for any other class to use these. This whitelist is specific only here.
So we are going to put this inside, it's going to be params which we know based off of all of the various things remember when we grabbed the params like "q" that's the full set of params that we have access to when a form is being submitted. The params are filled with items that we saw here in the terminal.
So here we have params such as the body and the blog title but for portfolio, we're going to say params.require portfolio and then the full list of permit items. Now one little point of style here usually when you start to get a really long list it's considered a bad practice to keep them all on one line.
I like to put them on their own lines, this makes it much easier to add to them later on.
If I do this now what we can do is whenever we want to add a new one, say that we add some like image. It makes it much easier to read, also another reason is on sites like GitHub, where other people might be looking at your code, if you have a line of code that is really long it can actually extend over the page and it makes it harder to read your code.
Let's test this out, let me first make sure we have portfolio items, make sure I don't have any spelling mistakes. Let's go and verify that our refactor worked.
If I go to portfolios and click on Create a new item I should be able to put all of this in here, make sure everything is working. Hit create portfolio and it looks like all of that worked
Now we have better-looking code here for our create and for our update actions and the cool thing is now if we add a new item we only have to make the change in one place. This follows the very important rule of not repeating your code it's one of the most foundational rules of development.
- git status
- git add .
- git commit -m "Refactored strong params for portfolio items."
- git push origin controller
We have close this out and technically we have closed out this feature. So and I did forget to start once again but since we're the only ones looking at that that's fine. This is all done. We have one more item in our deep dive and this is going to be one of those rare deep dives where we continue working on the portfolio project because there is a feature that I want to build called the null object pattern.
I know that sounds weird. I know it sounds a little intimidating. Don't worry. It's simply a way of being able to refactor the way our sessions work in regards to guest users which is your portfolio so the majority of the people visiting are going to be guests. And so I'm going to show you how we can implement some features that will clean up the way the application works with guest users.