aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorZog2018-01-15 10:34:30 +0100
committerZog2018-01-25 17:17:57 +0100
commit8c9ce8f5c143d1e9d3f2c038e447a01ee59c91d3 (patch)
treeed94d90b5ae6e6ad77973bd0e8dddcf335a0d995 /lib
parent5ecadfdead964381304fcf56a2564e2045988ef7 (diff)
downloadchouette-core-8c9ce8f5c143d1e9d3f2c038e447a01ee59c91d3.tar.bz2
Refs #5586 @4h; First `action_links` refactor
- Implement new API - Migrate the LineDecorator - ensure no change on the "lines/index" view
Diffstat (limited to 'lib')
-rw-r--r--lib/af83/decorator.rb124
1 files changed, 124 insertions, 0 deletions
diff --git a/lib/af83/decorator.rb b/lib/af83/decorator.rb
new file mode 100644
index 000000000..f1570008f
--- /dev/null
+++ b/lib/af83/decorator.rb
@@ -0,0 +1,124 @@
+class AF83::Decorator < Draper::Decorator
+ def self.action_link args={}
+ args[:if] = @_condition if args[:if].nil?
+ 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
+ self.class.action_links(action)\
+ .map{|l| l.bind_to_context(self)}\
+ .select{|l| l.enabled?}
+ 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(primary secondary permission weight).each do |k|
+ options[k] = args.delete(k) if args.has_key?(k)
+ end
+ link_options = args.dup
+ actions = args.delete :actions
+ actions ||= args.delete :on
+ actions ||= [args.delete(:action)]
+ actions = [actions] unless actions.is_a?(Array)
+ link_options[:_actions] = actions.compact
+ link_options[:_if] = args.delete(:if)
+ link_options[:_policy] = args.delete(:policy)
+ [options, link_options]
+ end
+
+ class Link
+ REQUIRED_ATTRIBUTES = %i(href content)
+
+ attr_reader :context
+
+ def initialize options={}
+ @options = options
+ end
+
+ def bind_to_context context
+ @context = context
+ self
+ end
+
+ def method *args
+ link_method *args
+ end
+
+ def method_missing name, *args, &block
+ if block_given?
+ @options[name] = block
+ elsif args.size == 0
+ out = @options[name]
+ out = context.instance_exec(&out) if out.is_a?(Proc)
+ out
+ else
+ @options[name] = args.first
+ end
+ end
+
+ def complete?
+ @missing_attributes = REQUIRED_ATTRIBUTES.select{|a| !@options[a].present?}
+ @missing_attributes.empty?
+ end
+
+ def enabled_actions
+ @options[:_actions].map(&:to_s) || []
+ end
+
+ def for_action? action
+ enabled_actions.empty? || enabled_actions.include?(action.to_s)
+ end
+
+ def enabled?
+ enabled = false
+ if @options[:_if].nil?
+ enabled = true
+ elsif @options[:_if].is_a?(Proc)
+ enabled = context.instance_exec(&@options[:_if])
+ else
+ enabled = !!@options[:_if]
+ end
+
+ enabled = enabled && check_policy(@options[:_policy]) if @options[:_policy].present?
+
+ enabled
+ end
+
+ def check_policy(policy)
+ @context.check_policy policy
+ end
+
+ def errors
+ "Missing attributes: #{@missing_attributes.to_sentence}"
+ end
+ end
+
+ class IncompleteLinkDefinition < RuntimeError
+ end
+end