我已經做了一些關於如何擴展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