Rails扩展ActiveRecord :: Base
我已经做了一些关于如何扩展ActiveRecord:Base类的阅读,所以我的模型会有一些特殊的方法。 什么是简单的方法来扩展它(一步一步的教程)?
有几种方法:
使用ActiveSupport ::关注(首选)
阅读ActiveSupport :: Concern文档以获取更多详细信息。
在lib目录下创建一个名为active_record_extension.rb的文件。 
 module ActiveRecordExtension extend ActiveSupport::Concern # add your instance methods here def foo "foo" end # add your static(class) methods here class_methods do #Eg: Order.top_ten def top_ten limit(10) end end end # include the extension ActiveRecord::Base.send(:include, ActiveRecordExtension) 
 在config/initializers目录中创建一个名为extensions.rb的文件,并将以下行添加到文件中: 
 require "active_record_extension" 
继承(首选)
请参考Toby的回答 。
猴子修补(应该避免)
 在config/initializers目录下创建一个名为active_record_monkey_patch.rb 。 
 class ActiveRecord::Base #instance method, Eg: Order.new.foo def foo "foo" end #class method, Eg: Order.top_ten def self.top_ten limit(10) end end 
有关Jamie Zawinski正则表达式的着名引用可以重新用于说明与修补猴子有关的问题。
有些人在遇到问题时,会想“我知道,我会用猴子补丁”。现在他们有两个问题。
猴子修补很简单,快捷。 但是,节省的时间和精力总是会在未来某个时候被提取出来。 与复利。 现在我限制猴子补丁,以便在滑轨控制台中快速创建解决方案。
你可以扩展这个类并简单地使用继承。
 class AbstractModel < ActiveRecord::Base self.abstract_class = true end class Foo < AbstractModel end class Bar < AbstractModel end 
 你也可以使用ActiveSupport::Concern并使用更多的Rails核心ActiveSupport::Concern : 
 module MyExtension extend ActiveSupport::Concern def foo end module ClassMethods def bar end end end ActiveRecord::Base.send(:include, MyExtension) 
[编辑]来自@daniel的评论
 然后,所有模型都将包含作为实例方法的foo方法, ClassMethods的方法包含为类方法。 例如在FooBar < ActiveRecord::Base您将拥有: FooBar.bar和FooBar#foo 
http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
使用Rails 4,使用关注点模块化和干化模型的概念一直是亮点。
顾虑基本上允许你在一个模块中将模型的类似代码或多个模型分组,然后在模型中使用这个模块。 这里是一个例子:
考虑文章模型,事件模型和评论模型。 一篇文章或一个事件有很多评论。 评论属于文章或事件。
传统上,模型可能如下所示:
评论型号:
 class Comment < ActiveRecord::Base belongs_to :commentable, polymorphic: true end 
文章型号:
 class Article < ActiveRecord::Base has_many :comments, as: :commentable def find_first_comment comments.first(created_at DESC) end def self.least_commented #return the article with least number of comments end end 
事件模型
 class Event < ActiveRecord::Base has_many :comments, as: :commentable def find_first_comment comments.first(created_at DESC) end def self.least_commented #returns the event with least number of comments end end 
正如我们可以注意到的,事件和文章模型都有一个共同的代码。 使用关注点,我们可以在一个单独的模块Commentable中提取这个通用代码。
为此,在app / model /关键字中创建一个commentable.rb文件。
 module Commentable extend ActiveSupport::Concern included do has_many :comments, as: :commentable end # for the given article/event returns the first comment def find_first_comment comments.first(created_at DESC) end module ClassMethods def least_commented #returns the article/event which has the least number of comments end end end 
现在你的模型看起来像这样:
评论型号:
  class Comment < ActiveRecord::Base belongs_to :commentable, polymorphic: true end 
文章型号:
 class Article < ActiveRecord::Base include Commentable end 
事件模型
 class Event < ActiveRecord::Base include Commentable end 
有一点我要强调的是,在使用Concerns时, Concerns应该用于“基于域”的分组而不是“技术”分组。 例如,域名分组就像“可注释”,“可标记”等。基于技术的分组将像“FinderMethods”,“ValidationMethods”一样。
这里是一个链接到一个职位 ,我发现非常有用的了解模型的关注。
希望写作帮助:)
步骤1
 module FooExtension def foo puts "bar :)" end end ActiveRecord::Base.send :include, FooExtension 
第2步
 # Require the above file in an initializer (in config/initializers) require 'lib/foo_extension.rb' 
第3步
 There is no step 3 :) 
 为了增加这个主题,我花了一段时间研究如何测试这样的扩展(我沿着ActiveSupport::Concern路线)。 
以下是我如何设置一个模型来测试我的扩展。
 describe ModelExtensions do describe :some_method do it 'should return the value of foo' do ActiveRecord::Migration.create_table :test_models do |t| t.string :foo end test_model_class = Class.new(ActiveRecord::Base) do def self.name 'TestModel' end attr_accessible :foo end model = test_model_class.new(:foo => 'bar') model.some_method.should == 'bar' end end end 
  Rails 5提供了一个用于扩展ActiveRecord::Base的内置机制。 
这是通过提供附加层来实现的:
 # app/models/application_record.rb class ApplicationRecord < ActiveRecord::Base self.abstract_class = true # put your extensions here end 
所有的模型都从这个模型继承而来:
 class Post < ApplicationRecord end 
看看这个博客帖子 。
我有
 ActiveRecord::Base.extend Foo::Bar 
在初始化器中
对于像下面这样的模块
 module Foo module Bar end end