当前位置:  开发笔记 > 后端 > 正文

在多个模型中放置常见代码的位置?

如何解决《在多个模型中放置常见代码的位置?》经验,为你挑选了5个好方法。

我有两个包含相同方法的模型:

def foo
  # do something
end

我应该把它放在哪里?

我知道常用代码在Rails应用程序的lib目录中.

但是如果我把它放在一个lib名为' Foo' 的新类中,并且我需要将它的功能添加到我的两个中ActiveRecord models,我是这样做的:

class A < ActiveRecord::Base
includes Foo

class B < ActiveRecord::Base
includes Foo

然后这两个AB将包含foo就像我在每个定义的方法就可以了?



1> Phil Ross..:

创建一个模块,您可以将其放在lib目录中:

module Foo
  def foo
    # do something
  end
end

然后include,您可以在每个模型类中使用该模块:

class A < ActiveRecord::Base
  include Foo
end

class B < ActiveRecord::Base
  include Foo
end

AB车型现在有一个foo定义的方法.

如果您使用模块名称和文件名称(例如foo.rb中的Foo和foo_bar.rb中的FooBar)遵循Rails命名约定,那么Rails将自动为您加载文件.否则,您将需要使用require_dependency 'file_name'加载您的lib文件.



2> Aaron Rustad..:

你真的有两个选择:

    将模块用于通用逻辑并将其包含在A和B中

    使用扩展ActiveRecord的公共类C并使A和B扩展C.

如果共享功能不是每个类的核心,则使用#1,但适用于每个类.例如:

(app/lib/serializable.rb)
module Serializable
  def serialize
    # do something to serialize this object
  end
end

如果共享功能对于每个类是通用的并且A&B共享自然关系,则使用#2:

(app/models/letter.rb)
class Letter < ActiveRecord::Base
  def cyrilic_equivilent
    # return somethign similar
  end
end

class A < Letter
end

class B < Letter
end


选项#2使Rails假设A和B都存储在一个名为"letters"的表中.如果你只想要共享逻辑,同时将A和B保存在不同的表中,那么抽象的父类就是可行的方法,正如@Ron在下面指出的那样(http://stackoverflow.com/a/20749863/2657571).

3> bronson..:

这是我如何做到的...首先创建mixin:

module Slugged
  extend ActiveSupport::Concern

  included do
    has_many :slugs, :as => :target
    has_one :slug, :as => :target, :order => :created_at
  end
end

然后将其混合到需要它的每个模型中:

class Sector < ActiveRecord::Base
  include Slugged

  validates_uniqueness_of :name
  etc
end

它几乎是漂亮的!

为了完成这个例子,虽然这与问题无关,但这是我的slug模型:

class Slug < ActiveRecord::Base
  belongs_to :target, :polymorphic => true
end



4> nicholaides..:

例如,一种选择是将它们放在新目录中app/models/modules/.然后,您可以将其添加到config/environment.rb:

Dir["#{RAILS_ROOT}/app/models/modules/*.rb"].each do |filename|
  require filename
end

这将require是该目录中的每个文件,因此如果您在模块目录中放置如下文件:

module SharedMethods
  def foo
    #...
  end
end

然后你可以在模型中使用它,因为它会自动加载:

class User < ActiveRecord::Base
  include SharedMethods
end

这种方法比将这些mixin放在lib目录中更有条理,因为它们靠近使用它们的类.



5> Ron..:

如果您需要ActiveRecord :: Base代码作为常用功能的一部分,那么使用抽象类也很有用.就像是:

class Foo < ActiveRecord::Base
  self.abstract_class = true
  #Here ActiveRecord specific code, for example establish_connection to a different DB.
end

class A < Foo; end
class B < Foo; end

就如此容易.此外,如果代码与ActiveRecord无关,请查找ActiveSupport::Concerns更好的方法.

推荐阅读
拾味湖
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有