active_decorator 0.8.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/.travis.yml +92 -25
- data/CHANGELOG.md +52 -0
- data/Gemfile +1 -6
- data/README.md +68 -49
- data/Rakefile +5 -1
- data/active_decorator.gemspec +15 -4
- data/gemfiles/Gemfile-rails.4.2.x +4 -5
- data/gemfiles/Gemfile-rails.5.0.x +3 -5
- data/gemfiles/Gemfile-rails.5.1.x +6 -0
- data/gemfiles/Gemfile-rails.5.2.x +7 -0
- data/gemfiles/Gemfile-rails.6.0.x +7 -0
- data/gemfiles/Gemfile-rails.6.1.x +8 -0
- data/gemfiles/Gemfile-rails.edge +18 -0
- data/lib/active_decorator/config.rb +8 -1
- data/lib/active_decorator/decorated.rb +5 -0
- data/lib/active_decorator/decorator.rb +52 -20
- data/lib/active_decorator/helpers.rb +21 -7
- data/lib/active_decorator/monkey/abstract_controller/rendering.rb +3 -0
- data/lib/active_decorator/monkey/action_controller/base/rescue_from.rb +5 -2
- data/lib/active_decorator/monkey/action_view/collection_renderer.rb +12 -0
- data/lib/active_decorator/monkey/action_view/object_renderer.rb +12 -0
- data/lib/active_decorator/monkey/action_view/partial_renderer.rb +22 -8
- data/lib/active_decorator/monkey/active_record/associations.rb +61 -0
- data/lib/active_decorator/railtie.rb +36 -2
- data/lib/active_decorator/version.rb +2 -1
- data/lib/active_decorator/view_context.rb +19 -21
- data/lib/active_decorator.rb +6 -1
- data/lib/generators/rails/USAGE +8 -0
- data/lib/generators/rails/decorator_generator.rb +4 -13
- data/lib/generators/rails/templates/decorator.rb +2 -0
- data/lib/generators/rspec/decorator_generator.rb +7 -4
- data/lib/generators/rspec/templates/decorator_spec.rb +4 -2
- data/lib/generators/test_unit/decorator_generator.rb +8 -4
- data/lib/generators/test_unit/templates/decorator_test.rb +4 -2
- metadata +133 -57
- data/gemfiles/Gemfile-rails.3.2.x +0 -11
- data/gemfiles/Gemfile-rails.4.0.x +0 -9
- data/gemfiles/Gemfile-rails.4.1.x +0 -9
- data/test/configuration_test.rb +0 -27
- data/test/controllers/fake_detection_test.rb +0 -9
- data/test/fake_app/app/views/authors/index.html.erb +0 -16
- data/test/fake_app/app/views/authors/show.html.erb +0 -2
- data/test/fake_app/app/views/authors/show.json.jbuilder +0 -3
- data/test/fake_app/app/views/book_mailer/thanks.text.erb +0 -1
- data/test/fake_app/app/views/books/_book.html.erb +0 -2
- data/test/fake_app/app/views/books/_book.json.jbuilder +0 -3
- data/test/fake_app/app/views/books/_book_locals.html.erb +0 -2
- data/test/fake_app/app/views/books/errata.html.erb +0 -1
- data/test/fake_app/app/views/books/error.html.erb +0 -1
- data/test/fake_app/app/views/books/index.html.erb +0 -4
- data/test/fake_app/app/views/books/purchase.html.erb +0 -1
- data/test/fake_app/app/views/books/show.html.erb +0 -4
- data/test/fake_app/app/views/movies/show.html.erb +0 -1
- data/test/fake_app/fake_app.rb +0 -198
- data/test/features/action_view_helpers_test.rb +0 -37
- data/test/features/controller_ivar_test.rb +0 -40
- data/test/features/jbuilder_test.rb +0 -15
- data/test/features/name_error_handling_test.rb +0 -17
- data/test/features/partial_test.rb +0 -28
- data/test/test_helper.rb +0 -30
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# On the fly delegation from the decorator to the decorated object and the helpers.
|
|
2
4
|
module ActiveDecorator
|
|
3
5
|
module Helpers
|
|
4
6
|
def method_missing(method, *args, &block)
|
|
5
7
|
super
|
|
6
|
-
rescue NoMethodError, NameError
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
rescue NoMethodError, NameError => e1
|
|
9
|
+
# the error is not mine, so just releases it as is.
|
|
10
|
+
raise e1 if e1.name != method
|
|
11
|
+
|
|
12
|
+
if (view_context = ActiveDecorator::ViewContext.current)
|
|
13
|
+
begin
|
|
14
|
+
view_context.send method, *args, &block
|
|
15
|
+
rescue NoMethodError => e2
|
|
16
|
+
raise e2 if e2.name != method
|
|
17
|
+
|
|
18
|
+
raise NoMethodError.new("undefined method `#{method}' for either #{self} or #{view_context}", method)
|
|
19
|
+
rescue NameError => e2
|
|
20
|
+
raise e2 if e2.name != method
|
|
21
|
+
|
|
22
|
+
raise NameError.new("undefined local variable `#{method}' for either #{self} or #{view_context}", method)
|
|
23
|
+
end
|
|
24
|
+
else # AC::API would have not view_context
|
|
25
|
+
raise e1
|
|
13
26
|
end
|
|
14
27
|
end
|
|
28
|
+
ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
|
|
15
29
|
end
|
|
16
30
|
end
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# A monkey-patch for Action Controller to pass the controller view_context over
|
|
4
|
+
# to `render` invocation in `rescue_from` block.
|
|
2
5
|
module ActiveDecorator
|
|
3
6
|
module Monkey
|
|
4
7
|
module ActionController
|
|
5
8
|
module Base
|
|
6
9
|
def rescue_with_handler(*)
|
|
7
|
-
ActiveDecorator::ViewContext.push(view_context)
|
|
10
|
+
ActiveDecorator::ViewContext.push(view_context) if defined?(view_context)
|
|
8
11
|
super
|
|
9
12
|
ensure
|
|
10
|
-
ActiveDecorator::ViewContext.pop
|
|
13
|
+
ActiveDecorator::ViewContext.pop if defined?(view_context)
|
|
11
14
|
end
|
|
12
15
|
end
|
|
13
16
|
end
|
|
@@ -1,20 +1,34 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# A monkey-patch for Action View `render :partial` that auto-decorates `locals` values.
|
|
2
4
|
module ActiveDecorator
|
|
3
5
|
module Monkey
|
|
4
6
|
module ActionView
|
|
5
7
|
module PartialRenderer
|
|
8
|
+
if Rails.version.to_f >= 6.1
|
|
9
|
+
def initialize(*)
|
|
10
|
+
super
|
|
11
|
+
|
|
12
|
+
@locals.each_value do |v|
|
|
13
|
+
ActiveDecorator::Decorator.instance.decorate v
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
6
18
|
private
|
|
7
19
|
|
|
8
|
-
|
|
9
|
-
|
|
20
|
+
if Rails.version.to_f < 6.1
|
|
21
|
+
def setup(*)
|
|
22
|
+
super
|
|
10
23
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
24
|
+
@locals.each_value do |v|
|
|
25
|
+
ActiveDecorator::Decorator.instance.decorate v
|
|
26
|
+
end if @locals
|
|
27
|
+
ActiveDecorator::Decorator.instance.decorate @object if @object
|
|
28
|
+
ActiveDecorator::Decorator.instance.decorate @collection unless @collection.blank?
|
|
16
29
|
|
|
17
|
-
|
|
30
|
+
self
|
|
31
|
+
end
|
|
18
32
|
end
|
|
19
33
|
end
|
|
20
34
|
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# A monkey-patch for Active Record that enables association auto-decoration.
|
|
4
|
+
module ActiveDecorator
|
|
5
|
+
module Monkey
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
module Associations
|
|
8
|
+
module Association
|
|
9
|
+
def target
|
|
10
|
+
ActiveDecorator::Decorator.instance.decorate_association(owner, super)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
if Rails.version.to_f < 5.1
|
|
15
|
+
module CollectionAssociation
|
|
16
|
+
private
|
|
17
|
+
def first_nth_or_last(*)
|
|
18
|
+
ActiveDecorator::Decorator.instance.decorate_association(owner, super)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module CollectionProxy
|
|
24
|
+
def take(*)
|
|
25
|
+
ActiveDecorator::Decorator.instance.decorate_association(@association.owner, super)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if Rails.version.to_f >= 5.1
|
|
29
|
+
def last(*)
|
|
30
|
+
ActiveDecorator::Decorator.instance.decorate_association(@association.owner, super)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def find_nth_with_limit(*)
|
|
36
|
+
ActiveDecorator::Decorator.instance.decorate_association(@association.owner, super)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def find_nth_from_last(*)
|
|
40
|
+
ActiveDecorator::Decorator.instance.decorate_association(@association.owner, super)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
module CollectionAssociation
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def build_record(*)
|
|
49
|
+
ActiveDecorator::Decorator.instance.decorate_association(@owner, super)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
module AssociationRelation
|
|
55
|
+
def spawn(*)
|
|
56
|
+
ActiveDecorator::Decorator.instance.decorate_association(@association.owner, super)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require 'active_decorator/view_context'
|
|
3
|
-
require 'rails'
|
|
4
2
|
|
|
5
3
|
module ActiveDecorator
|
|
6
4
|
class Railtie < ::Rails::Railtie
|
|
@@ -8,6 +6,14 @@ module ActiveDecorator
|
|
|
8
6
|
ActiveSupport.on_load :action_view do
|
|
9
7
|
require 'active_decorator/monkey/action_view/partial_renderer'
|
|
10
8
|
ActionView::PartialRenderer.send :prepend, ActiveDecorator::Monkey::ActionView::PartialRenderer
|
|
9
|
+
|
|
10
|
+
if Rails.version.to_f >= 6.1
|
|
11
|
+
require 'active_decorator/monkey/action_view/collection_renderer'
|
|
12
|
+
ActionView::CollectionRenderer.send :prepend, ActiveDecorator::Monkey::ActionView::CollectionRenderer
|
|
13
|
+
|
|
14
|
+
require 'active_decorator/monkey/action_view/object_renderer'
|
|
15
|
+
ActionView::ObjectRenderer.send :prepend, ActiveDecorator::Monkey::ActionView::ObjectRenderer
|
|
16
|
+
end
|
|
11
17
|
end
|
|
12
18
|
|
|
13
19
|
ActiveSupport.on_load :action_controller do
|
|
@@ -17,17 +23,45 @@ module ActiveDecorator
|
|
|
17
23
|
require 'active_decorator/monkey/action_controller/base/rescue_from'
|
|
18
24
|
ActionController::Base.send :prepend, ActiveDecorator::Monkey::ActionController::Base
|
|
19
25
|
|
|
26
|
+
require 'active_decorator/view_context'
|
|
20
27
|
ActionController::Base.send :include, ActiveDecorator::ViewContext::Filter
|
|
21
28
|
end
|
|
22
29
|
|
|
30
|
+
if Rails::VERSION::MAJOR >= 5
|
|
31
|
+
ActiveSupport.on_load :action_controller do
|
|
32
|
+
if self == ActionController::API
|
|
33
|
+
require 'active_decorator/monkey/abstract_controller/rendering'
|
|
34
|
+
::ActionController::API.send :prepend, ActiveDecorator::Monkey::AbstractController::Rendering
|
|
35
|
+
|
|
36
|
+
require 'active_decorator/monkey/action_controller/base/rescue_from'
|
|
37
|
+
::ActionController::API.send :prepend, ActiveDecorator::Monkey::ActionController::Base
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
23
42
|
ActiveSupport.on_load :action_mailer do
|
|
24
43
|
require 'active_decorator/monkey/abstract_controller/rendering'
|
|
25
44
|
ActionMailer::Base.send :prepend, ActiveDecorator::Monkey::AbstractController::Rendering
|
|
26
45
|
|
|
27
46
|
if ActionMailer::Base.respond_to? :before_action
|
|
47
|
+
require 'active_decorator/view_context'
|
|
28
48
|
ActionMailer::Base.send :include, ActiveDecorator::ViewContext::Filter
|
|
29
49
|
end
|
|
30
50
|
end
|
|
51
|
+
|
|
52
|
+
ActiveSupport.on_load :active_record do
|
|
53
|
+
require 'active_decorator/monkey/active_record/associations'
|
|
54
|
+
ActiveRecord::Associations::Association.send :prepend, ActiveDecorator::Monkey::ActiveRecord::Associations::Association
|
|
55
|
+
|
|
56
|
+
if Rails.version.to_f < 5.1
|
|
57
|
+
ActiveRecord::Associations::CollectionAssociation.send :prepend, ActiveDecorator::Monkey::ActiveRecord::Associations::CollectionAssociation
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
ActiveRecord::AssociationRelation.send :prepend, ActiveDecorator::Monkey::ActiveRecord::AssociationRelation
|
|
61
|
+
|
|
62
|
+
ActiveRecord::Associations::CollectionProxy.send :prepend, ActiveDecorator::Monkey::ActiveRecord::Associations::CollectionProxy
|
|
63
|
+
ActiveRecord::Associations::CollectionAssociation.send :prepend, ActiveDecorator::Monkey::ActiveRecord::Associations::CollectionAssociation
|
|
64
|
+
end
|
|
31
65
|
end
|
|
32
66
|
end
|
|
33
67
|
end
|
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# A module that carries the controllers' view_context to decorators.
|
|
2
4
|
module ActiveDecorator
|
|
3
5
|
module ViewContext
|
|
4
6
|
class << self
|
|
5
7
|
def current
|
|
6
|
-
|
|
8
|
+
view_context_stack.last
|
|
7
9
|
end
|
|
8
10
|
|
|
9
11
|
def push(view_context)
|
|
10
|
-
|
|
11
|
-
Thread.current[:active_decorator_view_contexts] << view_context
|
|
12
|
+
view_context_stack.push view_context
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def pop
|
|
15
|
-
|
|
16
|
+
view_context_stack.pop
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def view_context_stack
|
|
20
|
+
Thread.current[:active_decorator_view_contexts] ||= []
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def run_with(view_context)
|
|
24
|
+
push view_context
|
|
25
|
+
yield
|
|
26
|
+
ensure
|
|
27
|
+
pop
|
|
16
28
|
end
|
|
17
29
|
end
|
|
18
30
|
|
|
@@ -20,23 +32,9 @@ module ActiveDecorator
|
|
|
20
32
|
extend ActiveSupport::Concern
|
|
21
33
|
|
|
22
34
|
included do
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
ActiveDecorator::ViewContext.push controller.view_context
|
|
27
|
-
blk.call
|
|
28
|
-
ensure
|
|
29
|
-
ActiveDecorator::ViewContext.pop
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
else
|
|
33
|
-
around_filter do |controller, blk|
|
|
34
|
-
begin
|
|
35
|
-
ActiveDecorator::ViewContext.push controller.view_context
|
|
36
|
-
blk.call
|
|
37
|
-
ensure
|
|
38
|
-
ActiveDecorator::ViewContext.pop
|
|
39
|
-
end
|
|
35
|
+
around_action do |controller, blk|
|
|
36
|
+
ActiveDecorator::ViewContext.run_with(controller.view_context) do
|
|
37
|
+
blk.call
|
|
40
38
|
end
|
|
41
39
|
end
|
|
42
40
|
end
|
data/lib/active_decorator.rb
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'active_decorator/version'
|
|
3
4
|
require 'active_decorator/decorator'
|
|
4
|
-
|
|
5
|
+
begin
|
|
6
|
+
require 'rails'
|
|
7
|
+
require 'active_decorator/railtie'
|
|
8
|
+
rescue LoadError
|
|
9
|
+
end
|
|
5
10
|
require 'active_decorator/config'
|
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module Rails
|
|
3
4
|
module Generators
|
|
4
|
-
class DecoratorGenerator <
|
|
5
|
-
source_root File.expand_path(
|
|
6
|
-
|
|
7
|
-
desc <<DESC
|
|
8
|
-
Description:
|
|
9
|
-
Stubs out a decorator module in app/decorators directory.
|
|
10
|
-
|
|
11
|
-
Examples:
|
|
12
|
-
`rails g decorator book`
|
|
13
|
-
|
|
14
|
-
This creates:
|
|
15
|
-
app/decorators/book_decorator.rb
|
|
16
|
-
DESC
|
|
5
|
+
class DecoratorGenerator < NamedBase
|
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
|
7
|
+
check_class_collision suffix: "Decorator"
|
|
17
8
|
|
|
18
9
|
def create_decorator_file
|
|
19
10
|
template 'decorator.rb', File.join('app/decorators', class_path, "#{file_name}_decorator.rb")
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module Rspec
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
module Generators
|
|
5
|
+
class DecoratorGenerator < ::Rails::Generators::NamedBase
|
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
def create_spec_file
|
|
9
|
+
template 'decorator_spec.rb', File.join('spec/decorators', class_path, "#{file_name}_decorator_spec.rb")
|
|
10
|
+
end
|
|
8
11
|
end
|
|
9
12
|
end
|
|
10
13
|
end
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require '<%= File.exists?('spec/rails_helper.rb') ? 'rails_helper' : 'spec_helper' %>'
|
|
2
4
|
|
|
3
|
-
describe <%=
|
|
4
|
-
let(:<%= singular_name %>) { <%= class_name %>.new.extend <%=
|
|
5
|
+
RSpec.describe <%= class_name %>Decorator do
|
|
6
|
+
let(:<%= singular_name %>) { <%= class_name %>.new.extend <%= class_name %>Decorator }
|
|
5
7
|
subject { <%= singular_name %> }
|
|
6
8
|
it { should be_a <%= class_name %> }
|
|
7
9
|
end
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module TestUnit
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
module Generators
|
|
5
|
+
class DecoratorGenerator < ::Rails::Generators::NamedBase
|
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
|
7
|
+
check_class_collision suffix: "DecoratorTest"
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
def create_test_file
|
|
10
|
+
template 'decorator_test.rb', File.join('test/decorators', class_path, "#{file_name}_decorator_test.rb")
|
|
11
|
+
end
|
|
8
12
|
end
|
|
9
13
|
end
|
|
10
14
|
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'test_helper'
|
|
2
4
|
|
|
3
|
-
class <%=
|
|
5
|
+
class <%= class_name %>DecoratorTest < ActiveSupport::TestCase
|
|
4
6
|
def setup
|
|
5
|
-
@<%= singular_name %> = <%= class_name %>.new.extend <%=
|
|
7
|
+
@<%= singular_name %> = <%= class_name %>.new.extend <%= class_name %>Decorator
|
|
6
8
|
end
|
|
7
9
|
|
|
8
10
|
# test "the truth" do
|