В Rails 1.1 появился Object#with_options
Например, следующий код маршрутизации:
map.connect 'atom.xml', :controller => 'feed', :action => 'everything_atom'
map.connect 'comments-atom.xml', :controller => 'feed', :action => 'comments_atom'
можно использовать магию Object#with_options
map.with_options(:controller => 'feed') do |feed|
feed.connect 'atom.xml', :action => 'everything_atom'
feed.connect 'comments-atom.xml', :action => 'comments_atom'
end
Хорошо, а?
Давайте посмотрим на миграцию, которую я недавно написал:
class AddExcerptSlugAndImageToArticles < ActiveRecord::Migration
def self.up
add_column :articles, :excerpt, :text
add_column :articles, :slug, :string
add_column :articles, :image, :string
end
def self.down
remove_column :articles, :excerpt
remove_column :articles, :slug
remove_column :articles, :image
end
end
Argh … статьи, статьи везде! Во-первых, давайте подумаем, как бы мы хотели, чтобы API выглядел:
class AddExcerptSlugAndImageToArticles < ActiveRecord::Migration
def self.up
with_table :articles do |t|
t.add_column :excerpt, :text
t.add_column :slug, :string
t.add_column :image, :string
end
end
def self.down
with_table :articles do |t|
t.remove_column :excerpt
t.remove_column :slug
t.remove_column :image
end
end
end
Ааа … намного лучше. Как мы можем добавить этот метод with_table
Во-первых, нам нужно добавить метод with_table
ActiveRecord::Migration
class ActiveRecord::Migration
def self.with_table(table_name)
# Funky magic
end
end
Метод with_table
yield
Самый простой способ сделать это — создать новый Object
Мы определим метод method_missing
Если мы вызываем прокси с помощью add_column :blurb, :string
add_column :articles, :blurb, :string
Собирая все это вместе, мы получаем:
class ActiveRecord::Migration
def self.with_table(table_name)
proxy = Object.new
proxy.instance_variable_set(:@migration, self)
proxy.instance_variable_set(:@table_name, table_name)
def proxy.method_missing(method_name, *args)
@migration.send(method_name, *(args.to_a.insert(0, @table_name)))
end
yield proxy
end
end
Хорошо а? Попробуйте добавить это в начало одного из ваших файлов миграции и протестировать его, и, если вы хотите узнать больше об этом безумстве method_missing, ознакомьтесь с главой 6 «Почему стоит писать в Ruby» .