Ruby on Rails Custom Migration Generator

后端 未结 3 1107
走了就别回头了
走了就别回头了 2021-02-06 11:38

I\'m creating a Rails gem that integrates closely with Active Record. The gem requires a number of fields to be defined. For example:

class User < ActiveRecor         


        
相关标签:
3条回答
  • 2021-02-06 12:16

    I consider t.attached similar to t.references in a polymorphic association.

    With reference to the references method you can have something like below

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

    You might like to extend ActiveRecord::ConnectionAdapters::TableDefinition
    Have look at this http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html#method-i-references

    0 讨论(0)
  • 2021-02-06 12:24

    While Pravin did point in the right direction, i found it was not straightforward to implement it. I did the following, i added a file in config/initializers (name is not relevant), containing the following:

    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
    

    then you can just do something like:

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

    which will create the following migration:

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

    If you then run the migration, rake db:migrate it will create the following Person model:

    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) 
    

    Hope this helps!!

    0 讨论(0)
  • 2021-02-06 12:42

    Actually if you call

    rails g model profile name:string next:attached
    

    rails allready generates you a migration with

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

    however you can override the default migration template by placing it in /lib/templates/active_record/model/migration.rb

    You should write a rake my_gem:setup task to put the file there I haven't tried, but i guess rails does not search in non-engine gems for these templates

    Your migration template contents would then look like

    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 讨论(0)
提交回复
热议问题