menuable 0.1.0 → 0.1.2

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: f3e428de3e6e6e19e26e5eebbdf163677fc2dac048610e572a0c1c9e8473375f
4
+ data.tar.gz: abdd56584c6ceeb8854dceea90bad7c41134b28c3211c2d4ae5a6a99c4415e0f
5
5
  SHA512:
6
- metadata.gz: 15bd6260b99ffffab22ea211731a17c85ae5bb35978d78e5e7dac0d2b3a4112c24df2be5ec92f50898c4084dc70b9a95dcf942d8023dfe0210f9c45d3dffb9b7
7
- data.tar.gz: 681c86be7c17653563d8f00ca77a841c5bacc2aacd4762ea61b10a278a499eafb03d995ba46d65ea7f96de0a09d77a40c3490f9640dba7267415bcf3dc4ddd27
6
+ metadata.gz: 410d422e140b3e3f922a763df3086cf982c31cb18e5dcda9d4203189a383ef7af55bb1ac18922fdf1853849eb2dda14ae9e4f241941979266ea449d97f44a6a6
7
+ data.tar.gz: b1c01be9f31432e70d7b5667361b54ed414ab9b19d09f01f74ca6cb672af7c31c4d869560f422ad2c53150d67dcb3af0a1c4b36e2dda3ecefa45789ef489233e
data/.rubocop.yml CHANGED
@@ -1,5 +1,11 @@
1
+ require:
2
+ - rubocop-performance
3
+ - rubocop-rake
4
+ - rubocop-rspec
5
+
1
6
  AllCops:
2
7
  TargetRubyVersion: 3.2.2
8
+ NewCops: enable
3
9
 
4
10
  Style/StringLiterals:
5
11
  Enabled: true
@@ -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.2"
5
5
  end
data/lib/menuable.rb CHANGED
@@ -3,51 +3,65 @@
3
3
  require_relative "menuable/version"
4
4
  require "active_support/all"
5
5
 
6
+ #
7
+ # Menuable is a module for dynamically generating sidemenus
8
+ #
6
9
  module Menuable
7
10
  extend ActiveSupport::Concern
8
11
 
9
12
  class_methods do
10
- def menu(resource_name, &block)
11
- namespace = self.name.to_s.deconstantize.constantize
13
+ def resource(resource_name, **options, &)
14
+ resources(resource_name, single: true, **options, &)
15
+ end
16
+
17
+ def resources(resource_name, single: false, **options, &block)
18
+ namespace = name.to_s.deconstantize.constantize
12
19
 
13
20
  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
21
+ menu.options = options
22
+ menu.single = single
20
23
  menu.resource_name = resource_name
21
24
  menu.model_name = ActiveModel::Name.new(nil, nil, "#{namespace}/#{resource_name.to_s.classify}")
22
25
  menu.instance_eval(&block) if block
23
26
 
24
- self.class_eval do
27
+ class_eval do
25
28
  class_attribute :menu, default: menu
26
29
  end
27
30
  end
28
31
  end
29
32
 
33
+ #
34
+ # Value to set from controller
35
+ #
30
36
  class MenuDefinition
31
- class_attribute :namespace
37
+ class_attribute :options
32
38
  class_attribute :resource_name
33
39
  class_attribute :model_name
34
- class_attribute :name
40
+ class_attribute :single
35
41
 
36
42
  NOTHING = ->(_) { true }
37
43
 
44
+ def self.single?
45
+ single
46
+ end
47
+
38
48
  def self.loyalty(&value)
39
49
  return (@loyalty || NOTHING) if value.nil?
40
50
 
41
51
  @loyalty = value
42
52
  end
43
53
 
44
- def self.member_actions(values = nil)
45
- return Array(@member_actions) if values.nil?
54
+ def self.actions(&value)
55
+ return @actions if value.nil?
46
56
 
47
- @member_actions = values
57
+ @actions = value
48
58
  end
49
59
  end
50
60
 
61
+ #
62
+ # A class for binding with view_content to convert the settings defined in yaml
63
+ # into something that can actually be used
64
+ #
51
65
  class MenuContext
52
66
  attr_reader :context
53
67
 
@@ -56,14 +70,15 @@ module Menuable
56
70
  @context = context
57
71
  end
58
72
 
59
- def each
73
+ def each # rubocop:todo Metrics/MethodLength
74
+ return enum_for(:each) unless block_given?
75
+
60
76
  @menus.each do |config|
61
77
  case config
62
78
  in divider:
63
79
  yield config
64
- in group:
65
- items = config[:items].filter_map { |item| menu(item) }
66
- yield menu({ **config, items: })
80
+ in items:
81
+ yield menu({ **config, items: items.filter_map { |item| menu(item) } })
67
82
  else
