Introduction
While working with Ruby on Rails I have encountered a couple tedious things. On my first project in which I was learning Active Record query methods. I was writing a lot of these query methods in erb and couldn't help but think there was a simpler way.
Problem
I was attempting to render names of different models linked through a join table.
So my code looked something like:
<!-- app/views/actor/show.html.erb -->
<%@characters.each{ |character| %>
<tr>
<td><%= Movie.where({:id => character.movie_id})at(0).title %></td>
<td><%= Movie.where({:id => character.movie_id})at(0).year %></td>
<td><%= Director.where({:id => Movie.where({:id=> character.movie_id}).at(0).director_id}).a(0).name %></td>
<td><%= character.name %></td>
<td><a href="/movies/<%= character.movie_id%>">Show details</a></td>
</tr>
<% } %>
A minimum of 30 minutes were wasted writing that loop in order to avoid typos. That is too long. Luckily, I never have to do that again because of Association Accessors.
Solution
Association Accessors are to models like attribute accessors are to Classes.
On the third table data tag, you can see we are trying to get the name of the director using the movie_id value given by the character.
So we need to do two things:
- Create a director getter inside the Movie model
- Create a characters getter inside the Actor model
In our Movie model we need to return the director:
# app/models/movie.rb
class Movie < ApplicationRecord
def director
my_director_id = self.director_id
the_director = Director.where({:id => my_director_id}).at(0)
return the_director
end
end
Here we are creating a method that returns the director when called. So if we have the director_id we can call the method and chain the key of the value we want.
In our Actor model we need to return the Characters:
class Actor < ApplicationRecord
def characters
my_actor_id = self.id
characters = Character.where({:actor_id => my_actor_id})
return characters
end
end
We now created a method that returns the characters when called getting the id of the actor, so we can make our code more legible by using those methods.
<!-- app/views/actor/show.html.erb -->
<% @the_actor.characters.each do |a_character| %>
<% the_movie = a_character.movie %>
<tr>
<td><%= the_movie.title %></td>
<td><%= the_movie.year %></td>
<td><%= the_movie.director.name %></td>
<td><%= a_character.name %></td>
<td><a href="/movies/<%= the_movie.id %>"> Show details</a></td>
</tr>
<% end %>
Conclusion
You should be using association accessors when creating your models. They take time to create but they will save you time as your project scales.
Top comments (0)