xpe*_*int 160 ruby-on-rails extend rails-activerecord
我已经做了一些关于如何扩展ActiveRecord:Base类的阅读,所以我的模型会有一些特殊的方法.扩展它的简单方法是什么(逐步教程)?
Har*_*tty 336
有几种方法:
阅读ActiveSupport :: Concern文档以获取更多详细信息.
创建目录中调用active_record_extension.rb的lib文件.
require 'active_support/concern'
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)
Run Code Online (Sandbox Code Playgroud)
在被config/initializers调用的目录中创建一个文件,extensions.rb并将以下行添加到该文件中:
require "active_record_extension"
Run Code Online (Sandbox Code Playgroud)
请参阅Toby的回答.
在config/initializers名为的目录中创建一个文件active_record_monkey_patch.rb.
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
Run Code Online (Sandbox Code Playgroud)
关于Jamie Zawinski的正则表达式的着名引用可以重新用于说明与猴子修补相关的问题.
有些人在遇到问题时会想"我知道,我会使用猴子补丁."现在他们有两个问题.
猴子修补简单快捷.但是,节省的时间和精力总是在未来的某个时候被提取出来; 复利.这些天我限制猴子修补,以快速在rails控制台中原型解决方案.
Tob*_*ede 70
您可以只扩展类并简单地使用继承.
class AbstractModel < ActiveRecord::Base
self.abstract_class = true
end
class Foo < AbstractModel
end
class Bar < AbstractModel
end
Run Code Online (Sandbox Code Playgroud)
nik*_*ola 21
你也可以使用ActiveSupport::Concern和更多Rails核心惯用法,如:
module MyExtension
extend ActiveSupport::Concern
def foo
end
module ClassMethods
def bar
end
end
end
ActiveRecord::Base.send(:include, MyExtension)
Run Code Online (Sandbox Code Playgroud)
[编辑]跟随@daniel的评论
然后,所有模型都将该方法foo作为实例方法ClassMethods包含在内,并将方法 作为类方法包含在内.例如,FooBar < ActiveRecord::Base你将拥有:FooBar.bar和FooBar#foo
http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
Aad*_*ain 17
使用Rails 4,使用关注点模块化和干燥模型的概念已经成为亮点.
问题基本上允许您在单个模块中将模型的相似代码或多个模型分组,然后在模型中使用此模块.这是一个例子:
考虑文章模型,事件模型和评论模型.文章或A事件有很多评论.评论属于文章或事件.
传统上,模型可能如下所示:
评论模型:
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
Run Code Online (Sandbox Code Playgroud)
文章模型:
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
Run Code Online (Sandbox Code Playgroud)
事件模型
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
Run Code Online (Sandbox Code Playgroud)
我们可以注意到,事件和文章模型都有一个共同的重要代码.使用关注点,我们可以在单独的模块中提取此公共代码.
为此,在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
Run Code Online (Sandbox Code Playgroud)
现在您的模型看起来像这样:
评论模型:
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
Run Code Online (Sandbox Code Playgroud)
文章模型:
class Article < ActiveRecord::Base
include Commentable
end
Run Code Online (Sandbox Code Playgroud)
事件模型
class Event < ActiveRecord::Base
include Commentable
end
Run Code Online (Sandbox Code Playgroud)
在使用Concerns时我想强调的一点是,应该将关注点用于"基于域"的分组而不是"技术"分组.例如,域分组就像"可评论","可标记"等.基于技术的分组将类似于"FinderMethods","ValidationMethods".
希望写作有帮助:)
步骤1
module FooExtension
def foo
puts "bar :)"
end
end
ActiveRecord::Base.send :include, FooExtension
Run Code Online (Sandbox Code Playgroud)
第2步
# Require the above file in an initializer (in config/initializers)
require 'lib/foo_extension.rb'
Run Code Online (Sandbox Code Playgroud)
第3步
There is no step 3 :)
Run Code Online (Sandbox Code Playgroud)
滑轨5提供了用于扩展的内置机制ActiveRecord::Base。
这可以通过提供额外的层来实现:
# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
# put your extensions here
end
Run Code Online (Sandbox Code Playgroud)
所有模型都继承自该模型:
class Post < ApplicationRecord
end
Run Code Online (Sandbox Code Playgroud)
参见例如此博客文章。
在 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
Run Code Online (Sandbox Code Playgroud)
假设特殊方法模块需要在所有模型中可用,请将其包含在 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
Run Code Online (Sandbox Code Playgroud)
如果您希望将模块中定义的方法作为类方法,请将模块扩展为 ApplicationRecord。
# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
extend SpecialMethods
end
Run Code Online (Sandbox Code Playgroud)
希望它对其他人有帮助!
| 归档时间: |
|
| 查看次数: |
64839 次 |
| 最近记录: |