68
83
  menu(config).try { yield _1 }
69
84
  end
@@ -84,7 +99,7 @@ module Menuable
84
99
  path || config[:path] || "/"
85
100
  end
86
101
 
87
- def active?(menu)
102
+ def active?(menu) # rubocop:todo Metrics/MethodLength
88
103
  case menu
89
104
  in items:
90
105
  items.any? do |item|
@@ -110,18 +125,37 @@ module Menuable
110
125
  end
111
126
  end
112
127
 
128
+ #
129
+ # The actual state of the definition body that reads YAML
130
+ #
113
131
  class Menu
114
- def initialize(namespace, path)
115
- @controllers = []
132
+ def initialize(namespace, path) # rubocop:todo Metrics/MethodLength, Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
133
+ extract_namespace = lambda do |name|
134
+ if name
135
+ namespaces = name.split("/")
136
+ namespaces.pop
137
+ namespaces
138
+ else
139
+ []
140
+ end
141
+ end
142
+
143
+ @controllers = {}
116
144
  @menus = YAML.load_file(path).map do |config|
117
145
  config.deep_symbolize_keys!
118
- controller = "#{namespace}/#{config[:name]}_controller".classify.safe_constantize
119
- @controllers << controller if controller
146
+ namespaces = extract_namespace.call(config[:name])
147
+ controller = "#{namespace}/#{config[:name]&.pluralize}_controller".classify.safe_constantize
148
+ @controllers[namespaces] ||= []
149
+ @controllers[namespaces] << controller if controller
150
+
120
151
  config[:items]&.each do |item|
121
- item[:controller] = "#{namespace}/#{item[:name]}_controller".classify.safe_constantize
122
- @controllers << item[:controller] if item[:controller]
152
+ item[:controller] = "#{namespace}/#{item[:name]&.pluralize}_controller".classify.safe_constantize
153
+ item_namespaces = extract_namespace.call(item[:name])
154
+ @controllers[item_namespaces] ||= []
155
+ @controllers[item_namespaces] << item[:controller] if item[:controller]
123
156
  end
124
- { **config, controller: }
157
+
158
+ { **config, controller:, namespaces: }
125
159
  end
126
160
  end
127
161
 
@@ -134,29 +168,47 @@ module Menuable
134
168
  end
135
169
 
136
170
  def first(current_user:)
137
- @controllers.each do |controller|
171
+ @controllers.values.flatten.each do |controller|
138
172
  break controller.menu if controller.menu.loyalty.call(current_user)
139
173
  end
140
174
  end
141
175
 
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
176
+ def routes(routing) # rubocop:todo Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
177
+ controller_mappings = @controllers
178
+ routing.instance_eval do # rubocop:todo Metrics/BlockLength
179
+ controller_mappings.each do |namespaces, controllers| # rubocop:todo Metrics/BlockLength
180
+ define =
181
+ controllers.map do |controller|
182
+ if controller.menu.single?
183
+ lambda do |router|
184
+ router.resource controller.menu.resource_name do
185
+ router.instance_eval(&controller.menu.actions) if controller.menu.actions
186
+ end
187
+ end
188
+ else
189
+ lambda do |router|
190
+ router.resources controller.menu.resource_name do
191
+ router.instance_eval(&controller.menu.actions) if controller.menu.actions
192
+ end
151
193
  end
152
194
  end
153
195
  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
196
+
197
+ case namespaces.length
198
+ when 3
199
+ namespace namespaces[0] do
200
+ namespace namespaces[1] do
201
+ namespace namespaces[2] { define.each { _1.call(self) } }
158
202
  end
159
203
  end
204
+ when 2
205
+ namespace namespaces[0] do
206
+ namespace(namespaces[1]) { define.each { _1.call(self) } }
207
+ end
208
+ when 1
209
+ namespace(namespaces[0]) { define.each { _1.call(self) } }
210
+ when 0
211
+ define.each { _1.call(self) }
160
212
  end
161
213
  end
162
214
  end
metadata CHANGED
@@ -1,15 +1,29 @@
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.2
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
12
- dependencies: []
11
+ date: 2023-07-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  description: 'This library provides menu.yml and controller macros to manage routes
14
28
  and sidebar implementations when implementing management functions in rails.
15
29
 
@@ -38,6 +52,7 @@ metadata:
38
52
  homepage_uri: https://github.com/aileron-inc/menuable
39
53
  source_code_uri: https://github.com/aileron-inc/menuable
40
54
  changelog_uri: https://github.com/aileron-inc/menuable
55
+ rubygems_mfa_required: 'true'
41
56
  post_install_message:
42
57
  rdoc_options: []
43
58
  require_paths: