How ActiveRecords create tables

I’ll start off by saying I am new to Ruby and Rails…

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. 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. How is Ruby finding
create_table?

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? why no comma between t.string and :name.

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

BTW as I hunt I do see this in Migration:

def method_missing(method, *arguments, &block)

It is taunting me.

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

Thanks,

Cris

Cris S. 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 :slight_smile:

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
[email protected]

Marnen Laibow-Koser wrote:

Cris S. wrote:
[…]

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.
[…]

On second thought, the braces are probably OK (although it’s more common
to use do…end for multiline blocks and braces for single-line ones).
The bigger problem is the parentheses. If you’re going to use them,
then the closing parenthesis goes before the beginning of the block.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Marnen,

Thanks! You answered my questions perfectly!!!

Thanks,

Cris

Marnen Laibow-Koser wrote:

Marnen Laibow-Koser wrote:

Cris S. wrote:
[…]

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.
[…]

On second thought, the braces are probably OK (although it’s more common
to use do…end for multiline blocks and braces for single-line ones).
The bigger problem is the parentheses. If you’re going to use them,
then the closing parenthesis goes before the beginning of the block.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Oh and this does work, not around the block as you said:

def self.up
create_table (:people) { |t|
t.string :name, :type, :email, :camera
t.timestamps
}
end

Thanks again!

Cris S. wrote:

Marnen,

Thanks! You answered my questions perfectly!!!

Thanks,

Cris

Marnen Laibow-Koser wrote:

Marnen Laibow-Koser wrote:

Cris S. wrote:
[…]

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.
[…]

On second thought, the braces are probably OK (although it’s more common
to use do…end for multiline blocks and braces for single-line ones).
The bigger problem is the parentheses. If you’re going to use them,
then the closing parenthesis goes before the beginning of the block.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]