我已经做了一些关于如何扩展ActiveRecord:Base类的阅读,所以我的模型会有一些特殊的方法。什么是简单的方法来扩展它(一步一步的教程)?Rails扩展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
#E.g: Order.top_ten
def top_ten
limit(10)
end
end
end
# include the extension
ActiveRecord::Base.send(:include, ActiveRecordExtension)
创建一个名为extensions.rb
的config/initializers
目录中的文件,并将以下行添加到文件:
require "active_record_extension"
继承(首选)
参考托比的answer。
猴修补(应尽量避免)
创建一个名为active_record_monkey_patch.rb
的config/initializers
目录中的文件。
class ActiveRecord::Base
#instance method, E.g: Order.new.foo
def foo
"foo"
end
#class method, E.g: Order.top_ten
def self.top_ten
limit(10)
end
end
有关正则表达式的名言被Jamie Zawinski可以被重新利用来说明与猴子修补相关的问题。
Some people, when confronted with a problem, think “I know, I'll use monkey patching.” Now they have two problems.
猴子修补很容易和快捷。但是,节省的时间和精力总是会在将来的某个时候提取回 ;与复利。现在我限制猴子修补,以便在轨道控制台中快速构建原型解决方案。
嗯......第二个例子是当我运行./scripts/console时出现错误 “include”:TypeError:错误的参数类型Class (预期模块)“ – xpepermint 2010-02-24 21:17:36
@xpepermint听起来像是你用'class MyActiveRecordExtensions'而不是'module MyActiveRecordExtensions'来启动它的。 – 2010-02-24 23:59:06
没有...我疯了一个复制和粘贴。奇怪... – xpepermint 2010-02-25 08:01:02
步骤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 :)
我猜步骤2必须放置在config/environment.rb中。这对我来说不是很有用:(你可以写一些更多的帮助吗?Thx。 – xpepermint 2010-02-24 20:22:59
您可以只扩展该类并简单地使用继承。
class AbstractModel < ActiveRecord::Base
self.abstract_class = true
end
class Foo < AbstractModel
end
class Bar < AbstractModel
end
我喜欢这个想法,因为它是一种标准的做法,但是...我得到一个错误表'moboolo_development。 abstract_models'不存在:显示来自'abstract_models'的字段。我应该把它放在哪里? – xpepermint 2010-02-25 07:59:59
将'self.abstract_class = true'添加到'AbstractModel'中。 Rails现在将该模型视为一种抽象模型。 – 2010-02-25 17:53:40
哇!没想到这是可能的。当ActiveRecord ch咽在数据库中寻找'AbstractModel'时尝试了它并放弃了。谁知道一个简单的二传手会帮我干什么! (我开始畏缩......这很糟糕)。感谢Toby和Harish! – dooleyo 2013-06-28 04:04:52
您还可以使用ActiveSupport::Concern
和更Rails核心成语,如:
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
请注意,'InstanceMethods'已被弃用,因为Rails 3.2,只是把你的方法放入模块体。 – 2012-12-12 11:01:54
我在初始化器中放置了'ActiveRecord :: Base.send(:include,MyExtension)',然后这对我有用。 Rails 4.1.9 – 2015-01-20 06:38:02
只需添加到这个话题,我花了一段时间去解决如何测试这种扩展(我走下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
我
ActiveRecord::Base.extend Foo::Bar
在初始化
对于像下面
module Foo
module Bar
end
end
使用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
正如我们可以看到, 那里 是Event和Article Model共同的重要代码。使用关注点,我们可以在一个单独的可评论模块中提取此通用代码。
为此,在app/model/concerns中创建一个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是关注点应该用于“基于域”的分组而不是“技术”分组。例如,域名分组就像'可注释','可标记'等。基于技术的分组将像'FinderMethods','ValidationMethods'。
这是一个link to a post,我发现它对于理解模型中的问题非常有用。
希望的书面记录帮助:)
这是我最喜欢的答案,谢谢:) – 2017-03-30 14:36:50
的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
参见例如this blogpost。
使用Rails 5,所有模型都从ApplicationRecord &继承,它提供了很好的方式来包含或扩展其他扩展库。
# app/models/concerns/special_methods.rb
module SpecialMethods
extend ActiveSupport::Concern
scope :this_month, -> {
where("date_trunc('month',created_at) = date_trunc('month',now())")
}
def foo
# Code
end
end
假设特殊方法模块需要跨所有模型可用,请将其包含在application_record.rb文件中。如果我们想将其应用于特定的一组模型,则将其包含在相应的模型类中。
# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
include SpecialMethods
end
# app/models/user.rb
class User < ApplicationRecord
include SpecialMethods
# Code
end
如果您希望将模块中定义的方法定义为类方法,请将模块扩展到ApplicationRecord。
# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
extend SpecialMethods
end
希望它能帮助别人!
- 1. 扩展从ActiveRecord :: Base
- 2. 扩展的ActiveRecord :: Base的
- 3. 扩展的ActiveRecord :: Base的两个干将
- 4. Ruby on Rails:扩展ActiveRecord :: Errors
- 5. rails named_scope作为AR的扩展:: Base
- 6. 如何在Ruby on Rails中扩展ActiveRecord :: Base时指定列名和类型?
- 7. 在Rails中扩展ActiveRecord :: Base在测试环境中不起作用
- 8. 从rails引擎扩展ActiveRecord类
- 9. Rails模型不能继承ActiveRecord :: Base
- 10. 如何在Rails中使用ActiveRecord :: Base的
- 11. 比较ActiveRecord :: Base和ActiveRecord
- 12. 如何将ActiveRecord :: Associations扩展到rails中的frozen_record
- 13. 如何在Rails中扩展ActiveRecord对象的功能?
- 14. 通过JSON API扩展Activerecord
- 15. ActiveRecord :: Base deprecated destroy method
- 16. 如何在Julia中扩展方法Base.∘
- 17. Rails 3 - 扩展ActionController
- 18. 为什么新的Base()不能传递给<?扩展Base>?
- 19. Rails:扩展alias_method_chain
- 20. 如何扩展“保存!”方法在ActiveRecord?
- 21. RoR扩展ActiveRecord ::关系与unsutroy_all
- 22. rails activerecord扩展数据集以包含joineddata
- 23. 扩展model.save方法Rails
- 24. ActiveRecord :: Base before_validation with conditional not triggered
- 25. ActiveRecord :: Base Extension不工作
- 26. ActiveRecord :: Base Class不可变?
- 27. 理解的ActiveRecord :: Base类名
- 28. Rails - 扩展Ruby Gem
- 29. 扩展一个rails插件
- 30. Rails的ActiveRecord的和:追加来自ActiveRecord的继承方法,模型:: Base的
什么样的扩展?我们真的需要更多的继续。 – jonnii 2010-02-24 19:51:06