Rails 4에서 관심사를 사용하는 방법
기본 Rails 4 프로젝트 생성기는 이제 컨트롤러 및 모델 아래에 "concerns"디렉토리를 생성합니다. 라우팅 문제를 사용하는 방법에 대한 설명을 찾았지만 컨트롤러 나 모델에 대한 설명은 없습니다.
나는 그것이 커뮤니티의 현재 "DCI 트렌드"와 관련이 있다고 확신하고 그것을 시도하고 싶습니다.
문제는이 기능을 어떻게 사용해야하는지, 작동하도록 이름 지정 / 클래스 계층을 정의하는 방법에 대한 규칙이 있습니까? 모델 또는 컨트롤러에 문제를 어떻게 포함시킬 수 있습니까?
그래서 나는 그것을 스스로 발견했습니다. 실제로 매우 간단하지만 강력한 개념입니다. 아래 예제와 같이 코드 재사용과 관련이 있습니다. 기본적으로 아이디어는 모델을 정리하고 너무 뚱뚱하고 지저분 해지는 것을 방지하기 위해 공통 및 / 또는 컨텍스트 특정 코드 덩어리를 추출하는 것입니다.
예를 들어 잘 알려진 패턴 인 태그 지정 가능 패턴을 넣겠습니다.
# 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에 의해 꽤 잘 설명됩니다 .
Rails 4에서는 자동으로로드 경로의 일부인 기본 app / models / concerns 및 app / controllers / concerns 디렉토리에 대한 문제를 사용하도록 프로그래머를 초대 할 것입니다. ActiveSupport :: Concern 래퍼와 함께이 경량 팩터링 메커니즘을 빛나게하는 데 충분한 지원입니다.
나는 모델 문제 를 사용하여 뚱뚱한 모델을 피부 화하고 모델 코드를 건조시키는 것에 대해 읽었 습니다. 예를 들어 설명은 다음과 같습니다.
1) 모델 코드 건조
기사 모델, 이벤트 모델 및 댓글 모델을 고려하십시오. 기사 나 이벤트에 댓글이 많습니다. 댓글은 기사 또는 이벤트에 속합니다.
전통적으로 모델은 다음과 같이 보일 수 있습니다.
댓글 모델 :
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 모두에 공통된 중요한 코드가 있습니다. 관심사를 사용하여 별도의 모듈 Commentable에서이 공통 코드를 추출 할 수 있습니다.
이를 위해 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
이제 모델은 다음과 같습니다.
댓글 모델 :
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
기사 모델 :
class Article < ActiveRecord::Base
include Commentable
end
이벤트 모델 :
class Event < ActiveRecord::Base
include Commentable
end
2) 피부 나이 화 지방 모델.
이벤트 모델을 고려하십시오. 이벤트에는 많은 참석자와 댓글이 있습니다.
일반적으로 이벤트 모델은 다음과 같습니다.
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
연관성이 많고 그렇지 않은 모델은 점점 더 많은 코드를 축적하고 관리 할 수 없게되는 경향이 있습니다. 우려 사항은 지방 모듈을 피부 화하는 방법을 제공하여 모듈화되고 이해하기 쉽게 만듭니다.
위의 모델은 아래와 같은 관심사를 사용하여 리팩토링 할 수 있습니다. app / models / concerns / event 폴더에 attendable.rb
및 commentable.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
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
이제 Concerns를 사용하면 이벤트 모델이
class Event < ActiveRecord::Base
include Commentable
include Attendable
end
* 사용하는 동안 '기술적'그룹화보다는 '도메인'기반 그룹화를 사용하는 것이 좋습니다. 도메인 기반 그룹화는 '주석 가능', '사진 가능', '참석 가능'과 같습니다. 기술 그룹은 'ValidationMethods', 'FinderMethods'등을 의미합니다.
우려 사항을 사용하는 것은 많은 사람들에게 나쁜 생각으로 간주된다는 점을 언급 할 가치가 있습니다.
몇 가지 이유 :
- 배후에서 어떤 어두운 마법이 일어나고 있습니다. 문제는 패치
include
방법이고, 전체 종속성 처리 시스템이 있습니다. 사소하고 좋은 오래된 Ruby 믹스 인 패턴에 비해 너무 복잡합니다. - 수업이 덜 건조하지 않습니다. 다양한 모듈에 50 개의 퍼블릭 메서드를 채우고 포함 시키면 클래스에는 여전히 50 개의 퍼블릭 메서드가 있습니다. 단지 코드 냄새를 숨기고 쓰레기를 서랍에 넣는 것입니다.
- 코드베이스는 실제로 이러한 모든 문제를 해결하기가 더 어렵습니다.
- 팀의 모든 구성원이 실제로 우려 사항을 대체해야하는 사항을 동일하게 이해하고 있습니까?
우려 사항은 다리를 쏘는 쉬운 방법이므로 조심하십시오.
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
I felt most of the examples here demonstrating the power of module
rather than how ActiveSupport::Concern
adds value to module
.
Example 1: More readable modules.
So without concerns this how a typical module
will be.
module M
def self.included(base)
base.extend ClassMethods
base.class_eval do
scope :disabled, -> { where(disabled: true) }
end
end
def instance_method
...
end
module ClassMethods
...
end
end
After refactoring with ActiveSupport::Concern
.
require 'active_support/concern'
module M
extend ActiveSupport::Concern
included do
scope :disabled, -> { where(disabled: true) }
end
class_methods do
...
end
def instance_method
...
end
end
You see instance methods, class methods and included block are less messy. Concerns will inject them appropriately for you. That's one advantage of using ActiveSupport::Concern
.
Example 2: Handle module dependencies gracefully.
module Foo
def self.included(base)
base.class_eval do
def self.method_injected_by_foo_to_host_klass
...
end
end
end
end
module Bar
def self.included(base)
base.method_injected_by_foo_to_host_klass
end
end
class Host
include Foo # We need to include this dependency for Bar
include Bar # Bar is the module that Host really needs
end
In this example Bar
is the module that Host
really needs. But since Bar
has dependency with Foo
the Host
class have to include Foo
(but wait why Host
want to know about Foo
? can it be avoided?).
So Bar
adds dependency everywhere it goes. And **order of inclusion also matters here. **This adds lot of complexity/dependency to huge code base.
After refactoring with ActiveSupport::Concern
require 'active_support/concern'
module Foo
extend ActiveSupport::Concern
included do
def self.method_injected_by_foo_to_host_klass
...
end
end
end
module Bar
extend ActiveSupport::Concern
include Foo
included do
self.method_injected_by_foo_to_host_klass
end
end
class Host
include Bar # It works, now Bar takes care of its dependencies
end
Now it looks simple.
If you are thinking why cant we add Foo
dependency in Bar
module itself ? That wont work since method_injected_by_foo_to_host_klass
have to be injected in class thats including Bar
not on Bar
module itself.
Source: Rails ActiveSupport::Concern
In concerns make file filename.rb
For example I want in my application where attribute create_by exist update there value by 1, and 0 for updated_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
참고URL : https://stackoverflow.com/questions/14541823/how-to-use-concerns-in-rails-4
'Program Tip' 카테고리의 다른 글
모든 예외 포착 정보 (0) | 2020.10.02 |
---|---|
Python에서 테스트 없음 (0) | 2020.10.02 |
jQuery : 선택한 요소 태그 이름 가져 오기 (0) | 2020.10.02 |
서비스 대 공장에 대해 혼동 (0) | 2020.10.02 |
postgres : 사용자를 수퍼 유저로 업그레이드 하시겠습니까? (0) | 2020.10.02 |