00:00:24.339
Greetings and felicitations! My name is Tara Scherner De La Fuente. I have been a junior engineer at LivingSocial for one year as of last week. Thank you! I've been a professional engineer for one year, and I'm still short, but I've been short for much longer than I've been an engineer. You can find me on Twitter at @media_remedial. I would love for you to visit my blog, Goat User Stories, where I've been tweeting for a little while now. Earlier today, my girlfriend Hazel helped me post a Rocky Mountain Ruby story, so please check it out. In any case, my talk today is called "I Like My Params Like I Like My Coffee," which is strong, in case anybody was wondering. Although I had to change about 25 models and controllers in the application I work on, today I'm just going to talk about a few less documented tips I've gathered from working on one model and its thousand-plus line controller. Believe me, you wouldn't want to get into that code!
00:01:12.750
I'm also going to share a months-long mystery that prevented strong parameters from working effectively on that controller, and how the solution to that mystery turned out to be intricately tied to my coffee theme. This was not planned, as the mystery existed even when my talk was accepted, but it's been solved now, so stick around! Just a quick overview of strong parameters: we were using the strong parameters gem because we were on Rails 3.0 and eventually moved to Rails 3.2. With that gem installed, you’ll need to include a specific line in any model you want to apply strong parameters to. Then on the controller, this is the basic outline of what your new private method will use to implement these strong parameters.
00:02:01.320
Essentially, parameters that require your model are followed by `.permit` and whatever attributes you would like to allow. The idea of strong parameters is to prevent users from injecting inappropriate data into your application. It’s crucial to replace the params model bracket with your new method in any create or update actions. This is just a quick overview in case you’re unfamiliar with this concept. This is a screenshot of the coffee controller. It’s important to note that this is not the controller itself, but the attributes. All of the attributes listed here are directly on the coffee model, and starting from a certain point, you also have nested parameters that could span four or five slides if I were to show them all. You can imagine why it took a while to set all of these up.
00:03:40.620
Initially, to figure out which attributes needed to be included, I alphabetized all of them directly on the model and in the attributes section of the controller. It was a cumbersome process, but it allowed me to compare the raw parameters and make sure I had all the attributes correctly placed. I figured this would help future developers easily understand where to add or remove parameters. After I submitted that pull request, I had been applying strong parameters to other models and controllers for a couple of months. However, the implementation process did not go smoothly at all. One key takeaway I learned from this experience is to start by permitting all attributes when dealing with complex models and controllers. You can do this with a `permit!` method, which allows all your attributes and gets your code working everywhere else, regardless of whether the attribute list is correct.
00:04:29.580
After that, you can refine your attribute list. If you’re working on a thousand-plus line controller and it's an internal application, the risk might be low enough to take this approach. The next day, I managed to finally get strong parameters functioning on the coffee controller. It was a huge relief! I can’t believe it happened so quickly. Now here are some additional, lesser-known things I learned while working on that project. There are times when your private method lists strong parameters, including nested attributes, and you might still need to permit them separately within a method. In our case, this was the create method. Just like I used `permit!` on the private method, I also had to use it within the create method. This is something to watch out for as you may need to specify parameters again separately in a method.
00:06:40.070
Next, I learned a total newbie mistake: strong parameters are designed to prevent users from injecting code, but I mistakenly replaced all params brackets with my new method at the beginning of my learning curve. Strong parameters do not prevent the deletion of attributes—they simply don’t care about it. This misunderstanding caused us to think sometimes deleted attributes were still present; however, strong parameters don’t delete anything for you. As for some tests, we had API controllers and one other miscellaneous controller. When we were running certain updates, sometimes we felt we needed to pass in an empty hash for the object but would understandably receive a 400 error instead of a 204 no content response. It's vital to remember that with strong parameters, if you receive a 400 error, it's not necessarily an error; it's just that the expected parameters aren’t included in the request.
00:08:14.360
To avoid this, you should always include an actual attribute in your hash—you can’t just put any random value like ‘foo’ or ‘bar’. The tips I’ve learned so far are significant, but I did struggle with the coffee controller significantly during this process. I ran into many errors related to nested attributes, specifically with those attributes which included the phrase ‘additional attributes attributes.’ No joke! It was related to the depth of the parameters we were working with; it was challenging. I'd read the raw parameters and obsessesively reviewed the nesting, spending days comparing and ensuring everything was correctly placed. I was sure that the issue lay within the nesting, as it could easily complicate matters.
00:10:01.900
Some might wonder why I hadn’t utilized a certain gem that helps identify attribute discrepancies. The reason being, at that time, one of our lead software engineers was working on that gem. We discussed our experiences, and they confirmed that the gem was still being developed. I shared my terrifying raw parameters hash with him, and he adapted it to make his gem, which ended up being cleverly named after my strong emoji meme: ‘strong like bull.’ It has over 300 downloads now and seems to be beneficial for others. He also published an article on the topic on the LivingSocial tech blog that I highly recommend you check out, even if you’re not interested in the gem—it provides concise information regarding strong parameters and how they function. This brings me to another tip: to tackle the challenge of deeply nested parameters, I created a dedicated `params` file in our `lib` folder, straight-up constants with arrays of the parameters, ordered alphabetically. It allowed for easier management and readability.
00:12:38.965
After building all models and controllers, even with a `permit!` method on the coffee controller, I was then able to fix things quickly. I created a test that would specifically check for the run span error I kept encountering. The version that included the `permit!` would pass, while the version with my adjusted attributes that visually appeared correct would not work. Fortunately, in November at RubyConf, I finally got to collaborate with our lead engineer. He graciously offered to pair with me, and we worked on the project for two months, meeting every so often to make observations and steps forward. Our notes were often punctuated with frustrations, which culminated after several meetings when we finally noticed that the raw parameters differed versus the specifically designated attributes.
00:16:30.340
I recalled learning during a Ruby book club about the importance of order. I realized that we were overloading an active record method, which I hadn’t grasped initially. While I had my raw parameters compared against my alphabetized code base, Dan pointed out the differences that played a vital role in the success of strong parameters. After months of struggling, I pushed through the distinction of placing the time zone from its alphabetical position to right in the front of the list. After that minor adjustment, when we reran the tests, we received a ‘pass’ for the first time in ages! This was a fantastic breakthrough! So just to quickly recap: whitelisting all the attributes before listing them individually can help you focus on the necessary code changes required. Nested parameters might need to be permitted again within a method; and remember, there’s no deleting in strong parameters. Additionally, avoid using empty object hashes in tests or you risk running into those dreaded 400 errors. Finally, realize how crucial order is; successful pairing can lead to learning opportunities for all. Junior developers often possess an enthusiasm for tedious tasks, and they can be invaluable so put them to good use. Thank you for being my first tech audience; I really appreciate it!