提问者:小点点

如何在Rails 4中使用关注点


默认的Rails 4项目生成器现在在控制器和模型下创建目录“关注点”。我找到了一些关于如何使用路由问题的解释,但没有关于控制器或模型的解释。

我很确定这与社区目前的“DCI趋势”有关,我想试一试。

问题是,我应该如何使用这个特性,是否有一个关于如何定义命名/类层次结构的约定来使它工作?如何在模型或控制器中包含关注点?


共3个答案

匿名用户

所以我自己找出来的。这实际上是一个非常简单但强大的概念。它与代码重用有关,如下面的示例所示。基本上,这个想法是提取常见的和/或特定于上下文的代码块,以清理模型,避免它们变得过于肥胖和混乱。

作为一个例子,我将提出一个众所周知的模式,标记模式:

# app/models/product.rb
class Product
  include Taggable

  ...
end

# app/models/concerns/taggable.rb
# notice that the file name has to match the module name 
# (applying Rails conventions for autoloading)
module Taggable
  extend ActiveSupport::Concern

  included do
    has_many :taggings, as: :taggable
    has_many :tags, through: :taggings

    class_attribute :tag_limit
  end

  def tags_string
    tags.map(&:name).join(', ')
  end

  def tags_string=(tag_string)
    tag_names = tag_string.to_s.split(', ')

    tag_names.each do |tag_name|
      tags.build(name: tag_name)
    end
  end

  # methods defined here are going to extend the class, not the instance of it
  module ClassMethods

    def tag_limit(value)
      self.tag_limit_value = value
    end

  end

end

因此,在产品示例之后,您可以将Taggable添加到您想要的任何类,并共享其功能。

DHH很好地解释了这一点:

在Rails4中,我们将邀请程序员使用默认的app/models/concerns和app/controllers/concerns目录,这些目录自动成为加载路径的一部分。再加上ActiveSupport::Concern包装器,它就足够支持这个轻量级的分解机制了。

匿名用户

我一直在阅读关于使用模型关注来皮肤化脂肪模型以及干燥你的模型代码。下面是一个举例说明:

考虑一篇文章模型、一个事件模型和一个评论模型。一篇文章或一个事件有很多评论。评论属于文章或事件。

传统上,模型可能看起来像这样:

评论模型:

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中提取此公共代码。

为此,请创建一个可注释的。应用程序/模型/关注点中的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

考虑一个事件模型。一个活动有许多与会者和评论。

通常,事件模型可能如下所示

class Event < ActiveRecord::Base   
  has_many :comments
  has_many :attenders


  def find_first_comment
    # for the given article/event returns the first comment
  end

  def find_comments_with_word(word)
    # for the given event returns an array of comments which contain the given word
  end 

  def self.least_commented
    # finds the event which has the least number of comments
  end

  def self.most_attended
    # returns the event with most number of attendes
  end

  def has_attendee(attendee_id)
    # returns true if the event has the mentioned attendee
  end
end

具有许多关联和其他关联的模型倾向于积累越来越多的代码并变得不可管理。关注点提供了一种将脂肪模块皮肤化的方法,使其更加模块化,易于理解。

可以使用以下关注点重构上述模型:创建一个attendeable。rb可注释。rb应用程序/模型/关注点/事件文件夹中的文件

注意。铷

module Attendable
  extend ActiveSupport::Concern

  included do 
    has_many :attenders
  end

  def has_attender(attender_id)
    # returns true if the event has the mentioned attendee
  end

  module ClassMethods
    def most_attended
      # returns the event with most number of attendes
    end
  end
end

commentable.rb

module Commentable
  extend ActiveSupport::Concern

  included do 
    has_many :comments
  end

  def find_first_comment
    # for the given article/event returns the first comment
  end

  def find_comments_with_word(word)
    # for the given event returns an array of comments which contain the given word
  end

  module ClassMethods
    def least_commented
      # finds the event which has the least number of comments
    end
  end
end

现在使用关注,您的事件模型减少到

class Event < ActiveRecord::Base
  include Commentable
  include Attendable
end

*在使用关注时,建议使用基于领域的分组,而不是技术分组。基于域的分组类似于可注释、可拍照、可关注。技术分组将意味着验证方法、查找方法等

匿名用户

值得一提的是,许多人认为使用关注点是个坏主意。

  1. 像这个家伙

一些原因:

  1. 在幕后发生了一些黑魔法-关注的是修补includemethod,还有一个完整的依赖处理系统-对于一些微不足道的好的Ruby mixin模式来说太复杂了

担心是一种很容易打中自己腿的方式,要小心。