1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

edit of previous content

explains how to add/override engine classes in the main rails app via
1) Class#class_eval
2) ActiveSupport::Concern
This commit is contained in:
Weston Platter 2012-08-04 19:12:24 -05:00
parent 957e3d4966
commit 39674d1e90

View file

@ -655,15 +655,17 @@ This tells the application that you still want to perform a +GET+ request to the
h3. Improving engine functionality
This section looks at overriding or adding functionality to the views, controllers and models provided by an engine.
This section explains how to add and/or override engine MVC functionality in the main Rails application.
h4. Overriding Models
h4. Overriding Models and Controllers
Engine Models can be extended by (1) implementing decorators, or (2) including modules.
Engine model and controller classes can be extended by open classing them in the main Rails application (since model and controller classes are just Ruby classes that inherit Rails specific functionality). Open classing an Engine class redefines it for use in the main applicaiton. This is usually implemented by using the decorator pattern.
h5. Decorators
For simple class modifications use Class#class_eval, and for complex class modifications, consider using ActiveSupport::Concern.
Decorators extends Engine's model classes in the main application by open classing Engine models at run time execution.
h5. Implementing Decorator Pattern Using Class#class_eval
**Adding** Post#time_since_created,
<ruby>
# MyApp/app/decorators/models/blorgh/post_decorator.rb
@ -675,15 +677,48 @@ Blorgh::Post.class_eval do
end
</ruby>
h5. Modules
<ruby>
# Blorgh/app/models/post.rb
The other strategy is to create modules within the Engine holding all the models' code and include these in the respective Engine's model classes. Thus the Engine's model classes contain a mere include line referencing the respective module.
class Post < ActiveRecord::Base
:has_many :comments
end
</ruby>
Engine models can be overriden in the main application by creating a file with the Engine's same namespace and including the module originally referenced in the Engine's model class. ["**ActiveSupport::Concern**":http://edgeapi.rubyonrails.org/classes/ActiveSupport/Concern.html] helps manage the correct ordering of module dependencies at run time (it's worth it to reach the linked documentation).
**Overriding** Post#summary
<ruby>
# MyApp/app/decorators/models/blorgh/post_decorator.rb
Blorgh::Post.class_eval do
def summary
"#{title} - #{truncate(text)}"
end
end
</ruby>
<ruby>
# Blorgh/app/models/post.rb
class Post < ActiveRecord::Base
:has_many :comments
def summary
"#{title}"
end
end
</ruby>
h5. Implementing Decorator Pattern Using ActiveSupport::Concern
Using Class#class_eval is great for simple adjustments, but for more complex class modifications, you might want to consider using ActiveSupport::Concern. ["**ActiveSupport::Concern**":http://edgeapi.rubyonrails.org/classes/ActiveSupport/Concern.html] helps manage load order of interlinked dependencies at run time allowing you to significantly modularize your code.
**Adding** Post#time_since_created<br/>
**Overriding** Post#summary
<ruby>
# MyApp/app/models/blorgh/post.rb
# overrides Blorgh's original Post model
class Blorgh::Post < ActiveRecord::Base
include Blorgh::Concerns::Models::Post
@ -691,24 +726,30 @@ class Blorgh::Post < ActiveRecord::Base
def time_since_created
Time.current - created_at
end
def summary
"#{title} - #{truncate(text)}"
end
end
</ruby>
<ruby>
# Blorgh/app/models/post.rb
# this class is overriden by the MyApp Post model
class Post < ActiveRecord::Base
include Blorgh::Concerns::Models::Post
end
</ruby>
<ruby>
# Blorgh/lib/concerns/models/post
# Blorgh/app/concerns/models/post
module Blorg::Concerns::Models::Post
module Blorgh::Concerns::Models::Post
extend ActiveSupport::Concern
# 'included do' causes the code within to be evaluated in the conext
# where it is included, rather be executed in the module's context.
# 'included do' causes the included code to be evaluated in the
# conext where it is included (post.rb), rather than be
# executed in the module's context (blorgh/concerns/models/post).
included do
attr_accessor :author_name
belongs_to :author, :class_name => "User"
@ -722,9 +763,8 @@ module Blorg::Concerns::Models::Post
end
end
# methods defined here will be instance methods by default
def some_method
'some method string'
def summary
"#{title}"
end
module ClassMethods