diff options
| author | Zog | 2018-01-15 18:22:53 +0100 |
|---|---|---|
| committer | Zog | 2018-01-25 17:17:58 +0100 |
| commit | 936650bb189104bf9795e0a7e9b5b8044e59a652 (patch) | |
| tree | ebca427ef1127cde9d62dd902e521c2e9bec7507 | |
| parent | aefa3a507239b57ebdfe9110f3c8c789da6bce26 (diff) | |
| download | chouette-core-936650bb189104bf9795e0a7e9b5b8044e59a652.tar.bz2 | |
Refs #5586 @2h; Refactor the whole thing
We now have a ModelDecorator and an "instance" decorator, all in the
same file, with the same API.
| -rw-r--r-- | app/controllers/lines_controller.rb | 8 | ||||
| -rw-r--r-- | app/decorators/line_decorator.rb | 106 | ||||
| -rw-r--r-- | app/views/layouts/navigation/_page_header.html.slim | 1 | ||||
| -rw-r--r-- | app/views/lines/index.html.slim | 3 | ||||
| -rw-r--r-- | lib/af83/decorator.rb | 88 | ||||
| -rw-r--r-- | lib/af83/enhanced_decorator.rb | 80 | ||||
| -rw-r--r-- | spec/lib/af83/decorator/decorator_spec.rb | 1060 |
7 files changed, 738 insertions, 608 deletions
diff --git a/app/controllers/lines_controller.rb b/app/controllers/lines_controller.rb index 7041a3a26..10ecc7e9d 100644 --- a/app/controllers/lines_controller.rb +++ b/app/controllers/lines_controller.rb @@ -15,9 +15,8 @@ class LinesController < ChouetteController def index @hide_group_of_line = line_referential.group_of_lines.empty? index! do |format| - @lines = ModelDecorator.decorate( + @lines = LineDecorator.decorate( @lines, - with: LineDecorator, context: { line_referential: @line_referential, current_organisation: current_organisation @@ -69,9 +68,14 @@ class LinesController < ChouetteController respond_to do |format| format.json { render :json => filtered_lines_maps} end + end + def decorated_collection + @lines end + helper_method :decorated_collection + protected def filtered_lines_maps diff --git a/app/decorators/line_decorator.rb b/app/decorators/line_decorator.rb index 9325c6a8b..728543592 100644 --- a/app/decorators/line_decorator.rb +++ b/app/decorators/line_decorator.rb @@ -1,67 +1,73 @@ class LineDecorator < AF83::Decorator decorates Chouette::Line - delegate_all - - ### primary (and secondary) can be - ### - a single action - ### - an array of actions - ### - a boolean - - action_link primary: :index, on: :index do |l| - l.content h.t('lines.actions.show') - l.href { [context[:line_referential], object] } + action_link on: :index, primary: :index, policy: :create do |l| + l.content { h.t('lines.actions.new') } + l.href { h.new_line_referential_line_path(context[:line_referential]) } end - action_link do |l| - l.content h.t('lines.actions.show_network') - l.href { [context[:line_referential], object.network] } - end + with_instance_decorator do |instance_decorator| + instance_decorator.delegate_all + ### primary (and secondary) can be + ### - a single action + ### - an array of actions + ### - a boolean - action_link do |l| - l.content { h.t('lines.actions.show_company') } - l.href { [context[:line_referential], object.company] } - l.disabled { object.company.nil? } - end + instance_decorator.action_link primary: :index, on: :index do |l| + l.content h.t('lines.actions.show') + l.href { [context[:line_referential], object] } + end - can_edit_line = ->(){ h.policy(Chouette::Line).create? && context[:line_referential].organisations.include?(context[:current_organisation]) } + instance_decorator.action_link do |l| + l.content h.t('lines.actions.show_network') + l.href { [context[:line_referential], object.network] } + end - with_condition can_edit_line do - action_link on: %i(index show), primary: :show, secondary: :index do |l| - l.content { h.t('lines.actions.edit') } - l.href { h.edit_line_referential_line_path(context[:line_referential], object.id) } + instance_decorator.action_link do |l| + l.content { h.t('lines.actions.show_company') } + l.href { [context[:line_referential], object.company] } + l.disabled { object.company.nil? } end - action_link on: :index, secondary: :index do |l| - l.content { h.t('lines.actions.new') } - l.href { h.new_line_referential_line_path(context[:line_referential]) } + can_edit_line = ->(){ h.policy(Chouette::Line).create? && context[:line_referential].organisations.include?(context[:current_organisation]) } + + instance_decorator.with_condition can_edit_line do + action_link on: %i(index show), primary: :show, secondary: :index do |l| + l.content { h.t('lines.actions.edit') } + l.href { h.edit_line_referential_line_path(context[:line_referential], object.id) } + end + + action_link on: :index, secondary: :index do |l| + l.content { h.t('lines.actions.new') } + l.href { h.new_line_referential_line_path(context[:line_referential]) } + end end - end - ### the option :policy will automatically check for the corresponding method - ### on the object's policy + ### the option :policy will automatically check for the corresponding method + ### on the object's policy - action_link policy: :deactivate, secondary: :show, footer: :index do |l| - l.content { h.deactivate_link_content('lines.actions.deactivate') } - l.href { h.deactivate_line_referential_line_path(context[:line_referential], object) } - l.method :put - l.data confirm: h.t('lines.actions.deactivate_confirm') - l.extra_class "delete-action" - end + instance_decorator.action_link policy: :deactivate, secondary: :show, footer: :index do |l| + l.content { h.deactivate_link_content('lines.actions.deactivate') } + l.href { h.deactivate_line_referential_line_path(context[:line_referential], object) } + l.method :put + l.data confirm: h.t('lines.actions.deactivate_confirm') + l.extra_class "delete-action" + end - action_link policy: :activate, secondary: :show, footer: :index do |l| - l.content { h.activate_link_content('lines.actions.activate') } - l.href { h.activate_line_referential_line_path(context[:line_referential], object) } - l.method :put - l.data confirm: h.t('lines.actions.activate_confirm') - l.extra_class "delete-action" - end + instance_decorator.action_link policy: :activate, secondary: :show, footer: :index do |l| + l.content { h.activate_link_content('lines.actions.activate') } + l.href { h.activate_line_referential_line_path(context[:line_referential], object) } + l.method :put + l.data confirm: h.t('lines.actions.activate_confirm') + l.extra_class "delete-action" + end - action_link policy: :destroy, footer: true do |l| - l.content { h.destroy_link_content('lines.actions.destroy') } - l.href { h.line_referential_line_path(context[:line_referential], object) } - l.method :delete - l.data confirm: h.t('lines.actions.destroy_confirm') - l.extra_class "delete-action" + instance_decorator.action_link policy: :destroy, footer: true do |l| + l.content { h.destroy_link_content('lines.actions.destroy') } + l.href { h.line_referential_line_path(context[:line_referential], object) } + l.method :delete + l.data confirm: h.t('lines.actions.destroy_confirm') + l.extra_class "delete-action" + end end end diff --git a/app/views/layouts/navigation/_page_header.html.slim b/app/views/layouts/navigation/_page_header.html.slim index 076c76de4..353361992 100644 --- a/app/views/layouts/navigation/_page_header.html.slim +++ b/app/views/layouts/navigation/_page_header.html.slim @@ -20,6 +20,7 @@ div.page_header = yield :page_header_actions - action_links = resource.action_links(params[:action]) rescue nil + - action_links ||= decorated_collection.action_links(params[:action]) rescue nil - if action_links&.primary&.any? || action_links&.secondary&.any? .row .col-lg-12.text-right.mb-sm diff --git a/app/views/lines/index.html.slim b/app/views/lines/index.html.slim index 399a2d8e1..2d64e5f73 100644 --- a/app/views/lines/index.html.slim +++ b/app/views/lines/index.html.slim @@ -1,7 +1,4 @@ - breadcrumb :lines, @line_referential -- content_for :page_header_actions do - - if policy(Chouette::Line).create? - = link_to(t('lines.actions.new'), new_line_referential_line_path(@line_referential), class: 'btn btn-primary') .page_content .container-fluid diff --git a/lib/af83/decorator.rb b/lib/af83/decorator.rb index 6c7dff59d..79694ee59 100644 --- a/lib/af83/decorator.rb +++ b/lib/af83/decorator.rb @@ -1,80 +1,25 @@ -class AF83::Decorator < Draper::Decorator - def self.action_link args={} - args[:if] = @_condition if args[:if].nil? +class AF83::Decorator < ModelDecorator + include AF83::EnhancedDecorator + extend AF83::EnhancedDecorator::ClassMethods - options, link_options = parse_options args - - link = Link.new(link_options) - yield link if block_given? - raise IncompleteLinkDefinition.new(link.errors) unless link.complete? - - weight = options[:weight] || 1 - @_action_links ||= [] - @_action_links[weight] ||= [] - @_action_links[weight] << link - end - - def self.with_condition condition, &block - @_condition = condition - instance_eval &block - @_condition = nil - end - - def self.action_links action - (@_action_links || []).flatten.compact.select{|l| l.for_action?(action)} - end - - def action_links action=:index, opts={} - links = ActionLinks.new links: self.class.action_links(action), context: self, action: action - group = opts[:group] - links = links.for_group opts[:group] - links + def self.decorates klass + instance_decorator.decorates klass end - def primary_links action=:index - action_links(action, group: :primary) + def self.instance_decorator + @instance_decorator ||= Class.new(AF83::Decorator::InstanceDecorator) end - def secondary_links action=:index - action_links(action, group: :secondary) + def self.with_instance_decorator + yield instance_decorator end - def check_policy policy - _object = policy.to_s == "create" ? object.class : object - method = "#{policy}?" - h.policy(_object).send(method) - end - - private - def self.parse_options args - options = {} - %i(weight primary secondary footer on action actions policy if groups group).each do |k| - options[k] = args.delete(k) if args.has_key?(k) - end - link_options = args.dup - - actions = options.delete :actions - actions ||= options.delete :on - actions ||= [options.delete(:action)] - actions = [actions] unless actions.is_a?(Array) - link_options[:_actions] = actions.compact - - link_options[:_groups] = options.delete(:groups) - link_options[:_groups] ||= {} - if single_group = options.delete(:group) - if(single_group.is_a?(Symbol) || single_group.is_a?(String)) - link_options[:_groups][single_group] = true - else - link_options[:_groups].update single_group - end + def self.decorate object, options = {} + if object.is_a?(ActiveRecord::Base) + return instance_decorator.decorate object, options + else + self.new object, options.update(with: instance_decorator) end - link_options[:_groups][:primary] ||= options.delete :primary - link_options[:_groups][:secondary] ||= options.delete :secondary - link_options[:_groups][:footer] ||= options.delete :footer - - link_options[:_if] = options.delete(:if) - link_options[:_policy] = options.delete(:policy) - [options, link_options] end class ActionLinks @@ -267,4 +212,9 @@ class AF83::Decorator < Draper::Decorator class IncompleteLinkDefinition < RuntimeError end + + class InstanceDecorator < Draper::Decorator + include AF83::EnhancedDecorator + extend AF83::EnhancedDecorator::ClassMethods + end end diff --git a/lib/af83/enhanced_decorator.rb b/lib/af83/enhanced_decorator.rb new file mode 100644 index 000000000..41cc17f85 --- /dev/null +++ b/lib/af83/enhanced_decorator.rb @@ -0,0 +1,80 @@ +module AF83::EnhancedDecorator + module ClassMethods + def action_link args={} + args[:if] = @_condition if args[:if].nil? + + options, link_options = parse_options args + + link = AF83::Decorator::Link.new(link_options) + yield link if block_given? + raise AF83::Decorator::IncompleteLinkDefinition.new(link.errors) unless link.complete? + + weight = options[:weight] || 1 + @_action_links ||= [] + @_action_links[weight] ||= [] + @_action_links[weight] << link + end + + def with_condition condition, &block + @_condition = condition + instance_eval &block + @_condition = nil + end + + def action_links action + (@_action_links || []).flatten.compact.select{|l| l.for_action?(action)} + end + + def parse_options args + options = {} + %i(weight primary secondary footer on action actions policy if groups group).each do |k| + options[k] = args.delete(k) if args.has_key?(k) + end + link_options = args.dup + + actions = options.delete :actions + actions ||= options.delete :on + actions ||= [options.delete(:action)] + actions = [actions] unless actions.is_a?(Array) + link_options[:_actions] = actions.compact + + link_options[:_groups] = options.delete(:groups) + link_options[:_groups] ||= {} + if single_group = options.delete(:group) + if(single_group.is_a?(Symbol) || single_group.is_a?(String)) + link_options[:_groups][single_group] = true + else + link_options[:_groups].update single_group + end + end + link_options[:_groups][:primary] ||= options.delete :primary + link_options[:_groups][:secondary] ||= options.delete :secondary + link_options[:_groups][:footer] ||= options.delete :footer + + link_options[:_if] = options.delete(:if) + link_options[:_policy] = options.delete(:policy) + [options, link_options] + end + end + + def action_links action=:index, opts={} + links = AF83::Decorator::ActionLinks.new links: self.class.action_links(action), context: self, action: action + group = opts[:group] + links = links.for_group opts[:group] + links + end + + def primary_links action=:index + action_links(action, group: :primary) + end + + def secondary_links action=:index + action_links(action, group: :secondary) + end + + def check_policy policy + _object = policy.to_s == "create" ? object.klass : object + method = "#{policy}?" + h.policy(_object).send(method) + end +end diff --git a/spec/lib/af83/decorator/decorator_spec.rb b/spec/lib/af83/decorator/decorator_spec.rb index 04dc9df09..789813063 100644 --- a/spec/lib/af83/decorator/decorator_spec.rb +++ b/spec/lib/af83/decorator/decorator_spec.rb @@ -8,7 +8,7 @@ RSpec.describe AF83::Decorator, type: :decorator do } let(:args){ options.dup.update(link_options.dup) } it "should separate options from link_options" do - _options, _link_options = AF83::Decorator.send :parse_options, args + _options, _link_options = AF83::Decorator.instance_decorator.send :parse_options, args expect(_options).to eq({weight: 12}) link_options.each do |k, v| expect(_link_options[k]).to eq v @@ -25,675 +25,767 @@ RSpec.describe AF83::Decorator, type: :decorator do end } - describe(:action_links) do + context "as an collection decorator" do + let(:link_options) do + { + href: "/foo/bar", + content: "Blublu" + } + end + + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link link_options + klass + end + let(:decorated) do - obj = create :line - decorator.decorate(obj) + 3.times { create :line } + decorator.decorate(Chouette::Line.all) end - context "without links" do - let(:decorator) do - Class.new(AF83::Decorator) + it "should return the links" do + links = decorated.action_links + instance_exec links.first, link_options, &link_should_match_options + end + end + + context "as an instance decorator" do + describe("with the actual decorator") do + before(:each) do + Draper::HelperProxy.any_instance.stub(:policy){ + klass = Class.new do + def method_missing *args + true + end + end.new + } end - it "should return no link" do - links = decorated.action_links - expect(links.size).to eq 0 + let(:decorated) do + line = create :line + line.decorate(context: {line_referential: line.line_referential}) + end + + it "should return the links" do + expect{ decorated.action_links }.to_not raise_error end end - context "with a single link" do - let(:link_options) do - { - href: "/foo/bar", - content: "Blublu" - } + describe(:action_links) do + let(:decorated) do + obj = create :line + decorator.decorate(obj) end - context "incompletetly defined" do + context "without links" do let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link href: "bar" - klass + Class.new(AF83::Decorator) end - it "should raise an error" do - expect{decorator}.to raise_error(AF83::Decorator::IncompleteLinkDefinition) + it "should return no link" do + links = decorated.action_links + expect(links.size).to eq 0 end end - context "defined inline" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options - klass + context "with a single link" do + let(:link_options) do + { + href: "/foo/bar", + content: "Blublu" + } end - it "should return the defined link" do - links = decorated.action_links - expect(links.size).to eq 1 - instance_exec links.first, link_options, &link_should_match_options - end - end + context "incompletetly defined" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link href: "bar" + end + klass + end - context "defined in a block" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link do |l| - l.href link_options[:href] - l.content link_options[:content] + it "should raise an error" do + expect{decorator}.to raise_error(AF83::Decorator::IncompleteLinkDefinition) end - klass end - it "should return the defined link" do - links = decorated.action_links - expect(links.size).to eq 1 - instance_exec links.first, link_options, &link_should_match_options - end - end + context "defined inline" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options + end + klass + end - context "with proc attributes" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link do |l| - l.href { context[:href] } - l.content link_options[:content] + it "should return the defined link" do + links = decorated.action_links + expect(links.size).to eq 1 + instance_exec links.first, link_options, &link_should_match_options end - klass end - let(:decorated) do - obj = create :line - decorator.decorate(obj, context: {href: link_options[:href]}) - end + context "defined in a block" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link do |l| + l.href link_options[:href] + l.content link_options[:content] + end + end + klass + end - it "should return the defined link" do - links = decorated.action_links - expect(links.size).to eq 1 - expect(links.first.href).to eq link_options[:href] + it "should return the defined link" do + links = decorated.action_links + expect(links.size).to eq 1 + instance_exec links.first, link_options, &link_should_match_options + end end - end - context "with a method attributes" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link do |l| - l.href link_options[:href] - l.content link_options[:content] - l.method :put + context "with proc attributes" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link do |l| + l.href { context[:href] } + l.content "Blublu" + end + end + klass end - klass - end - let(:decorated) do - obj = create :line - decorator.decorate(obj, context: {href: link_options[:href]}) - end + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {href: link_options[:href]}) + end - it "should return the defined method" do - links = decorated.action_links - expect(links.size).to eq 1 - expect(links.first.method).to eq :put + it "should return the defined link" do + links = decorated.action_links + expect(links.size).to eq 1 + expect(links.first.href).to eq link_options[:href] + end end - end - end - context "with 2 links" do - let(:link_options_1) do - { - href: "/foo/bar", - content: "Blublu" - } - end - - let(:link_options_2) do - { - href: "/foo/bar/baz", - content: "Foo" - } - end + context "with a method attributes" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link do |l| + l.href "/foo/bar" + l.content "Blublu" + l.method :put + end + end + klass + end - context "without weight" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options_1 - klass.action_link link_options_2 - klass - end + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {href: link_options[:href]}) + end - it "should return links in the sequence they were defined" do - links = decorated.action_links - expect(links.size).to eq 2 - instance_exec links.first, link_options_1, &link_should_match_options - instance_exec links.last, link_options_2, &link_should_match_options + it "should return the defined method" do + links = decorated.action_links + expect(links.size).to eq 1 + expect(links.first.method).to eq :put + end end end - context "with weight" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options_1.update(weight: 10) - klass.action_link link_options_2 - klass + context "with 2 links" do + let(:link_options_1) do + { + href: "/foo/bar", + content: "Blublu" + } end - it "should return links in the sequence they were defined" do - links = decorated.action_links - expect(links.size).to eq 2 - instance_exec links.first, link_options_2, &link_should_match_options - instance_exec links.last, link_options_1, &link_should_match_options + let(:link_options_2) do + { + href: "/foo/bar/baz", + content: "Foo" + } end - end - context "scoped by action" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options_1.update(action: :index) - klass.action_link link_options_2 - klass - end + context "without weight" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options_1 + instance_decorator.action_link link_options_2 + end + klass + end - it "should only return links defined for the given action" do - links = decorated.action_links(:show) - expect(links.size).to eq 1 - instance_exec links.first, link_options_2, &link_should_match_options + it "should return links in the sequence they were defined" do + links = decorated.action_links + expect(links.size).to eq 2 + instance_exec links.first, link_options_1, &link_should_match_options + instance_exec links.last, link_options_2, &link_should_match_options + end end - end - context "with a policy" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link href: "foo", content: "foo", policy: :edit - klass + context "with weight" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options_1.update(weight: 10) + instance_decorator.action_link link_options_2 + end + klass + end + + it "should return links in the sequence they were defined" do + links = decorated.action_links + expect(links.size).to eq 2 + instance_exec links.first, link_options_2, &link_should_match_options + instance_exec links.last, link_options_1, &link_should_match_options + end end - context "when the policy is not met" do - before(:each) do - Draper::HelperProxy.any_instance.stub(:policy){ - klass = Class.new do - def edit? - false - end - end.new - } + context "scoped by action" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options_1.update(action: :index) + instance_decorator.action_link link_options_2 + end + klass end - it "should not return the link" do + it "should only return links defined for the given action" do links = decorated.action_links(:show) - expect(links.size).to eq 0 + expect(links.size).to eq 1 + instance_exec links.first, link_options_2, &link_should_match_options end end - context "when the policy is met" do - before(:each) do - Draper::HelperProxy.any_instance.stub(:policy){ - klass = Class.new do - def edit? - true - end - end.new - } + context "with a policy" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link href: "foo", content: "foo", policy: :edit + end + klass end - it "should not return the link" do - links = decorated.action_links(:show) - expect(links.size).to eq 1 + context "when the policy is not met" do + before(:each) do + Draper::HelperProxy.any_instance.stub(:policy){ + klass = Class.new do + def edit? + false + end + end.new + } + end + + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 0 + end + end + + context "when the policy is met" do + before(:each) do + Draper::HelperProxy.any_instance.stub(:policy){ + klass = Class.new do + def edit? + true + end + end.new + } + end + + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + end end end - end - context "with a condition" do - context "set with 'with_condition'" do - context "as a value" do - context "when the condition is true" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.with_condition true do - action_link href: "foo", content: "foo" + context "with a condition" do + context "set with 'with_condition'" do + context "as a value" do + context "when the condition is true" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.with_condition true do + action_link href: "foo", content: "foo" + end + end + klass + end + + it "should return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 end - klass end - it "should return the link" do - links = decorated.action_links(:show) - expect(links.size).to eq 1 + context "when the condition is false" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.with_condition false do + action_link href: "foo", content: "foo" + end + end + klass + end + + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 0 + end end end - context "when the condition is false" do + context "as a Proc" do let(:decorator) do klass = Class.new(AF83::Decorator) - klass.with_condition false do - action_link href: "foo", content: "foo" + klass.with_instance_decorator do |instance_decorator| + instance_decorator.with_condition ->{context[:show_link]} do + action_link href: "foo", content: "foo" + end end klass end - it "should not return the link" do - links = decorated.action_links(:show) - expect(links.size).to eq 0 - end - end - end + context "when the condition is true" do + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {show_link: true}) + end - context "as a Proc" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.with_condition ->{context[:show_link]} do - action_link href: "foo", content: "foo" + it "should return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + end end - klass - end - context "when the condition is true" do - let(:decorated) do - obj = create :line - decorator.decorate(obj, context: {show_link: true}) - end + context "when the condition is false" do + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {show_link: false}) + end - it "should return the link" do - links = decorated.action_links(:show) - expect(links.size).to eq 1 + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 0 + end end end + end - context "when the condition is false" do - let(:decorated) do - obj = create :line - decorator.decorate(obj, context: {show_link: false}) + context "set inline" do + context "as a value" do + context "when the condition is true" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options_1.update(if: true) + end + klass + end + + it "should return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + end end - it "should not return the link" do - links = decorated.action_links(:show) - expect(links.size).to eq 0 + context "when the condition is false" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options_1.update(if: false) + end + klass + end + + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 0 + end end end - end - end - context "set inline" do - context "as a value" do - context "when the condition is true" do + context "as a Proc" do let(:decorator) do klass = Class.new(AF83::Decorator) - klass.action_link link_options_1.update(if: true) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options_1.update(if: ->{context[:show_link]}) + end klass end - it "should return the link" do - links = decorated.action_links(:show) - expect(links.size).to eq 1 - end - end + context "when the condition is true" do + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {show_link: true}) + end - context "when the condition is false" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options_1.update(if: false) - klass + it "should return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + end end - it "should not return the link" do - links = decorated.action_links(:show) - expect(links.size).to eq 0 + context "when the condition is false" do + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {show_link: false}) + end + + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 0 + end end end end + end - context "as a Proc" do + context "scoped by action" do + context "with a single action" do let(:decorator) do klass = Class.new(AF83::Decorator) - klass.action_link link_options_1.update(if: ->{context[:show_link]}) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options_1.update(action: :index) + instance_decorator.action_link link_options_2 + end klass end - context "when the condition is true" do - let(:decorated) do - obj = create :line - decorator.decorate(obj, context: {show_link: true}) - end - - it "should return the link" do - links = decorated.action_links(:show) - expect(links.size).to eq 1 - end + it "should only return links defined for the given action" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + instance_exec links.first, link_options_2, &link_should_match_options end + end - context "when the condition is false" do - let(:decorated) do - obj = create :line - decorator.decorate(obj, context: {show_link: false}) - end - - it "should not return the link" do - links = decorated.action_links(:show) - expect(links.size).to eq 0 + context "with several actions" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options_1.update(actions: %i(index edit)) + instance_decorator.action_link link_options_2.update(actions: %i(show edit)) end + klass end - end - end - end - - context "scoped by action" do - context "with a single action" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options_1.update(action: :index) - klass.action_link link_options_2 - klass - end - - it "should only return links defined for the given action" do - links = decorated.action_links(:show) - expect(links.size).to eq 1 - instance_exec links.first, link_options_2, &link_should_match_options - end - end - context "with several actions" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options_1.update(actions: %i(index edit)) - klass.action_link link_options_2.update(actions: %i(show edit)) - klass - end - - it "should only return links defined for the given action" do - links = decorated.action_links(:show) - expect(links.size).to eq 1 - instance_exec links.first, link_options_2, &link_should_match_options + it "should only return links defined for the given action" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + instance_exec links.first, link_options_2, &link_should_match_options + end end - end - context "with the keyword 'on'" do - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options_1.update(on: %i(index edit)) - klass.action_link link_options_2.update(on: :show) - klass - end + context "with the keyword 'on'" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options_1.update(on: %i(index edit)) + instance_decorator.action_link link_options_2.update(on: :show) + end + klass + end - it "should only return links defined for the given action" do - links = decorated.action_links(:show) - expect(links.size).to eq 1 - instance_exec links.first, link_options_2, &link_should_match_options + it "should only return links defined for the given action" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + instance_exec links.first, link_options_2, &link_should_match_options + end end end end end - end - - describe '#primary' do - let(:decorator) do - Class.new(AF83::Decorator) - end - - let(:decorated) do - obj = create :line - decorator.decorate(obj) - end - - it "should return a new object everytime" do - actions = decorated.action_links - primary = actions.primary - expect(actions.options[:groups]).to be_nil - expect(primary.options[:groups]).to_not be_nil - end - end - - describe(:primary_links) do - let(:decorated) do - obj = create :line - decorator.decorate(obj) - end - context "without links" do + describe '#primary' do let(:decorator) do Class.new(AF83::Decorator) end - it "should return no link" do - links = decorated.action_links - expect(links.size).to eq 0 + let(:decorated) do + obj = create :line + decorator.decorate(obj) end - end - context "with a single link" do - let(:link_options) do - { - href: "/foo/bar/baz", - content: "Blublu", - primary: primary - } + it "should return a new object everytime" do + actions = decorated.action_links + primary = actions.primary + expect(actions.options[:groups]).to be_nil + expect(primary.options[:groups]).to_not be_nil end + end - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options - klass + describe(:primary_links) do + let(:decorated) do + obj = create :line + decorator.decorate(obj) end - context "always primary" do - let(:primary){ true } + context "without links" do + let(:decorator) do + Class.new(AF83::Decorator) + end - it "should return the link" do - links = decorated.primary_links(:show) - expect(links.size).to eq 1 + it "should return no link" do + links = decorated.action_links + expect(links.size).to eq 0 end end - context "primary on this action" do - let(:primary){ :show } + context "with a single link" do + let(:link_options) do + { + href: "/foo/bar/baz", + content: "Blublu", + primary: primary + } + end - it "should return the link" do - links = decorated.primary_links(:show) - expect(links.size).to eq 1 + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options + end + klass end - end - context "primary on this action among others" do - let(:primary){ %i(show edit) } + context "always primary" do + let(:primary){ true } - it "should return the link" do - links = decorated.action_links(:show, group: :primary) - expect(links.size).to eq 1 + it "should return the link" do + links = decorated.primary_links(:show) + expect(links.size).to eq 1 + end end - end - context "primary on other actions" do - let(:primary){ %i(index edit) } + context "primary on this action" do + let(:primary){ :show } - it "should not return the link" do - links = decorated.action_links(:show, group: :primary) - expect(links.size).to eq 0 + it "should return the link" do + links = decorated.primary_links(:show) + expect(links.size).to eq 1 + end end - end - context "primary on another action" do - let(:primary){ :index } + context "primary on this action among others" do + let(:primary){ %i(show edit) } - it "should not return the link" do - links = decorated.primary_links(:show) - expect(links.size).to eq 0 + it "should return the link" do + links = decorated.action_links(:show, group: :primary) + expect(links.size).to eq 1 + end end - end - context "never primary" do - let(:primary){ nil } + context "primary on other actions" do + let(:primary){ %i(index edit) } - it "should not return the link" do - links = decorated.primary_links(:show) - expect(links.size).to eq 0 + it "should not return the link" do + links = decorated.action_links(:show, group: :primary) + expect(links.size).to eq 0 + end end - end - end - end - describe("in a group") do - let(:decorated) do - obj = create :line - decorator.decorate(obj) - end + context "primary on another action" do + let(:primary){ :index } - context "without links" do - let(:decorator) do - Class.new(AF83::Decorator) - end + it "should not return the link" do + links = decorated.primary_links(:show) + expect(links.size).to eq 0 + end + end + + context "never primary" do + let(:primary){ nil } - it "should return no link" do - links = decorated.action_links - expect(links.size).to eq 0 + it "should not return the link" do + links = decorated.primary_links(:show) + expect(links.size).to eq 0 + end + end end end - - context "with a single link" do - let(:link_options) do - { - href: "/foo/bar/baz", - content: "Blublu", - groups: {foo: group} - } + describe("in a group") do + let(:decorated) do + obj = create :line + decorator.decorate(obj) end - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options - klass + context "without links" do + let(:decorator) do + Class.new(AF83::Decorator) + end + + it "should return no link" do + links = decorated.action_links + expect(links.size).to eq 0 + end end - context "always in" do - let(:group){ true } - it "should return the link" do - links = decorated.action_links(:show, group: :foo) - expect(links.size).to eq 1 + context "with a single link" do + let(:link_options) do + { + href: "/foo/bar/baz", + content: "Blublu", + groups: {foo: group} + } end - context "define with group" do - let(:link_options) do - { - href: "/foo/bar/baz", - content: "Blublu", - group: :foo - } + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options end + klass + end - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options - klass - end + context "always in" do + let(:group){ true } it "should return the link" do links = decorated.action_links(:show, group: :foo) expect(links.size).to eq 1 end - it "should not return the link" do - links = decorated.action_links(:show, group: :bar) - expect(links.size).to eq 0 + context "define with group" do + let(:link_options) do + { + href: "/foo/bar/baz", + content: "Blublu", + group: :foo + } + end + + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options + end + klass + end + + it "should return the link" do + links = decorated.action_links(:show, group: :foo) + expect(links.size).to eq 1 + end + + it "should not return the link" do + links = decorated.action_links(:show, group: :bar) + expect(links.size).to eq 0 + end end end - end - context "primary on this action" do - let(:group){ :show } + context "primary on this action" do + let(:group){ :show } - it "should return the link" do - links = decorated.action_links(:show, group: :foo) - expect(links.size).to eq 1 + it "should return the link" do + links = decorated.action_links(:show, group: :foo) + expect(links.size).to eq 1 + end end - end - context "in this action among others" do - let(:group){ %i(show edit) } + context "in this action among others" do + let(:group){ %i(show edit) } - it "should return the link" do - links = decorated.action_links(:show, group: :foo) - expect(links.size).to eq 1 + it "should return the link" do + links = decorated.action_links(:show, group: :foo) + expect(links.size).to eq 1 + end end - end - context "in other actions" do - let(:group){ %i(index edit) } + context "in other actions" do + let(:group){ %i(index edit) } - it "should not return the link" do - links = decorated.action_links(:show, group: :foo) - expect(links.size).to eq 0 + it "should not return the link" do + links = decorated.action_links(:show, group: :foo) + expect(links.size).to eq 0 + end end - end - context "in another action" do - let(:group){ :index } + context "in another action" do + let(:group){ :index } - it "should not return the link" do - links = decorated.action_links(:show, group: :foo) - expect(links.size).to eq 0 + it "should not return the link" do + links = decorated.action_links(:show, group: :foo) + expect(links.size).to eq 0 + end end - end - context "never" do - let(:group){ nil } + context "never" do + let(:group){ nil } - it "should not return the link" do - links = decorated.action_links(:show, group: :foo) - expect(links.size).to eq 0 + it "should not return the link" do + links = decorated.action_links(:show, group: :foo) + expect(links.size).to eq 0 + end end end - end - describe(:grouped_by) do - let(:link_options_1) do - { - href: "/foo/bar", - content: "Blublu", - primary: true - } - end + describe(:grouped_by) do + let(:link_options_1) do + { + href: "/foo/bar", + content: "Blublu", + primary: true + } + end - let(:link_options_2) do - { - href: "/foo/bar/baz", - content: "Foo", - groups: {secondary: :show} - } - end + let(:link_options_2) do + { + href: "/foo/bar/baz", + content: "Foo", + groups: {secondary: :show} + } + end - let(:link_options_3) do - { - href: "/foo/bar/baz/bat", - content: "Foo", - groups: {foo: :show} - } - end + let(:link_options_3) do + { + href: "/foo/bar/baz/bat", + content: "Foo", + groups: {foo: :show} + } + end - let(:link_options_4) do - { - href: "/footer", - content: "Foo", - footer: true - } - end + let(:link_options_4) do + { + href: "/footer", + content: "Foo", + footer: true + } + end - let(:decorator) do - klass = Class.new(AF83::Decorator) - klass.action_link link_options_1 - klass.action_link link_options_2 - klass.action_link link_options_3 - klass.action_link link_options_4 - klass - end + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_instance_decorator do |instance_decorator| + instance_decorator.action_link link_options_1 + instance_decorator.action_link link_options_2 + instance_decorator.action_link link_options_3 + instance_decorator.action_link link_options_4 + end + klass + end - it "should return links in their groups" do - links = decorated.action_links(:show).grouped_by(:primary, :secondary, :blu, :footer) - expect(links.size).to eq 5 - instance_exec links[:primary].first, link_options_1, &link_should_match_options - instance_exec links[:secondary].first, link_options_2, &link_should_match_options - expect(links[:blu].size).to eq 0 - instance_exec links[:other].first, link_options_3, &link_should_match_options - instance_exec links[:footer].first, link_options_4, &link_should_match_options + it "should return links in their groups" do + links = decorated.action_links(:show).grouped_by(:primary, :secondary, :blu, :footer) + expect(links.size).to eq 5 + instance_exec links[:primary].first, link_options_1, &link_should_match_options + instance_exec links[:secondary].first, link_options_2, &link_should_match_options + expect(links[:blu].size).to eq 0 + instance_exec links[:other].first, link_options_3, &link_should_match_options + instance_exec links[:footer].first, link_options_4, &link_should_match_options + end end end end |
