menuable 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7cd924adb10768078fdf03b62129b6bfd9a90ef7425777cc94d4bfa6fbd4ed7
4
- data.tar.gz: 24f889651399a85900f5e6b18ca57a02e5fa129137021c45f94bc3c9c98ab8b1
3
+ metadata.gz: f0c4ea54013a825585c4b87cdf3e25e54d82c04b1b6aab36b436ac2cc588a3d1
4
+ data.tar.gz: 2b635cf422c7eed2068b5e1fad5fcb0518ca1f8402f7237a04971dab84f5ca0f
5
5
  SHA512:
6
- metadata.gz: 15bd6260b99ffffab22ea211731a17c85ae5bb35978d78e5e7dac0d2b3a4112c24df2be5ec92f50898c4084dc70b9a95dcf942d8023dfe0210f9c45d3dffb9b7
7
- data.tar.gz: 681c86be7c17653563d8f00ca77a841c5bacc2aacd4762ea61b10a278a499eafb03d995ba46d65ea7f96de0a09d77a40c3490f9640dba7267415bcf3dc4ddd27
6
+ metadata.gz: 650d34d9d2699828ea17994775f6f9230e1229bb853c2bbd87d354871a4e7d7ce83e26f4bc897e91e5a61e3663264511240a4a0fbeee400dd6351b20e7e30759
7
+ data.tar.gz: c5625b3c58e74e01a09f803088cd9b443113284d769fe6987bea16e3f461d9a5b73b4dad95c400c75132eabcdac028852b614441ae04e552d93bc186e672bf7a
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Menuable
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/lib/menuable.rb CHANGED
@@ -7,44 +7,48 @@ module Menuable
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  class_methods do
10
- def menu(resource_name, &block)
11
- namespace = self.name.to_s.deconstantize.constantize
10
+ def resource(resource_name, **options, &block)
11
+ resources(resource_name, single: true, **options, &block)
12
+ end
13
+
14
+ def resources(resource_name, single: false, **options, &block)
15
+ namespace = name.to_s.deconstantize.constantize
12
16
 
13
17
  menu = Class.new(MenuDefinition)
14
- menu.namespace =
15
- self.name.split("::").try do |token|
16
- token.shift
17
- token.pop
18
- token.first&.underscore
19
- end
18
+ menu.options = options
19
+ menu.single = single
20
20
  menu.resource_name = resource_name
21
21
  menu.model_name = ActiveModel::Name.new(nil, nil, "#{namespace}/#{resource_name.to_s.classify}")
22
22
  menu.instance_eval(&block) if block
23
23
 
24
- self.class_eval do
24
+ class_eval do
25
25
  class_attribute :menu, default: menu
26
26
  end
27
27
  end
28
28
  end
29
29
 
30
30
  class MenuDefinition
31
- class_attribute :namespace
31
+ class_attribute :options
32
32
  class_attribute :resource_name
33
33
  class_attribute :model_name
34
- class_attribute :name
34
+ class_attribute :single
35
35
 
36
36
  NOTHING = ->(_) { true }
37
37
 
38
+ def self.single?
39
+ single
40
+ end
41
+
38
42
  def self.loyalty(&value)
39
43
  return (@loyalty || NOTHING) if value.nil?
40
44
 
41
45
  @loyalty = value
42
46
  end
43
47
 
44
- def self.member_actions(values = nil)
45
- return Array(@member_actions) if values.nil?
48
+ def self.actions(&value)
49
+ return @actions if value.nil?
46
50
 
47
- @member_actions = values
51
+ @actions = value
48
52
  end
49
53
  end
50
54
 
@@ -56,14 +60,15 @@ module Menuable
56
60
  @context = context
57
61
  end
58
62
 
59
- def each
63
+ def each # rubocop:todo Metrics/MethodLength
64
+ return enum_for(:each) unless block_given?
65
+
60
66
  @menus.each do |config|
61
67
  case config
62
68
  in divider:
63
69
  yield config
64
- in group:
65
- items = config[:items].filter_map { |item| menu(item) }
66
- yield menu({ **config, items: })
70
+ in items:
71
+ yield menu({ **config, items: items.filter_map { |item| menu(item) } })
67
72
  else
68
73
  menu(config).try { yield _1 }
