2011-03-05 114 views
4

我創建了一個與Active Record緊密集成的Rails創建工具。寶石需要定義許多字段。例如:Ruby on Rails自定義遷移生成器

class User < ActiveRecord::Base 
    # requires 'avatar_identifier', 'avatar_extension', 'avatar_size' 
    has_attached :avatar 
end 

是否有可能有類似:

rails g model user name:string avatar:attached 

,導致:

create_table :users do |t| 
    t.string :name 
    t.string :avatar_identifier 
    t.string :avatar_extension 
    t.integer :avatar_size 
end 

如果這是不可能的,什麼辦法能讓:

create_table :users do |t| 
    t.string :name 
    t.attached :avatar 
end 

生成多個字段?謝謝!

回答

3

雖然Pravin確實指向了正確的方向,但我發現實現它並不簡單。我做了以下,我在config/initializers添加的文件(名稱是不相關的),包含以下內容:

require 'active_support' 
require 'active_record' 

class YourApplication 
    module SchemaDefinitions 

    module ExtraMethod 
     def attachment(*args) 
     options = args.extract_options! 
     args.each do |col| 
      column("#{col}_identifier", :string, options) 
      column("#{col}_extension", :string, options) 
      column("#{col}_size", :integer, options) 
     end 
     end 
    end 

    def self.load! 
     ::ActiveRecord::ConnectionAdapters::TableDefinition.class_eval { include YourApplication::SchemaDefinitions::ExtraMethod } 
    end 

    end 
end 


ActiveSupport.on_load :active_record do 
    YourApplication::SchemaDefinitions.load! 
end 

那麼你可以這樣做:

rails g model Person name:string title:string avatar:attachment 

這將創建下列遷移:

def self.up 
    create_table :people do |t| 
    t.string :name 
    t.string :title 
    t.attachment :avatar 

    t.timestamps 
    end 
end 

如果再進行遷移,rake db:migrate,將創建下列Person型號:

ruby-1.9.2-p0 > Person 
=> Person(id: integer, name: string, title: string, avatar_identifier: string, avatar_extension: string, avatar_size: integer, created_at: datetime, updated_at: datetime) 

希望這有助於!

2

我認爲t.attached類似於t.references在多態關聯。

參照references方法,你可以像下面

def attached(*args) 
    options = args.extract_options! 
    column(:avatar_identifier, :string, options) 
    column(:avatar_extension, :string, options) 
    column(:avatar_size, :integer, options) 
end 

你可能想延長ActiveRecord::ConnectionAdapters::TableDefinition
有看看這個 http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html#method-i-references

3

其實如果你打電話

rails g model profile name:string next:attached 

rails allready ge nerates你

def self.up 
    create_table :profiles do |t| 
    t.string :name 
    t.attached :next 

    t.timestamps 
    end 
end 

遷移但是你可以把它放在 /lib/templates/active_record/model/migration.rb

你應該寫一耙my_gem覆蓋默認遷移模板:設置任務把文件中有 我還沒有嘗試過,但我想在鐵軌非發動機寶石這些模板

不進行搜索,那麼您的遷移模板的內容看起來像

class <%= migration_class_name %> < ActiveRecord::Migration 
    def self.up 
    create_table :<%= table_name %> do |t| 
<% for attribute in attributes -%> 
    <% if attribute.type.to_s == "attached" %> 
     t.string :<%= attribute.name %>_identifier 
     t.string :<%= attribute.name %>_extension 
     t.integer :<%= attribute.name %>_size 
    <% else %> 
     t.<%= attribute.type %> :<%= attribute.name %> 
    <% end %> 
<% end -%> 
<% if options[:timestamps] %> 
     t.timestamps 
<% end -%> 
    end 
    end 

    def self.down 
    drop_table :<%= table_name %> 
    end 
end 
+0

這是一個很好的替代方法,但它只適用於使用生成器。 – nathanvda 2011-03-15 21:29:59

+0

以及quiestion是「是否有可能有這樣的事情:rails g模型用戶名:字符串頭像:附加」。所以我想這是適用的,但我明白你的觀點。 – Valdis 2011-03-15 21:35:34