prappo prince prappo prince - 8 months ago 9
Ruby Question

How does Ruby's block syntax work?

I'm new in Ruby and trying to understand this syntax:

create_table :posts do |t|
t.string :title
t.string :content
t.string :likes
t.string :comments

t.timestamps null: false
end


I fully understand what this code is doing, but I don't understand how it works. More specifically, I understand that
create_table
is a method and
:posts
is a parameter, but I don't understand the rest of the code.

Answer

Let's first forget about Active Record and focus on the code structure itself. Here is a super simple version of that structure.

class MyBuilder
  def initialize
    # keys are property names, values are options
    @properties = {}
  end

  def property(name, options={})
    @properties[name] = options
  end

  def build
    # For simplicity, just return all properties
    @properties
  end
end

def create_thing(name)
  puts "Begin creating #{name}"

  builder = MyBuilder.new

  puts "Let user use the builder to define properties"
  yield builder

  puts "Consume the builder"
  properties = builder.build

  puts "Persist changes to #{name}..."
  # For simplicity just print them out
  p properties

  puts 'done'
end

create_thing :bar do |builder|
  builder.property :counter, color: 'brown'
  builder.property :wine_storage, texture: 'wood'
end

Please type the code above by hand to grab some feel.

Although the code above has nothing to do with Active Record, it has the same structure as the migration.

When ever create_table is called, it instantiates a builder (of type TableDefinition), and "pushes" that builder to the block (by yielding it) in order to let user define the tables columns. The builder is consumed later by create_table when the user is done defining the columns.