Thursday, December 26, 2013

Why Strings Are Mutable in Ruby

Objects can be either mutable or immutable. Mutable objects are objects whose states can be changed, while immutable objects are objects whose states never change after creation. One important implication of immutable objects are any modification of existing objects results in new objects.

Immutable objects has many desirable properties.

  • Immutable objects are thread-safe. Since any modification of existing objects results in creating new one, there is no need to set up lock to avoid conflicts while multiple threads attempt to access the object at the same time. 
  • Immutable objects make good hash keys, because the value of the hash key should never change. 
  • Immutable objects have higher memory efficiency, because the same object can be pointed to by multiple variables, thus enhancing reusability. 
Why Ruby does not adopt immutable string if it has so many advantages? The reason is it is intuitive to think of string as mutable, because you can do so many operations on a string, concatenation, appending etc. Ruby thus makes string mutable by default at the expense of performance. 

For example, appending on a string didn't creating new string.

> a = 'Hello'
=> "Hello" 
> a.object_id
=> 70161220331780 
> a << ' world!'
=> "Hello world!" 
> a.object_id
=> 70161220331780 # object_id does not change!

Don't confuse the code above with the following code

> a = 'Hello'
=> "Hello" 
> a.object_id
=> 70161220396780 
> a += ' world!'
=> "Hello world!" 
> a.object_id
=> 70161220412700 

As  "+=" creates a new string and then assign it to "a". The old string is not changed. You can make a string as immutable by using the method "freeze". After you freeze a string, an attempt to change it results in RuntimeError.

> a = 'Hello'
 => "Hello" 
> a.freeze
 => "Hello" 
> a << ' world!'
RuntimeError: can't modify frozen String

Why we need "freeze". What if we don't have it. Then we can't use string as hash key in Ruby. Because if you change the value of the string, you can't use the old value to refer to the right position in the hash. Here is how Ruby deal with it. It copies the string, freezes the copy and use the copy as the hash key.

Friday, December 13, 2013

Ruby: load vs require, include vs extend

When it comes to including files within another file, there are two methods we can use, load and require.

Here is a table that gives the differences

loadrequire
file pathabsolute/relativeabsolute/relative
file extensionRequiredOptional
Can load a file multiple times YesNo

The file path and file extension rows are pretty straightforward. The most important difference is the third row, Can load a file multiple times. You can load a file multiple times by using method load, but for require, you can't. That's because The absolute path of the loaded file is added to $LOADED_FEATURES. Every time a new file is going to be required, ruby checks if there is already a same absolute path in $LOADED_FEATURES, and if there is, the file won't be loaded again.

It's easy for beginner to confuse load/require with include/extend. To some extent, these two groups of methods are similar. However, they are used under different context. include and extend are used to adding methods from a module to classes. If you include a module within a  class, all the methods within that module will be added to the class as its instance methods. If you extend a module within a  class, all the methods within that module will be added to the class as its class methods.  See the example below,

module Mod_1
  def hello1
    puts "Hello from Mod_1.\n"
  end
end

module Mod_2
  def hello2
    puts "Hello from Mod_2.\n"
  end
end

class Klass
  include Mod_1
  extend Mod_2
  def hello3
    puts "Hello from Klass.\n"
  end
end

a = Klass.new
a.hello1      
Hello from Mod_1
=> nil 
Klass.hello2
Hello from Mod_2
=> nil
a.hello3
Hello from Klass
=> nil

Tuesday, December 10, 2013

Rails router, route, path, URL, resource routing

When it come to routing, there is a lot of confusing terms. In this blog, I'll try to shed some light on their meanings.

Router
Rails router is just a piece of code that handles HTTP verb and URL combos and dispatch them to a controller's action.

Route
Route is just the mapping from HTTP verb and URL combo to controller's action.
For example
get '/patients/:id', to: 'patients#show'

Path vs URL
Paths and URLs are easy to be confused.
Say we have a users controller, we can have a path and a URL for it, shown below.
Path => /users
URL => http://www.example.com/users
As we can see here, URLs are just paths prefixed with the current host, port and path prefix.

Resource Routing
In Rails, resource routing allows you to quickly declare all of the common routes for a given resourceful controller by using a single line. For example, you have a controller called photos.

