首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用其他方法扩展ActiveRecord::Migration?

如何使用其他方法扩展ActiveRecord::Migration?
EN

Stack Overflow用户
提问于 2010-11-22 04:38:24
回答 2查看 3.4K关注 0票数 17

我正在创建一个Ruby gem,并希望使用我自己的助手扩展ActiveRecord::Migration,以创建所需的列。(这类似于Devise为其各种身份验证策略创建迁移时所做的事情。)我意识到我添加的功能本身是相当微不足道的,而且可能有更好/更有效的方法来做到这一点-我尝试将其作为一种学习体验,而不是作为实际应用程序。我只想了解如何在Rails中添加新的迁移功能这样具有侵入性的事情。

到目前为止,我已经成功地构建并安装了gem,但是当我尝试运行如下迁移时:

代码语言:javascript
复制
class CreatePosts < ActiveRecord::Migration
  def self.up
    create_table :posts do |t|
      t.string :name
      t.string :title
      t.text :content
      t.hideable
      t.tracks_hidden_at
      t.timestamps
    end
  end
end

..。它不能说hideable没有定义。

我已经研究了Devise是如何做到这一点的,我不得不承认我有点迷茫,但我试图摸索着克服它。我做了以下工作:

扩展了ActiveRecord,添加了新的模型,并创建了一个方法,用于根据新的迁移方法应用模式更改

代码语言:javascript
复制
require 'orm_adapter/adapters/active_record'

module HiddenRecord
  module Orm
    # This module contains some helpers and handle schema (migrations):
    #
    #   create_table :accounts do |t|
    #     t.hideable
    #     t.tracks_hidden_timestamp
    #   end
    #
    module ActiveRecord
      module Schema
        include HiddenRecord::Schema

        # Tell how to apply schema methods.
        def apply_hiddenrecord_schema(name, type, options={})
          column name, type.to_s.downcase.to_sym, options
        end
      end
    end
  end
end
ActiveRecord::Base.extend HiddenRecord::Models
ActiveRecord::ConnectionAdapters::Table.send :include, HiddenRecord::Orm::ActiveRecord::Schema
ActiveRecord::ConnectionAdapters::TableDefinition.send :include, HiddenRecord::Orm::ActiveRecord::Schema

创建了一个类似于Devise的schema.rb的模式模块,它定义了我想在迁移中使用的方法,并调用一个方法来应用模式

代码语言:javascript
复制
module HiddenRecord
  # Holds schema definition for hiddenrecord model options.
  module Schema
    # Sets the model as having hidable rows
    #
    # == Options
    # * :null - When true, allows the hidden row flag to be null
    # * :default - Used to set default hidden status to true. If not set, default is false (rows are not hidden)
    def hideable(options={})
      null = options[:null] || false
      default = options[:default] || false

      apply_hiddenrecord_schema :hiddenrecord_is_row_hidden, Boolean, :null => null, :default => default
    end

    # Sets the model to record the timestamp when a row was hidden
    def tracks_hidden_timestamp()
      apply_hiddenrecord_schema :hiddenrecord_hidden_at, DateTime
    end
  end
end

为模型添加了支持新字段的方法

代码语言:javascript
复制
module HiddenRecord
  module Models
    # This module implements the hideable API
    module Hideable
      def self.included(base)
        base.class_eval do
          extend ClassMethods
        end
      end

      scope :visible, where(:hiddenrecord_is_row_hidden => true)

      def hidden?
        return hiddenrecord_is_row_hidden || false
      end

      def hide
        hiddenrecord_is_row_hidden = true
      end

      def hide!
        hiddenrecord_is_row_hidden = true
        save!
      end

      def unhide
        hiddenrecord_is_row_hidden = false
      end

      def unhide!
        hiddenrecord_is_row_hidden = false
        save!
      end

    end
  end
end

在gem的主模块中加载模式和模型文件

代码语言:javascript
复制
module HiddenRecord
  autoload :Schema, 'hiddenrecord/schema'
  autoload :Models, 'hiddenrecord/models'
  ...
end
require 'hiddenrecord/models/hideable'
require 'hiddenrecord/models/tracks_hidden_timestamp'

再一次,认识到这主要是一次学习经历,我希望有人能为我指出如何做到这一点的正确方向。我在Rails 3上尝试了这一点。

EN

回答 2

Stack Overflow用户

发布于 2012-04-02 07:46:58

下面是我如何使用Rails 2和MySQL为以前的项目添加自定义迁移字段。效果很好。

我不知道这在多大程度上适用于您的确切需求,所以请随时向我提问。

我将这段代码放在Rails.root/lib/dbd_migration_helper.rb中

代码语言:javascript
复制
module Ddb

  module MigrationHelper

    def self.included(base) # :nodoc:
      base.send(:include, InstanceMethods)
    end

    module InstanceMethods
      def active    (column_name=:active)     column(column_name, :boolean, :default=>true) end
      def email     (column_name=:email)      column(column_name, :string)     end
      def latitude  (column_name=:latitude)   column(column_name, :float)      end
      def longitude (column_name=:longitude)  column(column_name, :float)      end
      def position  (column_name=:position)   column(column_name, :integer)    end
    end
  end
end

require 'activerecord'
if defined?(ActiveRecord::ConnectionAdapters::TableDefinition)
   ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, Ddb::MigrationHelper)
end
票数 7
EN

Stack Overflow用户

发布于 2012-04-07 19:47:05

快速注意,下面这几行:

代码语言:javascript
复制
ActiveRecord::ConnectionAdapters::Table.send :include, HiddenRecord::Orm::ActiveRecord::Schema
ActiveRecord::ConnectionAdapters::TableDefinition.send :include, HiddenRecord::Orm::ActiveRecord::Schema

似乎没有包含正确的模块。我认为它们应该是:

代码语言:javascript
复制
ActiveRecord::ConnectionAdapters::Table.send :include, HiddenRecord::Schema
ActiveRecord::ConnectionAdapters::TableDefinition.send :include, HiddenRecord::Schema

但是,您似乎也没有在任何地方定义#tracks_hidden_at

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4240231

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档