Re: How ActiveRecords create tables

Marnen Laibow-Koser
Wed, 23 Sep 2009 20:18:17 -0000

Cris Shupp wrote:
> I''ll start off by saying I am new to Ruby and Rails...

You might find it helpful to read about Ruby''s object model in general.
It''s subtly different from those of most other OO languages.

>
> Suppose I run the following;
>
> $ script/generate model person
>
>
> which creates:
>
> class CreatePeople < ActiveRecord::Migration
>   def self.up
>     create_table :people do |t|
>
>       t.timestamps
>     end
>   end
>
>   def self.down
>     drop_table :people
>   end
> end
>
>
> I added in some code (the author instructs me to) such that it now
> reads:
>
> class CreatePeople < ActiveRecord::Migration
>   def self.up
>     create_table :people do |t|
>       t.string :name, :type, :email, :camera #ADDED IN
>       t.timestamps
>     end
>   end
>
>   def self.down
>     drop_table :people
>   end
> end
>
> I do not understand, at a ruby level, what is going on.  It appears I
> have a class (static) method called up.

Correct.

> The first thing I am doing is
> calling Migration''s create_table method.  This leads to question
1:
>
> 1:) Migration does not have create_table method.

You''re right.  But the DB connection adapters do.

> How is Ruby finding
> create_table?

Presumably by delegating to the connection adapter, likely by means of
method_missing.

>
> Now the create_table method appears to accept two parameters.  The first
> being a symbol, and the second being a code block.
>
> I am assuming that the only thing obtainable from this code block is the
> last line t.timestamps, as the last line is returned in ruby.
>
> So question number two:
>
> 2:  What does this line even do?
> t.string :name, :type, :email, :camera #ADDED IN
>
> What is t being passed in?

A block argument.

> why no comma between t.string and :name.

Because string is the name of the method being called on t , while :name
is its first argument.  With parentheses, it would be t.string(:name,
:and_so_on) , but in Ruby, you can omit the parentheses when it would
not be ambiguous.

>
>
> And my final question...
>
> How come I cannot write the code as follows (Aptana will not compile
> it)?
>   def self.up
>     create_table (:people,{|t|
>       t.string :name, :type, :email, :camera
>       t.timestamps
>     })
>   end

Because you''ve got your syntax wrong.  The braces aren''t
correct In this
context (this isn''t JavaScript!) and parens don''t go around
blocks
passed to functions.

Aptana isn''t doing any compilation for you, BTW.  (And on an unrelated
note, the sooner you stop using an IDE for Rails, the better.  I
reccomend a good editor like KomodoEdit instead.)
>
>
> BTW as I hunt I do see this in Migration:
>
> def method_missing(method, *arguments, &block)
>
> It is taunting me.

What''s taunting you?  Go learn about method_missing and how it works.
It''s an important Ruby concept.

>
> Feel free to respond to me like I am four.  You could try to insult me
> but you would fail :-)

I think you can answer many of your questions by looking at the Rails
source and the remainder by reading Programming Ruby.

>
> Thanks,
>
> Cris

Best,
--
Marnen Laibow-Koser
http://www.marnen.org
marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org