69
74
  end
@@ -111,17 +116,33 @@ module Menuable
111
116
  end
112
117
 
113
118
  class Menu
114
- def initialize(namespace, path)
115
- @controllers = []
119
+ def initialize(namespace, path) # rubocop:todo Metrics/MethodLength, Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
120
+ extract_namespace = lambda do |name|
121
+ if name
122
+ namespaces = name.split("/")
123
+ namespaces.pop
124
+ namespaces
125
+ else
126
+ []
127
+ end
128
+ end
129
+
130
+ @controllers = {}
116
131
  @menus = YAML.load_file(path).map do |config|
117
132
  config.deep_symbolize_keys!
118
- controller = "#{namespace}/#{config[:name]}_controller".classify.safe_constantize
119
- @controllers << controller if controller
133
+ namespaces = extract_namespace.call(config[:name])
134
+ controller = "#{namespace}/#{config[:name]&.pluralize}_controller".classify.safe_constantize
135
+ @controllers[namespaces] ||= []
136
+ @controllers[namespaces] << controller if controller
137
+
120
138
  config[:items]&.each do |item|
121
- item[:controller] = "#{namespace}/#{item[:name]}_controller".classify.safe_constantize
122
- @controllers << item[:controller] if item[:controller]
139
+ item[:controller] = "#{namespace}/#{item[:name]&.pluralize}_controller".classify.safe_constantize
140
+ item_namespaces = extract_namespace.call(item[:name])
141
+ @controllers[item_namespaces] ||= []
142
+ @controllers[item_namespaces] << item[:controller] if item[:controller]
123
143
  end
124
- { **config, controller: }
144
+
145
+ { **config, controller:, namespaces: }
125
146
  end
126
147
  end
127
148
 
@@ -134,29 +155,47 @@ module Menuable
134
155
  end
135
156
 
136
157
  def first(current_user:)
137
- @controllers.each do |controller|
158
+ @controllers.values.flatten.each do |controller|
138
159
  break controller.menu if controller.menu.loyalty.call(current_user)
139
160
  end
140
161
  end
141
162
 
142
- def routes(routing)
143
- controllers = @controllers
144
- routing.instance_eval do
145
- controllers.each do |controller|
146
- if controller.menu.namespace
147
- namespace controller.menu.namespace do
148
- resources controller.menu.resource_name do
149
- controller.menu.member_actions.each do |action_name|
150
- get action_name, on: :member
163
+ def routes(routing) # rubocop:todo Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
164
+ controller_mappings = @controllers
165
+ routing.instance_eval do # rubocop:todo Metrics/BlockLength
166
+ controller_mappings.each do |namespaces, controllers| # rubocop:todo Metrics/BlockLength
167
+ define =
168
+ controllers.map do |controller|
169
+ if controller.menu.single?
170
+ lambda do |router|
171
+ router.resource controller.menu.resource_name do
172
+ router.instance_eval(&controller.menu.actions) if controller.menu.actions
173
+ end
174
+ end
175
+ else
176
+ lambda do |router|
177
+ router.resources controller.menu.resource_name do
178
+ router.instance_eval(&controller.menu.actions) if controller.menu.actions
179
+ end
151
180
  end
152
181
  end
153
182
  end
154
- else
155
- resources controller.menu.resource_name do
156
- controller.menu.member_actions.each do |action_name|
157
- get action_name, on: :member
183
+
184
+ case namespaces.length
185
+ when 3
186
+ namespace namespaces[0] do
187
+ namespace namespaces[1] do
188
+ namespace namespaces[2] { define.each { _1.call(self) } }
158
189
  end
159
190
  end
191
+ when 2
192
+ namespace namespaces[0] do
193
+ namespace(namespaces[1]) { define.each { _1.call(self) } }
194
+ end
195
+ when 1
196
+ namespace(namespaces[0]) { define.each { _1.call(self) } }
197
+ when 0
198
+ define.each { _1.call(self) }
160
199
  end
161
200
  end
162
201
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: menuable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masa (Aileron inc)
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-17 00:00:00.000000000 Z
11
+ date: 2023-07-18 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 'This library provides menu.yml and controller macros to manage routes
14
14
  and sidebar implementations when implementing management functions in rails.