A helper method is used to perform a particular repetitive task common across multiple classes. They help us stay committed to upholding the DRY principle. Helper methods are really handy and can help minimize errors in our code by having the logic in one place and let them handle just one particular task and handles it very well.
Transitioning from HTML and CSS to Ruby curriculum to SQL and now Ruby on Rails has not just been amazing for me. I have been able to leave remarkable footprints of standard projects as I move through each curriculum. Tic-tac-toe game, Ruby linter, Full-flesh blog app, Twitter clone, and many more counting, you should see my Github page, make sure you like the projects 😃. Thanks to Microverse, a global school for remote software developers where students learn through remote pair programming.
Okay, back to our main focus rails view helpers, by now you know what helpers in the general perspective.
Just in case you forgot,
“Rails has an application directory called app/ with three subdirectories: models, views, and controllers. This is the model-view-controller (MVC) architectural pattern, which enforces a separation between business logic from the input and presentation logic associated with a graphical user interface (GUI).”
From the above definition, your views should stay a presenter, there should be absolutely NO logic in views. Hmm! okay, Uduak what does that even mean?
An example will suffice, the code below is a bad practice, it displays ‘Create Post’ if the user is signed in and displays “Sign in” if he/she is not. Now that’s logic inside our index.html.erb file.
...
<h3>Recent Posts
<% if user_signed_in? %>
<span class="float-right btn btn-outline-secondary">
<%= link_to "Create Post", new_post_path %></span>
<% else %>
<span class="float-right btn btn-outline-secondary">
<%= link_to "Sign in", user_session_path %></span>
<% end %>
</h3>
...
When we create our controllers, rails automatically generate the corresponding folders for us, example the new action inside the posts_controller file will automatically look out for new.html.erb inside apps/views/posts
. As you can see in the figure, posts_helper.rb
was created for us on this same vein, should there be any logic we want to display in our views corresponding to the apps/views/posts
directory.
Let’s see what the correct implementation will look like.
...
<h3>Recent Posts
<%= create_post_btn %>
</h3>
...
A lot cleaner, isn’t it? You get the hang of it. The create_post_btn
becomes our helper method that does just one thing, generates a create post button on the view if the user is signed in, note that you can give any method name of your choice.
Inside our posts_helper.rb
file we will define our method.
module PostsHelper
def create_post_btn
out = ''
if user_signed_in?
out << link_to('Create Post', new_post_path, class: 'float-right mr-2 btn btn-outline-secondary')
end
out.html_safe
end
end
How convenient, separating logic out of your view. It’s the pattern of “Separation of Concerns”. What concerns the model, belongs to the model, likewise what concerns controllers, belongs to controllers. So should the view.
Rendering Partials Via Helpers
Sometimes, the logic might involve rendering more than one or two lines of HTML codes. The snippet below displays a block of HTML codes if there exists an event created by that user. Here I used that same line of code on the events page also to display a list of events as well as both past and upcoming events.
...
def created_events(user, name, events, title)
render partial: name, locals: { obj: events, title: title } if user.events.size.positive?
end
...
Here is what the partial looks like
<% obj.each do |event| %>
<div class="col-sm-3 mb-2">
<div class="card">
...
And the code below show’s how the helper method is called from the view file.
...
<%= created_events(@user, 'users/events', @user.events, 'List of created events') %>
...
Rails view helpers will help you avoid the temptation of embedding logic in your views. I hope you found this both an enjoyable and insightful read. Please comment and share.