1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
class AF83::Decorator < ModelDecorator
include AF83::Decorator::EnhancedDecorator
extend AF83::Decorator::EnhancedDecorator::ClassMethods
def self.decorates klass
instance_decorator.decorates klass
end
def self.instance_decorator
@instance_decorator ||= begin
klass = Class.new(AF83::Decorator::InstanceDecorator)
klass.delegate_all
klass
end
end
def self.with_instance_decorator
@_with_instance_decorator = true
yield instance_decorator
@_with_instance_decorator = false
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
end
def self.define_instance_method method_name, &block
instance_decorator.send(:define_method, method_name, &block)
end
# Defines a class method on the decorated object's class. These
# can be called like `object.class.my_method`.
def self.define_instance_class_method method_name, &block
instance_decorator.send(:define_singleton_method, method_name, &block)
end
class ActionLinks
attr_reader :options
delegate :each, :map, :size, :first, :last, :any?, :select, to: :resolve
def initialize opts
@options = opts.deep_dup
end
def for_group group
returning_a_copy do
@options[:groups] = [group] if group.present?
end
end
def for_groups groups
returning_a_copy do
@options[:groups] = groups if groups.present?
end
end
def primary
for_group :primary
end
def secondary
for_group :secondary
end
def resolve
out = @options[:links].map{|l| l.bind_to_context(@options[:context], @options[:action])}.select{|l| l.enabled?}
if @options[:groups].present?
out = out.select do |l|
@options[:groups].any? do |g|
l.in_group_for_action?(g)
end
end
end
out
end
alias_method :to_ary, :resolve
def grouped_by *groups
add_footer = groups.include?(:footer)
groups -= [:footer]
out = HashWithIndifferentAccess[*groups.map{|g| [g, []]}.flatten(1)]
out[:other] = []
if add_footer
out[:footer] = []
groups << :footer
end
each do |l|
found = false
groups.each do |g|
if l.in_group_for_action?(g)
out[g] << l
found = true
next
end
end
out[:other] << l unless found
end
out
end
private
def returning_a_copy &block
out = ActionLinks.new options
out.instance_eval &block
out
end
end
class IncompleteLinkDefinition < RuntimeError
end
class InstanceDecorator < Draper::Decorator
include AF83::Decorator::EnhancedDecorator
extend AF83::Decorator::EnhancedDecorator::ClassMethods
end
end
|