resource :photos

By adding this line into our routes.rb file, we creates the following seven routes.

HTTP VerbPathActionUsed for
GET/photosindexdisplay a list of all photos
GET/photos/newnewreturn an HTML form for creating a new photo
POST/photoscreatecreate a new photo
GET/photos/:idshowdisplay a specific photo
GET/photos/:id/editeditreturn an HTML form for editing a photo
PATCH/PUT/photos/:idupdateupdate a specific photo
DELETE/photos/:iddestroydelete a specific photo
For example, if Rails application receives a incoming request for 
GET /photos/1
The router would dispatch that request to the show action in the photos controller with {id: '1'} in params.

Thursday, May 23, 2013

Experimenting Rails Notification Module

Rails ActiveSupport::Notification module offers a mechanism to launch certain behavior when certain events occur. A common instance is to send an email to user after they finished signing up. Here we will do something much easier to show you how Notification module works. The basic idea is we'll simulate a man (which we will call it mess maker) pouring water into a pitcher. Each time he will pour certain amount of water into the pitcher, and when the pitcher can no longer hold any more water, a warning is fired telling him that the water is overflowing.

So first of all, we need to create a Pitcher class and a MessMaker class.
class Pitcher
  attr_accessor :content

  VOLUME = 100

  def initialize
   @content = 0
  end

  def check_overflow(name)
   ActiveSupport::Notifications.instrument("overflow", :name => name) if content > VOLUME  end
end

class MessMaker
  attr_accessor :name

  def pour_water(pitcher, amount)
   pitcher.content += amount
   pitcher.check_overflow(name)
  end

  ActiveSupport::Notifications.subscribe("overflow") do |name, start, finsih, id, payload|     puts 'Hey, ' + payload[:name].to_s + '. Stop pouring water!'
  end
end

As we can see, each Pitcher instance has a instance variable called content which is initialized to be 0 and recalculated as the mess maker pours more water into it. When the content reaches the VOLUME, an event called "overflow" is instrumented.  Right after "overflow" event is instrumented, the block in the Notification.subscribe gets executed, asking the mess maker to stop pouring more water. Note that subscribing code is not necessarily under the MessMaker class, you can put it wherever that makes sense as long as that chunk of code is loaded when you launch the application.

Now let's do some experiments in rails console
1.9.3-p392 :001 > mm = MessMaker.new
 => # 
1.9.3-p392 :002 > mm.name = 'david'
 => "david" 
1.9.3-p392 :003 > p = Pitcher.new
 => # 
1.9.3-p392 :004 > mm.pour_water(p, 30)
 => nil 
1.9.3-p392 :005 > p.content
 => 30 
1.9.3-p392 :006 > mm.pour_water(p, 30)
 => nil 
1.9.3-p392 :007 > p.content
 => 60 
1.9.3-p392 :008 > mm.pour_water(p, 30)
 => nil 
1.9.3-p392 :009 > mm.pour_water(p, 30)
Hey, david. Stop pouring water!
 => nil 




Sunday, May 19, 2013

Rails Single Table Inheritance

Updated at Sep 21, 2014
Rails Version 4.1.1

Why single table inheritance?
In Rails,we usually have one database table for each of our model. That's very straightforward. But how do we deal with classes (or models) that inherit from other classes. Do we need to create database tables for each of them. The answer is it depends. If all the subclasses are very similar to each other or even identical (attribute wise), then creating individual tables for each of them might not be a good idea. Luckily, we have single table inheritance in Rails. Implied by its name, single table inheritance has only one table for the base class and all the subclasses. This table must meet the following requirement:

  • Contains the attributes of all the classes involved in single table inheritance
  • Contain a column called "type" to identify the class of each record in it
  • Allow null for each of the attribute that do not appear in all classes
What's the benefit of it?
The benefit of single table inheritance is very obvious: you got only one table. You give up data purity to gain more performance. Model wise, however, you still get the flexibility: each class can have their unique behaviors (methods).

