The GitHub Repo
The Heroku app
I found this episode useful. It showed me that a model’s attribute does not have to be directly on one of the table’s columns. Not only did I learn about virtual attributes, but I also improved on associations, validations, and callbacks.
The virtual attributes were easy enough to understand. You create a setter and getter method named with the desired virtual attribute name. In the episode’s case it was price_in_cents
sort of aliased to price_in_dollars
. Within the method you could change the value of the virtual attribute to match whatever is in the database.
def price_in_dollars
price_in_cents.to_d / 100 if price_in_cents
end
def price_in_dollars=(dollars)
self.price_in_cents = dollars.to_d * 100 if dollars.present?
end
Strftime
This is the first time I used the :strftime method, but it is not too dissimilar to how I have formatted dates within the terminal.
Rails 3 to Rails 4
One thing to note, these videos date back sometime before the current Ruby on Rails 4.0 release, thus I must convert some of the techniques shown in the videos into whatever they translate to in the new version of the framework. An example of this is the use of attr_accessible. Attr_accessible has been incorporated in the the strong parameters update in Rails 4. So instead of
attr_accessible :name, :price_in_dollars, :released_at_text, :category_id, :new_category, :tag_names
You would do the following in the ProductsController
def product_params
params.require(:product).permit(:name, :price_in_dollars, :released_at_text, :category_id, :new_category, :tag_names)
end
Associations
I knew I was a little weak with associations, so when I saw that this project had categories, products, tags, and taggings, I decided to make everything from scratch. I followed along with the schema to create the migrations needed. When creating a has_many
and belongs_to
relationship you always put the parent id onto the child’s table. Example:
class Product < ActiveRecord::Base
belongs_to :category
end
class Category < ActiveRecord::Base
has_many :products
end
The schema would look like this:
create_table "categories", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "products", :force => true do |t|
t.string "name"
t.integer "category_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
This relationship is similar to the taggings, tags, and products relationship. The taggings has the foreign key for both the tags and products. The difference is that products has_many tags through the taggings model.
Validations
I liked how Ryan Bates created his own custom validation method with check_released_at_text
The validation first check if the released_at_text instance variable is present and the time is nil. If it is, then add to the errors
object with a custom error message. If there was an ArgumentError
, then again the errors
object is appended with the custom error message. Creating a custom validation adds more control than if some of the more generic validation methods like presence
or length
.
Callbacks
The callbacks created this episode used before_save
. The reasoning for this is to actually save the instance variable’s values to the database in the correctly formatted form. In the create_category
callback it actually creates a new category record.
def create_category
self.category = Category.create!(name: new_category) if new_category.present?
end
Pluck
The first time I’ve seen the pluck method used. I looked it up and found that tags.pluck(:name)
is a shortcut for tags.map(&:name)
. The goal is to get only a certain attribute from the model.
Those where the noteworthy parts of the episode.