모델에 특별한 메소드가 있도록 ActiveRecord : Base 클래스를 확장하는 방법에 대해 약간의 독서를했습니다. 그것을 확장하는 쉬운 방법은 무엇입니까 (단계별 튜토리얼)?
답변
몇 가지 접근 방식이 있습니다.
ActiveSupport :: Concern 사용 (선호)
자세한 내용은 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)
config/initializers
라는 디렉토리에 파일을 작성하고 파일에 extensions.rb
다음 행을 추가하십시오.
require "active_record_extension"
상속 (권장)
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
Jamie Zawinski의 정규 표현식에 대한 유명한 인용문은 원숭이 패치와 관련된 문제를 설명하기 위해 용도 변경 될 수 있습니다.
어떤 사람들은 문제에 직면했을 때“나는 원숭이 패치를 사용할 것입니다”라고 생각합니다. 이제 두 가지 문제가 있습니다.
원숭이 패치는 쉽고 빠릅니다. 그러나 절약 된 시간과 노력은 항상 언젠가 다시 추출됩니다. 복리 관심. 요즘에는 레일 콘솔에서 솔루션을 신속하게 프로토 타입하기 위해 원숭이 패치를 제한합니다.
답변
클래스를 확장하고 상속을 사용하면됩니다.
class AbstractModel < ActiveRecord::Base
self.abstract_class = true
end
class Foo < AbstractModel
end
class Bar < AbstractModel
end
답변
다음 ActiveSupport::Concern
과 같은 Rails 핵심 관용어를 더 많이 사용할 수 있습니다 .
module MyExtension
extend ActiveSupport::Concern
def foo
end
module ClassMethods
def bar
end
end
end
ActiveRecord::Base.send(:include, MyExtension)
@daniel의 의견에 따라 [편집]
그런 다음 모든 모델에 메소드 foo
가 인스턴스 메소드로 ClassMethods
포함되고 메소드가 클래스 메소드 로 포함됩니다. 예는에 FooBar < ActiveRecord::Base
, 당신은 것입니다 : FooBar.bar
및FooBar#foo
http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
답변
Rails 4에서는 모델을 모듈화하고 건조시키기 위해 우려 사항을 사용하는 개념이 강조되었습니다.
우려 사항은 기본적으로 하나의 모듈에서 유사한 모델 코드 또는 여러 모델을 그룹화 한 다음이 모듈을 모델에서 사용할 수 있습니다. 예를 들면 다음과 같습니다.
기사 모델, 이벤트 모델 및 주석 모델을 고려하십시오. 기사 또는 이벤트에는 많은 의견이 있습니다. 의견은 기사 또는 이벤트에 속합니다.
전통적으로 모델은 다음과 같습니다.
댓글 모델 :
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에서 추출 할 수 있습니다.
이를 위해 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
이제 모델은 다음과 같습니다.
댓글 모델 :
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
기사 모델 :
class Article < ActiveRecord::Base
include Commentable
end
이벤트 모델
class Event < ActiveRecord::Base
include Commentable
end
관심사를 사용하면서 강조하고 싶은 한 가지는 ‘기술적’그룹화보다는 ‘도메인 기반’그룹화에 관심사를 사용해야한다는 것입니다. 예를 들어 도메인 그룹은 ‘Commentable’, ‘Taggable’등과 같습니다. 기술 기반 그룹은 ‘FinderMethods’, ‘ValidationMethods’와 같습니다.
다음은 모델의 관심사를 이해하는 데 매우 유용한 게시물 의 링크 입니다.
글쓰기가 도움이되기를 바랍니다 🙂
답변
1 단계
module FooExtension
def foo
puts "bar :)"
end
end
ActiveRecord::Base.send :include, FooExtension
2 단계
# Require the above file in an initializer (in config/initializers)
require 'lib/foo_extension.rb'
3 단계
There is no step 3 :)
답변
Rails 5는 확장을위한 내장 메커니즘을 제공합니다 ActiveRecord::Base
.
추가 레이어를 제공하면됩니다.
# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
# put your extensions here
end
모든 모델은 그 모델에서 상속됩니다.
class Post < ApplicationRecord
end
예를 들어이 블로그 게시물을 참조하십시오 .
답변
이 주제에 추가하기 위해 그러한 확장을 테스트하는 방법을 연구하는 데 잠시 시간을 보냈습니다 ( ActiveSupport::Concern
경로를 따라갔습니다 ).
내 확장 프로그램을 테스트하기위한 모델을 설정하는 방법은 다음과 같습니다.
describe ModelExtensions do
describe :some_method do
it 'should return the value of foo' do
ActiveRecord::Migration.create_table :test_models do |t|
t.string :foo
end
test_model_class = Class.new(ActiveRecord::Base) do
def self.name
'TestModel'
end
attr_accessible :foo
end
model = test_model_class.new(:foo => 'bar')
model.some_method.should == 'bar'
end
end
end