In the following I'm going to show you a simple example of how to use single table inheritance. Let's say we have a base class Student, which is the super class of the class TA (teaching assistant) and class RA (research assistant). First of all, we need to find out all the attributes these three classes have. The base class Student has student_id, firstname, lastname, department, major. TA has an extra attribute called course_number, indicating the course TA assists in teaching. RA has an extra attribute called topic, indicating the topic s/he is researching on. As we've mentioned, all the six attributes have to appear in the table student, as well as the type attribute.

Create the migrate for Student model
class CreateStudent < ActiveRecord::Migration
  def change
    create_table :students do |t|
      t.integer :student_id, :null => false
      t.string :firstname, :null => false
      t.string :lastname, :null => false
      t.integer :department_id, :null => false
      t.string :major, :null => false
      t.string :type, :null => false
      t.integer :course_number
      t.string :topic
    end
  end
end

Now let's create the hierarchy of our single table inheritance

student.rb
class Student
end
ta.rb
class Ta < Student
  def grade 
    puts 'I can grade'
  end
end
ra.rb
class Ra < Student
  def research 
    puts 'I can do research'
  end
end

Now let's launch the console and do some experiments.
david = Ra.create(:student_id => 1, :firstname=>'david', :lastname=>'zheng', :major=>'cs', :department_id=>1, :topic=> 'Database')
mike = Ta.create(:student_id => '002', :firstname=>'mike', :lastname=>'lu', :major=>'cs', :department_id=>1, :course_number =>'CS511')
All the records we created using subclass RA and TA will go into the table students.
david.research
I can do research
mike.grade
I can grade
Objects of subclasses can only call their own methods.
dave = Student.find_by_first_name('david')
dave.class.name
=> "RA"
The object uses the "type" column to determine which class it belongs to.

Wednesday, April 17, 2013

Use Ruby Block and Save Your Code

How I run into this?
I'm recently working on a small project, which is basically about importing an excel file into our system. Among all the implementing steps, one thing i need to do is to validate each cell of the excel file. The same validation can be applied to the cells within the same column, because they are of the same data type. So I could've written something like this:

def validate_column_1
  for i in 1..sheet.last_row
    # do some validation
  end
end  

def validate_column_2
  for i in 1..sheet.last_row
    # do some validation
  end
end 

...

By doing this, I ended up written a bunch of identical for loops (I mean the for loops themselves, not the code within them). However, you can write something smarter by using a technic which is commonly used in functional programming. What you can do is write one method which takes each different validation code as parameter and apply it to each cell while iterating through rows. This way, you only need to write one for loop. In Ruby, you can achieve this by using blocks. There are a bunch of excellent blogs about Ruby block out there, so I will not repeat that.

So here is the smarter way to go;

def validate_excel(args, &block)
  for i in 1..sheet.last_row
      block.call #pass in the argument for the block
  end
end

# call the method
validate_excel(args) {|variables| validation_code}




Friday, March 8, 2013

Ruby Pass By Value? Pass By Reference? Pass By Sharing!!

Updated at Dec 27, 2013

There has been a debate over the Internet about whether Ruby's method parameters are passed by value or by reference. Some people claim that it's passed by value by providing the following code.

str_1 = "pass_by_value"

def pass_by_value(str)
  str = "pass_by_reference"
end

pass_by_value(str_1)
str_1
=> "pass_by_value"

It looks convincing at the first glance, as the function pass_by_value didn't change the value of the str_1. But if you change the code a little bit, you will find this assertion is erroneous.

str_1 = "pass_by_value"
str_1.object_id
=> 70332873209820

def pass_by_value(str)
  puts str.object_id
end

pass_by_value(str_1)
70332873209820
 => nil
In the method pass_by_value, when we call method object_id of the object referenced by the variable str, it returns the same id as the object referenced by "str_1". If Ruby pass argument by value, the object_id should NOT be the same. As the value is copied to a new memory location and the local variable str will point to the new object.

Now we can come to the conclusion that Ruby does not pass argument by value, but neither does it pass argument by reference. Because if it does, str_1 should've been changed in our first code snippet. So there must be another evaluation strategy that Ruby uses. This third evaluation strategy is called pass by sharing. Here is a citation from wikipedia that states how pass by sharing works. The semantics of call by sharing differ from call by reference in that assignments to function arguments within the function aren't visible to the caller (unlike by reference semantics)[citation needed], so e.g. if a variable was passed, it is not possible to simulate an assignment on that variable in the caller's scope. However since the function has access to the same object as the caller (no copy is made), mutations to those objects, if the objects are mutable, within the function are visible to the caller, which may appear to differ from call by value semantics. Let's take a look at the following code snippet.

