menuable 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.