madmin 1.2.1 → 1.2.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: 1f3bd8e986e4859620b06401c531dc24ca84bb02e4e2284a34918b5a088c126c
4
- data.tar.gz: 9bf59b4f93849feda832005caa748e02b4227ea2552cd6e94264d3b7d170f5a9
3
+ metadata.gz: '05151328dcf6fdd8c23755a1b1f3f14b9dcceadc8215e6f102e133d915e95be6'
4
+ data.tar.gz: 305bf51253018fa0c871d0314e9ecd69339c510160cdacf1439c2fd361a95a97
5
5
  SHA512:
6
- metadata.gz: 3181e8f05aad7af36b905a4a04ffb2ddd63419b347e699b0b9ea6d8d2fb9a880f12ebbd7b12d05770e02dc7508e4789a1cb8250b11b6eed26878b6ef71d7fc1b
7
- data.tar.gz: '0019a725b02cde9e007190917381da718a139662d1d9094a0e49ccc69b799437865a4170658b99492947ce1d6d2ae04f71dde97886212a8dd728c3a9aa2275f3'
6
+ metadata.gz: 625d77d1c5ee5bd30462c2609a8b53b7c5d321fb97e0951a95b852eca019189d468c596fcda77e170ed996bd25707feea787a3668faf318a542a65f03d75e488
7
+ data.tar.gz: b594b3c324289e44dbdeb3f0acc70a532b391f8c46faa4854ea5654e9dfe648c88062e24c29433bb476165134a0d79fdbbca526000bbf6c148e9c2c28777f0ed
@@ -19,7 +19,7 @@
19
19
  <div id="sidebar" class="md:w-64 p-4 flex-shrink-0 border-r">
20
20
  <%= render "navigation" -%>
21
21
  </div>
22
- <main class="flex-grow p-4" role="main">
22
+ <main class="flex-grow p-4 overflow-x-scroll" role="main">
23
23
  <%#= render "flashes" -%>
24
24
  <%= yield %>
25
25
  </main>
@@ -28,69 +28,19 @@ module Madmin
28
28
 
29
29
  private
30
30
 
31
- def associations
32
- model.reflections.reject { |name, association|
33
- # Hide these special associations
34
- name.starts_with?("rich_text") ||
35
- name.ends_with?("_attachment") ||
36
- name.ends_with?("_attachments") ||
37
- name.ends_with?("_blob") ||
38
- name.ends_with?("_blobs")
39
- }.keys
31
+ def model
32
+ @model ||= class_name.constantize
40
33
  end
41
34
 
42
- def attributes
43
- model.attribute_names + virtual_attributes - redundant_attributes
35
+ def resource_builder
36
+ @resource_builder ||= ResourceBuilder.new(model)
44
37
  end
45
38
 
46
- def virtual_attributes
47
- virtual = []
48
-
49
- # has_secure_password columns
50
- password_attributes = model.attribute_types.keys.select { |k| k.ends_with?("_digest") }.map { |k| k.delete_suffix("_digest") }
51
- virtual += password_attributes.map { |attr| [attr, "#{attr}_confirmation"] }.flatten
52
-
53
- # Add virtual attributes for ActionText and ActiveStorage
54
- model.reflections.each do |name, association|
55
- if name.starts_with?("rich_text")
56
- virtual << name.split("rich_text_").last
57
- elsif name.ends_with?("_attachment")
58
- virtual << name.split("_attachment").first
59
- elsif name.ends_with?("_attachments")
60
- virtual << name.split("_attachments").first
61
- end
62
- end
63
-
64
- virtual
39
+ def model_attributes
40
+ resource_builder.attributes
65
41
  end
66
42
 
67
- def redundant_attributes
68
- redundant = []
69
-
70
- # has_secure_password columns
71
- redundant += model.attribute_types.keys.select { |k| k.ends_with?("_digest") }
72
-
73
- model.reflections.each do |name, association|
74
- if association.has_one?
75
- next
76
- elsif association.collection?
77
- next
78
- elsif association.polymorphic?
79
- redundant << "#{name}_id"
80
- redundant << "#{name}_type"
81
- elsif name.starts_with?("rich_text")
82
- redundant << name
83
- else # belongs to
84
- redundant << "#{name}_id"
85
- end
86
- end
87
-
88
- redundant
89
- end
90
-
91
- def model
92
- @model ||= class_name.constantize
93
- end
43
+ delegate :associations, :virtual_attributes, :store_accessors, to: :resource_builder
94
44
 
95
45
  def formatted_options_for_attribute(name)
96
46
  options = options_for_attribute(name)
@@ -114,7 +64,7 @@ module Madmin
114
64
  {form: false}
115
65
 
116
66
  # Attributes without a database column
117
- elsif !model.column_names.include?(name)
67
+ elsif !model.column_names.include?(name) && !store_accessors.map(&:to_s).include?(name)
118
68
  {index: false}
119
69
  end
120
70
  end
@@ -1,6 +1,6 @@
1
1
  class <%= class_name %>Resource < Madmin::Resource
2
2
  # Attributes
3
- <% attributes.each do |attribute_name| -%>
3
+ <% model_attributes.each do |attribute_name| -%>
4
4
  attribute :<%= attribute_name %><%= formatted_options_for_attribute(attribute_name) %>
5
5
  <% end -%>
6
6
 
data/lib/madmin/engine.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Madmin
2
2
  class Engine < ::Rails::Engine
3
- initializer "madmin.autoload", before: :set_autoload_paths do |app|
4
- app.config.paths.add "app/madmin/resources", eager_load: true
5
- app.config.paths.add "app/madmin/fields", eager_load: true
3
+ config.before_configuration do |app|
4
+ app.config.autoload_paths << File.expand_path("app/madmin/resources", Rails.root)
5
+ app.config.autoload_paths << File.expand_path("app/madmin/fields", Rails.root)
6
6
  end
7
7
 
8
8
  config.to_prepare do
@@ -39,6 +39,19 @@ module Madmin
39
39
  type: type,
40
40
  field: field.new(**options.merge(attribute_name: name, model: model))
41
41
  )
42
+ rescue => e
43
+ builder = ResourceBuilder.new(model)
44
+ raise ArgumentError, <<~MESSAGE
45
+ Madmin couldn't find attribute or association '#{name}' on #{model} model.
46
+
47
+ We searched these attributes and associations:
48
+ #{(builder.attributes + builder.associations).join(", ")}
49
+
50
+ This attribute is defined in a Madmin resource at:
51
+ #{e.backtrace.find { |l| l =~ /_resource.rb/ }}
52
+
53
+ Either add the missing attribute or assocation, or remove this line from your Madmin resource.
54
+ MESSAGE
42
55
  end
43
56
 
44
57
  def friendly_name
@@ -154,15 +167,6 @@ module Madmin
154
167
  rich_text: Fields::RichText,
155
168
  nested_has_many: Fields::NestedHasMany
156
169
  }.fetch(type)
157
- rescue
158
- raise ArgumentError, <<~MESSAGE
159
- Couldn't find attribute or association '#{name}' with type '#{type}' on #{model} model
160
-
161
- To fix this, either:
162
-
163
- 1. Remove 'attribute #{name}' from app/madmin/resources/#{model.to_s.underscore}_resource.rb
164
- 2. Or add the missing attribute or association to the #{model} model
165
- MESSAGE
166
170
  end
167
171
 
168
172
  def infer_type(name)
@@ -187,6 +191,10 @@ module Madmin
187
191
  # has_secure_password
188
192
  elsif model.attribute_types.include?("#{name_string}_digest") || name_string.ends_with?("_confirmation")
189
193
  :password
194
+
195
+ # ActiveRecord Store
196
+ elsif model_store_accessors.include?(name)
197
+ :string
190
198
  end
191
199
  end
192
200
 
@@ -205,6 +213,12 @@ module Madmin
205
213
  def url_helpers
206
214
  @url_helpers ||= Rails.application.routes.url_helpers
207
215
  end
216
+
217
+ def model_store_accessors
218
+ store_accessors = model.stored_attributes.values
219
+
220
+ store_accessors.flatten
221
+ end
208
222
  end
209
223
  end
210
224
  end
@@ -0,0 +1,80 @@
1
+ module Madmin
2
+ class ResourceBuilder
3
+ attr_reader :model
4
+
5
+ def initialize(model)
6
+ @model = model
7
+ end
8
+
9
+ def associations
10
+ model.reflections.reject { |name, association|
11
+ # Hide these special associations
12
+ name.starts_with?("rich_text") ||
13
+ name.ends_with?("_attachment") ||
14
+ name.ends_with?("_attachments") ||
15
+ name.ends_with?("_blob") ||
16
+ name.ends_with?("_blobs")
17
+ }.keys
18
+ end
19
+
20
+ def attributes
21
+ model.attribute_names + virtual_attributes - redundant_attributes
22
+ end
23
+
24
+ def store_accessors
25
+ model.stored_attributes.values.flatten
26
+ end
27
+
28
+ def virtual_attributes
29
+ virtual = []
30
+
31
+ # has_secure_password columns
32
+ password_attributes = model.attribute_types.keys.select { |k| k.ends_with?("_digest") }.map { |k| k.delete_suffix("_digest") }
33
+ virtual += password_attributes.map { |attr| [attr, "#{attr}_confirmation"] }.flatten
34
+
35
+ # ActiveRecord Store columns
36
+ virtual += store_accessors.map(&:to_s)
37
+
38
+ # Add virtual attributes for ActionText and ActiveStorage
39
+ model.reflections.each do |name, association|
40
+ if name.starts_with?("rich_text")
41
+ virtual << name.split("rich_text_").last
42
+ elsif name.ends_with?("_attachment")
43
+ virtual << name.split("_attachment").first
44
+ elsif name.ends_with?("_attachments")
45
+ virtual << name.split("_attachments").first
46
+ end
47
+ end
48
+
49
+ virtual
50
+ end
51
+
52
+ def redundant_attributes
53
+ redundant = []
54
+
55
+ # has_secure_password columns
56
+ redundant += model.attribute_types.keys.select { |k| k.ends_with?("_digest") }
57
+
58
+ # ActiveRecord Store columns
59
+ store_columns = model.stored_attributes.keys
60
+ redundant += store_columns.map(&:to_s)
61
+
62
+ model.reflections.each do |name, association|
63
+ if association.has_one?
64
+ next
65
+ elsif association.collection?
66
+ next
67
+ elsif association.polymorphic?
68
+ redundant << "#{name}_id"
69
+ redundant << "#{name}_type"
70
+ elsif name.starts_with?("rich_text")
71
+ redundant << name
72
+ else # belongs to
73
+ redundant << "#{name}_id"
74
+ end
75
+ end
76
+
77
+ redundant
78
+ end
79
+ end
80
+ end
@@ -1,3 +1,3 @@
1
1
  module Madmin
2
- VERSION = "1.2.1"
2
+ VERSION = "1.2.2"
3
3
  end
data/lib/madmin.rb CHANGED
@@ -6,6 +6,7 @@ module Madmin
6
6
  autoload :Field, "madmin/field"
7
7
  autoload :GeneratorHelpers, "madmin/generator_helpers"
8
8
  autoload :Resource, "madmin/resource"
9
+ autoload :ResourceBuilder, "madmin/resource_builder"
9
10
  autoload :Search, "madmin/search"
10
11
 
11
12
  module Fields
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: madmin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Oliver
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-09-09 00:00:00.000000000 Z
12
+ date: 2021-09-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -182,6 +182,7 @@ files:
182
182
  - lib/madmin/generator_helpers.rb
183
183
  - lib/madmin/namespace.rb
184
184
  - lib/madmin/resource.rb
185
+ - lib/madmin/resource_builder.rb
185
186
  - lib/madmin/search.rb
186
187
  - lib/madmin/version.rb
187
188
  - lib/madmin/view_generator.rb