str_1 = 'abc'
str_2 = 'abc'

def mutate_str(str)
str << 'efg'
end

def assign_str(str)
str = 'abcefg'
end

And if we call mutate_str on str_1 and assign_str on str_2. We can find that str_1 is changed to 'abcefg', while str_2 remains 'abc'.
> mutate_str(str_1)
=> "abcefg" 
> str_1
=> "abcefg" 
> assign_str(str_2)
=> "abcefg" 
> str_2
=> "abc" 

When to Use "self" Keyword Explicitly

In Ruby, when you are defining an instance method, the keyword "self" can be used to refer to the current object.

class Name < String
  def write_name_in_capital_letter
    self.upcase
  end
end
name = Name.new('david')
name.write_name_in_capital_letter
=> "DAVID"

In the example above, you can remove the self keyword and the method still works. That's because when you call a method without an explicit receiving object, the method message is implicitly sent to "self". In this case, upcase is sent to "self".

class Name < String
  def write_name_in_capital_letter
    upcase
  end
end
name = Name.new('david')
name.write_name_in_capital_letter
=> "DAVID"
This is just a Ruby's idiom to save programmers' work. However, abusing this feature may lead to unexpected result. There are two situation where "self" is needed to get desirable result. The first situation is when you attempt to call the method "class".

class Name < String
  def show_my_class_name
    puts class.name
  end
end
It actually gives the following error.

SyntaxError: (irb):49: syntax error, unexpected '.'
puts class.name
Because the Ruby interpreter thinks of "class" as the class keyword instead the class method.

Another situation is when you attempt to call the setter method on an instance variable.

class Name < String
  attr_accessor :an_attr

  def change_attr
     an_attr = 'hohoho'
  end
end
n = Name.new
n.an_attr = 'hahaha'
n.change_attr
n.an_attr
 => "hahaha"
We can see no error is thrown, but "an_attr" is not changed at all. That's because the "an_attr=" in method change_attr is not interpreted as the setter method of "an_attr". Instead, it is an assignment of local variable. Because if Ruby interpreter takes it as the setter method, there will be no way left for you to define a local variable named "an_attr".

So in these two situations you need to use "self" explicitly.

References
http://www.jimmycuadra.com/posts/self-in-ruby

Wednesday, March 6, 2013

Yaml Basics and Some Simple Examples (Part 2)

Sometimes you need certain values to appear several times in your yaml file. Instead of copying and pasting, you can use node anchors, which marks a node for future reference. An anchor is denoted by the “&” indicator and a reference is denoted by "*"indicator. For example, in the test_3.yml file in Part 1, if we want the team_3 to have the same members as team_1, we can use node anchors.

test_3.yml
team_1: &team_1_members
  - Brian
  - David
  - Tom

team_2: 
  - Mike
  - Bob
  - Sam

team_3: 
  *team_1_members 
 => {"team_1"=>["Brian", "David", "Tom"], "team_2"=>["Mike", "Bob", "Sam"], "team_3"=>["Brian", "David", "Tom"]}

Tuesday, March 5, 2013

Yaml Basics and Some Simple Examples (Part 1)

Yaml is a great tool for storing configuration data. Just check out the config folder of your rails app, you will find plenty of files ending with .yml. You can load your yaml file by calling the method YAML.load_file. After a yaml file is loaded into memory, it presents itself as either Array or Hash, which depends on how the original yaml file has been written.

In a yaml file, indentations are not just used for ease of reading, they are actually used to indicate parent node and child node. Here is how yaml's official site (http://www.yaml.org/spec/1.2/spec.html#id2777534) puts it, Each node must be indented further than its parent node. All sibling nodes must use the exact same indentation level. However the content of each sibling node may be further indented independently.

In the following, I will show you four yaml files. Two of them presents themselves as arrays after they are read into memory, and the other two presents themselves as hashes.

test_1.yml
- Abraham Lincoln 
- George W. Bush
- Barack Obama
=> ["Abraham Lincoln", "George W. Bush", "Barack Obama"]

test_2.yml
name: David
age: 25
gender: male 
 => {"name"=>"David", "age"=>25, "gender"=>"male"}

test_3.yml
team_1:
  - Brian
  - David
  - Tom

team_2: 
  - Mike
  - Bob
  - Sam

team_3: 
  - Adam
  - Aron
  - Bruce 
 => {"team_1"=>["Brian", "David", "Tom"], "team_2"=>["Mike", "Bob", "Sam"], "team_3"=>["Adam", "Aron", "Bruce"]}

test_4.yml
-
 name: david
 age: 25
 gender: male
-
 name: sam
 age: 22
 gender: male
-
 name: bill
 age: 29
 gender: male 
=> [{"name"=>"david", "age"=>25, "gender"=>"male"}, {"name"=>"sam", "age"=>22, "gender"=>"male"}, {"name"=>"bill", "age"=>29, "gender"=>"male"}]

We see two symbols here, the dash and space ("- ") and the colon and space (": "). The former is used to mark the start of an array member and the latter is used to mark a key-value pair. So for the four test files, after we load them into memory, we get an array, a hash, a hash whose values are arrays and an array of hashes, respectively.

Monday, March 4, 2013

Experimenting Built-in Transactions

One important feature of a reliable database system is atomicity, i.e. either a transaction succeeds as a whole or none of its statement is executed. Put it in another way, if one of its statement fails, all of its statements must not be executed. Rails has a nice clean implementation of transaction, just wrap all the rails code which you want to put within a transaction with the transaction call,

  A_CLASS.transaction do
    # ...
  end

All the code within the block that will touch the database is guaranteed to be executed on a whole or none of them are executed. However, one thing worth noting is that only the database is guaranteed on atomicity, those models involved are changed anyway. If you want to restore the models involved in the transaction if any of the database statement fails, you need to add them as parameters to the transaction method.

However, what I'm going to mess around with today is a special kind of transaction called built-in transaction. Built-in transaction guarantees the atomicity of the transaction that occurs between parent and child tables. For example, when saving a parent record, built-in transaction makes sure that either the parent record and all its related child records are saved to database, or nothing is saved to database.

Let's create two very simple classes, Order and OrderLineItem, and define a one-to-many relationship between them.
rails generate model Order total:decimal description:text
rails generate model OrderLineItem subtotal:decimal description:text order:references

class Order < ActiveRecord::Base
  attr_accessible :description, :total
  has_many :order_line_items
end

We also require that each line item's subtotal must be greater than 0.
class OrderLineItem < ActiveRecord::Base
  belongs_to :order
  attr_accessible :description, :subtotal

  # validations
  validates_numericality_of :subtotal, 
        :greater_than => 0
end

Now let's launch the console. Let's create an order , and an order line item with subtotal to be -1, and then we assign the line item to the order object. We know the line item is invalid. We also know if we save the order object, the line item will be saved too. So let's call the save method on the order object and see what happens. As expected, it throws an error saying line item subtotal must be greater than zero. Now let's check the database, we can see no order or order line item records is added to database. Then let's change subtotal of the line item object to 1, and then save the order again, now both the order and the line item are saved to database.


Thursday, February 21, 2013

Experimenting Rails Validation Helpers

(This experiment is performed using Ruby version 1.9.3 and Rails version 3.0.9)

This post is to experiment the Rails validation helpers. Rails validation helpers are just shortcut of some very common validations. For example, a username attribute of the User class must be no longer than 16 characters. How to use these validation helper is very straightforward: just pass in the attribute on which you want to validate and set up the configuration options. Here is how I experiment them. I create a User class, which has attributes username, firstname, lastname, age, birthday, language, balance, password and two instance variables terms and password_confirmation. The required validation on these attributes and instance variables are upon each save
- term must be true
- password and password_confirmation must be the same
- firstname and lastname must not contain spaces
- age must be greater than 17
- birthday format must be in the form "xx/xx/xx"
- language must be either "English" or "Chinese"
- username must be no longer than 16 characters
- balance must be greater than 0.0
- username must be unique

To achieve the validations above, I add the following validation helpers in my User class.
class User < ActiveRecord::Base
  validates_acceptance_of :terms, 
                          :message => 'Please accept the terms to proceed'  validates_confirmation_of :password, :password_confirmation
  validates_each :firstname, :lastname do |model, attr, value|
    if value.include?(' ')
      model.errors.add(attr, "User #{model.id} has a #{attr} which contains spaces")    end
  end
  validates_exclusion_of :age, 
                         :in => 1..17, 
                         :message => 'All users must be 18 year old or higher'  validates_format_of :birthday, 
                      :with => /^[0-9]{2}\/[0-9]{2}\/[0-9]{2}$/
  validates_inclusion_of :language,
                         :in => ['English', 'Chinese'], 
                         :message => 'should be either English or Chinese'  validates_length_of :username, 
                      :maximum => 16, 
                      :message => 'username too long'
  validates_numericality_of :balance, 
                            :greater_than => 0.0
  validates_presence_of :term, :password_confirmation
  validates_uniqueness_of :username
end

All these validations will be invoked when you call valid? or save! on any object of the User class. The error messages will be saved to a hash structure called errors of that object.

Note that validates_acceptance_of and validates_confirmation_of can be performed only if terms and password_confirmation are not nil, and by default only on save. So make sure terms and password_confirmation are not nil using validates_presence_of.

Another thing that is very important is validates_uniqueness_of doesn't really guarantee the unique value of a column. Use database-level constraints instead.

Friday, February 15, 2013

Experimenting Rails Callback Class

(This experiment is performed using Ruby version 1.9.3 and Rails version 3.0.9)

An ActiveRecord model object experiences different states during its life cycle. Typically, it starts with creation, experiences several modification, saved to database and finally gets destroyed. We can write callbacks (ruby methods) that will be triggered upon each state change of model objects.

Callbacks are just ruby methods. Then what's callback class? A Callback class is just a group of methods where you can put your callback handlers and thus they can be shared among different models.

Let's say we have an Dog class, which has an instance variable called favorite_food. The table dogs has an attribute called name. What we want is whenever an Dog object is initialized, values will be assigned to favorite_food and name.

class Dog
  attr_accessor :favorite_food
end

We need to create a callback class. Let's call it SharedCallbacks. And we need to define a method called after_initialize, which is the same name of the event we want it to handle.

class SharedCallbacks
  def after_initialize(model)
    model.favorite_food = 'meat'
    model.name = 'This is a dog'
  end
end

The parameter "model" is the object on which the callback method will have effect on, which in this case is any Dog object.

Back to Dog class, now what we need to do is to create a SharedCallbacks object and hook it with the after_initialize declaration.

class Dog
  attr_accessor :favorite_food
  after_initialize SharedCallbacks.new
end

So whenever a Dog object is initialized, an new SharedCallbacks object is created and the corresponding callback method, which is after_initialize in this case, is called using the Dog object as the single parameter. As a result, the Dog object's favorite_food and name are set to the desired values.

Now let's add another requirement, whenever a record is found in database, its name will be set to  'This is a cat'. What we need to do is define a after_find method in SharedCallbacks class and hook one of its object with the after_find callback declaration in Dog class.

class SharedCallbacks
  def after_initialize(model)
    model.favorite_food = 'meat'
    model.name = 'This is a dog'
  end

  def after_find(model)
    model.name = 'This is a cat'
  end
end

class Dog
  attr_accessor :favorite_food
  after_initialize SharedCallbacks.new
  after_find SharedCallbacks.new
end

If we retrieve a record from database and look into it, we're gonna find that its name is set to 'This is a dog', NOT 'This is a cat'. That's because the after_initialize callback is always invoked after after_find. In the book Agile Web Development with Rails, there is a complete order in which callbacks are invoked, if they are declared of course.

Monday, February 11, 2013

Experimenting autosave

(This experiment is performed using Ruby version 1.9.3 and Rails version 3.0.9)

