如何在Rails 4中使用問題

本文翻譯自:How to use concerns in Rails 4

The default Rails 4 project generator now creates the directory "concerns" under controllers and models. 默認的Rails 4項目生成器現在在控制器和模型下創建目錄“Concer”。 I have found some explanations about how to use routing concerns, but nothing about controllers or models. 我找到了一些關於如何使用路由問題的解釋,但沒有關於控制器或模型的解釋。

I am pretty sure it has to do with the current "DCI trend" in the community and would like to give it a try. 我很確定它與社區當前的“DCI趨勢”有關,並且想嘗試一下。

The question is, how am I supposed to use this feature, is there a convention on how to define the naming / class hierarchy in order to make it work? 問題是,我應該如何使用此功能,是否有關於如何定義命名/類層次結構以使其工作的約定? How can I include a concern in a model or controller? 如何在模型或控制器中包含問題?


#1樓

參考:https://stackoom.com/question/z0zX/如何在Rails-中使用問題


#2樓

So I found it out by myself. 所以我自己發現了它。 It is actually a pretty simple but powerful concept. 它實際上是一個非常簡單但功能強大的概念。 It has to do with code reuse as in the example below. 它與代碼重用有關,如下例所示。 Basically, the idea is to extract common and / or context specific chunks of code in order to clean up the models and avoid them getting too fat and messy. 基本上,這個想法是提取常見的和/或特定於上下文的代碼塊,以便清理模型並避免它們變得太胖和混亂。

As an example, I'll put one well known pattern, the taggable pattern: 作爲一個例子,我將放置一個衆所周知的模式,可標記的模式:

# 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

So following the Product sample, you can add Taggable to any class you desire and share its functionality. 因此,按照Product示例,您可以將Taggable添加到您想要的任何類並共享其功能。

This is pretty well explained by DHH : DHH很好地解釋了這一點:

In Rails 4, we're going to invite programmers to use concerns with the default app/models/concerns and app/controllers/concerns directories that are automatically part of the load path. 在Rails 4中,我們將邀請程序員使用默認app / models / concerns和app / controllers / concerns目錄中的問題,這些目錄自動成爲加載路徑的一部分。 Together with the ActiveSupport::Concern wrapper, it's just enough support to make this light-weight factoring mechanism shine. 與ActiveSupport :: Concern包裝一起,它足以支持這種輕量級因子機制。


#3樓

This post helped me understand concerns. 這篇文章幫助我理解了問題。

# app/models/trader.rb
class Trader
  include Shared::Schedule
end

# app/models/concerns/shared/schedule.rb
module Shared::Schedule
  extend ActiveSupport::Concern
  ...
end

#4樓

I have been reading about using model concerns to skin-nize fat models as well as DRY up your model codes. 我一直在閱讀有關使用模型問題來修飾脂肪模型以及幹掉模型代碼的問題。 Here is an explanation with examples: 以下是對示例的解釋:

1) DRYing up model codes 1)幹掉型號代碼

Consider a Article model, a Event model and a Comment model. 考慮文章模型,事件模型和評論模型。 An article or an event has many comments. 文章或事件有很多評論。 A comment belongs to either Article or Event. 評論屬於文章或事件。

Traditionally, the models may look like this: 傳統上,模型可能如下所示:

Comment Model: 評論模型:

class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
end

Article Model: 文章模型:

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

Event Model 事件模型

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

As we can notice, there is a significant piece of code common to both Event and Article. 我們可以注意到,事件和文章都有一個共同的重要代碼。 Using concerns we can extract this common code in a separate module Commentable. 使用關注點,我們可以在單獨的模塊中提取此公共代碼。

For this create a commentable.rb file in app/models/concerns. 爲此,在app / models / 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

And now your models look like this : 現在您的模型看起來像這樣:

Comment Model: 評論模型:

class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
end

Article Model: 文章模型:

class Article < ActiveRecord::Base
  include Commentable
end

Event Model: 活動模型:

class Event < ActiveRecord::Base
  include Commentable
end

2) Skin-nizing Fat Models. 2)皮膚肥胖模型。

Consider a Event model. 考慮事件模型。 A event has many attenders and comments. 一個活動有很多參與者和評論。

Typically, the event model might look like this 通常,事件模型可能如下所示

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

Models with many associations and otherwise have tendency to accumulate more and more code and become unmanageable. 具有許多關聯的模型,否則傾向於積累越來越多的代碼並變得難以管理。 Concerns provide a way to skin-nize fat modules making them more modularized and easy to understand. 關注點提供了一種皮膚化脂肪模塊的方法,使它們更加模塊化和易於理解。

The above model can be refactored using concerns as below: Create a attendable.rb and commentable.rb file in app/models/concerns/event folder 可以使用以下關注點重構上述模型:在app / models / concerns / event文件夾中創建attendable.rbcommentable.rb文件

attendable.rb attendable.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 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

And now using Concerns, your Event model reduces to 現在使用Concerns,您的事件模型減少到

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

* While using concerns its advisable to go for 'domain' based grouping rather than 'technical' grouping. *在使用問題時,建議採用“域名”分組而不是“技術”分組。 Domain Based grouping is like 'Commentable', 'Photoable', 'Attendable'. 基於域的分組就像“可評論”,“可照片”,“可以參加”。 Technical grouping will mean 'ValidationMethods', 'FinderMethods' etc 技術分組將意味着'ValidationMethods','FinderMethods'等


#5樓

In concerns make file filename.rb 關注make文件filename.rb

For example I want in my application where attribute create_by exist update there value by 1, and 0 for updated_by 例如,我想在我的應用程序中,屬性create_by存在,將值更新爲1,更新爲update_by

module TestConcern 
  extend ActiveSupport::Concern

  def checkattributes   
    if self.has_attribute?(:created_by)
      self.update_attributes(created_by: 1)
    end
    if self.has_attribute?(:updated_by)
      self.update_attributes(updated_by: 0)
    end
  end

end

If you want to pass arguments in action 如果你想傳遞參數

included do
   before_action only: [:create] do
     blaablaa(options)
   end
end

after that include in your model like this: 之後,在您的模型中包含如下:

class Role < ActiveRecord::Base
  include TestConcern
end

#6樓

It's worth to mention that using concerns is considered bad idea by many. 值得一提的是,使用顧慮被很多人認爲是壞主意。

  1. like this guy 喜歡這個傢伙
  2. and this one 還有這個

Some reasons: 一些原因:

  1. There is some dark magic happening behind the scenes - Concern is patching include method, there is a whole dependency handling system - way too much complexity for something that's trivial good old Ruby mixin pattern. 幕後發生了一些黑暗魔法 - 關注是修補include方法,有一個完整的依賴處理系統 - 對於一些瑣碎的好舊Ruby混合模式的東西太複雜了。
  2. Your classes are no less dry. 你的課程也不幹。 If you stuff 50 public methods in various modules and include them, your class still has 50 public methods, it's just that you hide that code smell, sort of put your garbage in the drawers. 如果你在各種模塊中填充50個公共方法幷包含它們,你的類仍然有50個公共方法,只是你隱藏了代碼味道,有點把你的垃圾放在抽屜裏。
  3. Codebase is actually harder to navigate with all those concerns around. 代碼庫實際上更難以解決所有這些問題。
  4. Are you sure all members of your team have same understanding what should really substitute concern? 您確定您的團隊中的所有成員都有同樣的理解應該真正替代關注點嗎?

Concerns are easy way to shoot yourself in the leg, be careful with them. 關注是輕鬆拍攝腿部的方法,小心使用它們。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章