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
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
def product_params params.require(:product).permit(:name, :price_in_dollars, :released_at_text, :category_id, :new_category, :tag_names) end
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
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.
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
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
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.