diff options
| -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 | 