When we define a one-to-one or one-to-many relationship in Rails, very likely we're gonna want the child object(s) to be saved to database when parent object is saved. For example, we have an Order class, which has a one-to-many relationship to an OrderLineItem class. After we initialize an order object and associate it with several order line item objects, we're gonna want to save the order object. Whether the related line item objects will be saved depends on how you specify the autosave option of the has_many relationship (it also exists in has_one and belongs_to relationships). Below is how Ruby on Rails documentation say about autosave.

:autosave
If true, always save the associated objects or destroy them if marked for destruction, when saving the parent object. If false, never save or destroy the associated objects. By default, only save associated objects that are new records.

Clear enough, right? If :autosave is defined to be false, no change will be applied to the child database when the parent object is saved, even though there are a bunch of child objects associated to the parent object. If defined to be true, all the changes will be applied to the child database when the parent object is saved, no matter these child objects are new or initialized from existing records in database. Finally if by default, only those new child objects will be saved to database when parent object is saved.

You can experiment it by using the following example code. Assume we have a order record in orders table and a order line item record in order_line_items table associated to that order record, and assume quantity, one of the attributes, of that order line item is 10.

Let's type in the following commands in console when autosave is set to be true and default respectively.

o = Order.first 
order.line_items.first.quantity = 5
o.save!


If autosave is set to true. Go to the database after these commands, you will find the quantity is updated to 5.
If autosave is set to default. Go to the database after these commands, you will find the quantity is still 10.


Let's type in a different set of commands in console when autosave is set to be default and false respectively.

o = Order.first
order.line_items << new_line_item # assume we have created a new line item object called new_line_item
o.save!


If autosave is set to default. Go to the database after these commands, you will find the new_line_item is saved to db.
If autosave is set to false. Go to the database after these commands, you will find the new_line_item is NOT saved to db.

Thursday, February 7, 2013

Ruby's Single Quote And Double Quote

As a Rails tester, I've been using Ruby's single quote and double quote exchangeably until I run into the following problem. After writing so many tests, I'm thinking about metaprogramming the testing as certain tests are the same for all the models. I wrote a test template file that will be loaded for each new test file I'm going to write. This template file is basically pure text, but I want it to be a little bit more dynamic. For example, I want it to generate today's date. So I write something like the following in the template file:

# Author
#    David on #{Date.today.strftime("%m/%d/%y")}
=>
# Author
#    David on #{Date.today.strftime("%m/%d/%y")} 


However, when I read this template file into my test file, these strings appear as exactly the same as they appear in the template, as oppose to showing today date. So I searched on the Internet and find that Ruby treats single quotes and double quotes really differently: the double quotes interpret the interpolation and the escaped characters within the string, while single quotes do not do these two things. So performance-wise, using double quote is gonna take longer if interpolation or escaped character is involved.

Now back to my problem, the reason that the date is not shown correctly is that the content of the template is read as being wrapped with single quotes. So how can we tell Ruby that we want the content as to be wrapped with double quotes? We can use the double quote mark "%Q{}". Everything within the delimiter will appear as if they are wrapped with double quotes (see below).

%Q(# Author
#    David on #{Date.today.strftime("%m/%d/%y")})
=>
# Author
#    David on 02/06/2013

Wednesday, February 6, 2013

Rails Polymorphic Association

Updated on March 26, 2014
Updated on Sep 21, 2014

Let's create a scenario where polymorphic association can be used. Assume an online store (like Amazon) keeps the data of different type of items in several different tables, such as books, laptops and cell_phones.These tables have different attributes. There is another table called orders to keep track of all the items that's been ordered by customers.

This orders table has a one-to-one relationship to all the other three tables, which means it must have three different foreign keys pointing to these three tables. This is a bad design because for each order record there are two columns that are not used. You might say why not create three different tables called order_books, order_laptops and order_cell_phones. But you will find these are three identical table serving the same functionality. So here is where polymorphic association comes in.

To use polymorphic association, you need to add another attribute called "type" (rails will automatically do it for you when you define a polymorphic association) to determine which table an order record is associated to, and thus only a single foreign key is needed instead of three. Below is how polymorphic association is defined using our example.



Instead of using a specific table, model Order use a universal name "item" to refer to the other three tables. If you look into the database, you will find an attribute called "type" in table orders. Using the "type" and the foreign key, the orders table is able to uniquely point to an item, whether it's a book, a laptop or a cell phone.