DRY Land! Keeping It DRY on Rails

Angelo Urtula
6 min readMay 28, 2021

For this mod’s structured project, I decided to create a “Choir Scheduler” with Ruby on Rails. With this app, choir leaders can set up 1-on-1 practice times and choir members can sign up for those practice times on a first come first serve basis! Ruby on Rails is like a more powerful version of Sinatra, the framework used in our last mod’s structured project. It’s much more powerful such that terminal commands can almost make an entire app with just a few commands. For example, running something like ‘rails generate scaffold’ can build out most of your app with just a few keystrokes! Of course, using such a command was prohibited for this project, but I just wanted to make a point of how amazing Ruby on Rails can be. What Rails can’t do with its generators though is keep your code DRY (don’t repeat yourself)! Keeping code DRY can help you maintain your code more easily in the future; for example, if you needed to change some code that’s repeated throughout your app, you would need to change it in multiple areas, and you may even miss one of the repeated lines you needed to change! Instead, if you refactored that repeated code with a helper method, you would only need to change it in one spot: the helper method itself. I feel that with the ease of making apps with Rails, the importance of keeping your code DRY can be forgotten, so I wanted to highlight areas of my project where I was able to keep my code DRY through refactoring with helpers and partials.

The Controller:
Repeated code can be found between methods in the same controller, with an example being between the “show” and “edit” methods. Although the repeated code in this example is only one line of code, it’s still an opportunity to create a helper method that can help keep our code DRY!

Lines 19, 27, and 36 all have the same line of code: a method named “find_choir_member”. This method is self explanatory, as it passes an id parameter through the .find method of the ChoirMember model. After doing so, it then sets that found choir member to the variable @choir_member, which is then available for use in the views for the corresponding method. Another example of keeping code DRY can be seen on line 28 with the helper method “current_login”. Unlike the previous example, this one has more than one line of code, as it contains a few conditionals that check to see who is currently logged in.

With certain methods in our controllers, such as edit and destroy, these methods should only be available to the users that own these objects. That being said, these methods should all have code that checks to make sure the currently logged in user is the same as the user that owns the object in question. In order to not repeat the same code over and over, it helps to have helper methods, that does the checking for us! For that purpose, Rails allows us to add and organize our helper methods in the helpers folder, with the above picture being an example of a helper.rb file. Our sessions_helper.rb file handles checking if someone is logged in and who that current user is. We can then make these methods available to the rest of our controllers and views by adding “include SessionsHelper” in our ApplicationController class!

The Models:
In some cases, your models may be similar to each other in that they may have some of the same attributes. A few examples can be: name, email, phone number, and the list can go on and on. When attempting to create new objects, in order to keep “bad data” to a minimum in our database, we like to run these attributes given by the user through validations. As one could imagine, if different models have some of the same attributes, then one could guess that the validations would look the same as well, which sounds like another opportunity to keep our code DRY! Fortunately, in this project, both choir members and choir leaders share much of the same attributes, and thus share many of the same validations. So how do we go about refactoring those validations? First we would create a “shared_validations.rb” file in our models/concerns. In that file, we would then declare a module SharedValidations and in that module include all of the shared validations in the ChoirMember model and ChoirLeader model.

This cuts down on about 5 lines of code that would’ve otherwise been repeated in our two models! In order to access these validations, we would then have to add the line “include SharedValidations” to both our ChoirMember model and our ChoirLeader model.

The Views:
If our models share the same attributes, then we can guess that their corresponding views may look similar as well. Again, this sounds like another great opportunity to use the tools at our disposal to make our code DRY! This is where partials come in handy, partials with locals to be exact with our app. Partials take repeated code in views and keeps them to one file that then can be called upon in the view you want with the line <%= render ‘name_of_partial_file’ %>. However, in the example of “new” and “edit” views that use the form_for tag, it’s then necessary to make use of partials with locals in order for our code to work properly!

Take for example this “_form.html.erb” file (the underscore in front indicates that this is a partial). There appears to be a variable or method “f” that is not referenced anywhere in the code! Much like our initial observation, if we attempt to use this partial with the normal <%= render ‘form %> line, our code would not be able to read this properly and we would get hit with a nomethod error. Even if the render line was sandwiched between a form_for tag and an end, we would still end up with the same error! Again, this is where the partials with locals kicks in and we get something that looks like this:

The use of the locals here tells our code that the “f” in our partial is the “f” being referenced to in our form_for tag! Now that the connection has been made, we can successfully render all of the text fields in our ‘_form.html.erb” file when we visit our edit view for choir leaders! Furthermore, although our form partial is located in our choir leader views folder, we can access that same partial in our choir member new and edit views the same way as in the previous example with one addition to our render line. The line would then look like: <%= render partial: ‘choir_leaders/form’, locals: {f: f} %> to indicate that the partial we are attempting to render is located in a different folder.

--

--