administrate 0.12.0 → 0.20.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +0 -2
  3. data/app/assets/javascripts/administrate/application.js +0 -2
  4. data/app/assets/javascripts/administrate/components/associative.js +5 -0
  5. data/app/assets/javascripts/administrate/components/select.js +3 -0
  6. data/app/assets/javascripts/administrate/components/table.js +1 -1
  7. data/app/assets/stylesheets/administrate/application.scss +0 -1
  8. data/app/assets/stylesheets/administrate/base/_forms.scss +1 -1
  9. data/app/assets/stylesheets/administrate/base/_tables.scss +3 -0
  10. data/app/assets/stylesheets/administrate/components/_attributes.scss +4 -3
  11. data/app/assets/stylesheets/administrate/components/_buttons.scss +20 -0
  12. data/app/assets/stylesheets/administrate/components/_cells.scss +2 -0
  13. data/app/assets/stylesheets/administrate/components/_field-unit.scss +24 -4
  14. data/app/assets/stylesheets/administrate/components/_flashes.scss +2 -10
  15. data/app/assets/stylesheets/administrate/components/_main-content.scss +1 -0
  16. data/app/assets/stylesheets/administrate/components/_navigation.scss +2 -3
  17. data/app/assets/stylesheets/administrate/library/_variables.scss +11 -9
  18. data/app/controllers/administrate/application_controller.rb +127 -25
  19. data/app/controllers/concerns/administrate/punditize.rb +44 -20
  20. data/app/helpers/administrate/application_helper.rb +56 -20
  21. data/app/views/administrate/application/_collection.html.erb +26 -29
  22. data/app/views/administrate/application/_collection_header_actions.html.erb +4 -0
  23. data/app/views/administrate/application/_collection_item_actions.html.erb +17 -0
  24. data/app/views/administrate/application/_flashes.html.erb +1 -0
  25. data/app/views/administrate/application/_form.html.erb +20 -5
  26. data/app/views/administrate/application/_icons.html.erb +1 -1
  27. data/app/views/administrate/application/_index_header.html.erb +28 -0
  28. data/app/views/administrate/application/_navigation.html.erb +6 -4
  29. data/app/views/administrate/application/_pagination.html.erb +1 -0
  30. data/app/views/administrate/application/edit.html.erb +2 -2
  31. data/app/views/administrate/application/index.html.erb +9 -29
  32. data/app/views/administrate/application/new.html.erb +1 -1
  33. data/app/views/administrate/application/show.html.erb +28 -12
  34. data/app/views/fields/belongs_to/_form.html.erb +3 -3
  35. data/app/views/fields/belongs_to/_index.html.erb +1 -1
  36. data/app/views/fields/belongs_to/_show.html.erb +1 -1
  37. data/app/views/fields/date/_form.html.erb +22 -0
  38. data/app/views/fields/date/_index.html.erb +21 -0
  39. data/app/views/fields/date/_show.html.erb +21 -0
  40. data/app/views/fields/date_time/_form.html.erb +1 -3
  41. data/app/views/fields/has_many/_index.html.erb +1 -1
  42. data/app/views/fields/has_many/_show.html.erb +2 -1
  43. data/app/views/fields/has_one/_form.html.erb +15 -5
  44. data/app/views/fields/has_one/_index.html.erb +3 -2
  45. data/app/views/fields/has_one/_show.html.erb +22 -15
  46. data/app/views/fields/number/_form.html.erb +1 -1
  47. data/app/views/fields/polymorphic/_index.html.erb +2 -1
  48. data/app/views/fields/polymorphic/_show.html.erb +1 -1
  49. data/app/views/fields/select/_form.html.erb +9 -8
  50. data/app/views/fields/string/_show.html.erb +2 -2
  51. data/app/views/fields/text/_show.html.erb +2 -3
  52. data/app/views/fields/time/_form.html.erb +2 -2
  53. data/app/views/fields/time/_index.html.erb +3 -1
  54. data/app/views/fields/time/_show.html.erb +3 -1
  55. data/app/views/fields/url/_index.html.erb +2 -2
  56. data/app/views/fields/url/_show.html.erb +2 -2
  57. data/app/views/layouts/administrate/application.html.erb +2 -1
  58. data/config/locales/administrate.ar.yml +2 -0
  59. data/config/locales/administrate.bs.yml +2 -0
  60. data/config/locales/administrate.ca.yml +2 -0
  61. data/config/locales/administrate.da.yml +2 -0
  62. data/config/locales/administrate.de.yml +4 -2
  63. data/config/locales/administrate.en.yml +2 -0
  64. data/config/locales/administrate.es.yml +2 -0
  65. data/config/locales/administrate.fi.yml +30 -0
  66. data/config/locales/administrate.fr.yml +4 -2
  67. data/config/locales/administrate.id.yml +2 -0
  68. data/config/locales/administrate.it.yml +2 -0
  69. data/config/locales/administrate.ja.yml +7 -5
  70. data/config/locales/administrate.ko.yml +2 -0
  71. data/config/locales/administrate.nl.yml +7 -5
  72. data/config/locales/administrate.pl.yml +2 -0
  73. data/config/locales/administrate.pt-BR.yml +4 -2
  74. data/config/locales/administrate.pt.yml +4 -2
  75. data/config/locales/administrate.ru.yml +2 -0
  76. data/config/locales/administrate.sl.yml +30 -0
  77. data/config/locales/{administrate.al.yml → administrate.sq.yml} +3 -1
  78. data/config/locales/administrate.sv.yml +2 -0
  79. data/config/locales/administrate.tr.yml +30 -0
  80. data/config/locales/administrate.uk.yml +2 -0
  81. data/config/locales/administrate.vi.yml +2 -0
  82. data/config/locales/administrate.zh-CN.yml +2 -0
  83. data/config/locales/administrate.zh-TW.yml +2 -0
  84. data/docs/adding_controllers_without_related_model.md +52 -0
  85. data/docs/adding_custom_field_types.md +3 -1
  86. data/docs/authentication.md +3 -1
  87. data/docs/authorization.md +47 -22
  88. data/docs/customizing_attribute_partials.md +4 -1
  89. data/docs/customizing_controller_actions.md +67 -1
  90. data/docs/customizing_dashboards.md +171 -40
  91. data/docs/customizing_page_views.md +18 -4
  92. data/docs/extending_administrate.md +27 -0
  93. data/docs/getting_started.md +35 -11
  94. data/docs/guides/customising_search.md +149 -0
  95. data/docs/guides/hiding_dashboards_from_sidebar.md +21 -0
  96. data/docs/guides/scoping_has_many_relations.md +27 -0
  97. data/docs/guides.md +7 -0
  98. data/docs/rails_api.md +5 -3
  99. data/lib/administrate/base_dashboard.rb +73 -14
  100. data/lib/administrate/custom_dashboard.rb +15 -0
  101. data/lib/administrate/engine.rb +9 -2
  102. data/lib/administrate/field/associative.rb +61 -7
  103. data/lib/administrate/field/base.rb +39 -9
  104. data/lib/administrate/field/belongs_to.rb +22 -5
  105. data/lib/administrate/field/date.rb +20 -0
  106. data/lib/administrate/field/deferred.rb +26 -3
  107. data/lib/administrate/field/has_many.rb +35 -8
  108. data/lib/administrate/field/has_one.rb +36 -12
  109. data/lib/administrate/field/number.rb +13 -2
  110. data/lib/administrate/field/polymorphic.rb +7 -6
  111. data/lib/administrate/field/select.rb +23 -4
  112. data/lib/administrate/field/time.rb +11 -0
  113. data/lib/administrate/field/url.rb +4 -0
  114. data/lib/administrate/namespace.rb +5 -1
  115. data/lib/administrate/not_authorized_error.rb +20 -0
  116. data/lib/administrate/order.rb +85 -19
  117. data/lib/administrate/page/base.rb +5 -3
  118. data/lib/administrate/page/collection.rb +1 -0
  119. data/lib/administrate/page/form.rb +12 -4
  120. data/lib/administrate/page/show.rb +10 -2
  121. data/lib/administrate/resource_resolver.rb +4 -3
  122. data/lib/administrate/search.rb +47 -36
  123. data/lib/administrate/version.rb +1 -1
  124. data/lib/administrate/view_generator.rb +14 -3
  125. data/lib/administrate.rb +42 -0
  126. data/lib/generators/administrate/dashboard/dashboard_generator.rb +38 -16
  127. data/lib/generators/administrate/dashboard/templates/controller.rb.erb +23 -11
  128. data/lib/generators/administrate/dashboard/templates/dashboard.rb.erb +4 -4
  129. data/lib/generators/administrate/install/install_generator.rb +43 -2
  130. data/lib/generators/administrate/install/templates/application_controller.rb.erb +4 -4
  131. data/lib/generators/administrate/routes/routes_generator.rb +26 -27
  132. data/lib/generators/administrate/test_record.rb +21 -0
  133. data/lib/generators/administrate/views/views_generator.rb +5 -4
  134. metadata +57 -78
  135. data/app/assets/javascripts/administrate/components/date_time_picker.js +0 -10
  136. data/app/assets/javascripts/administrate/components/has_many_form.js +0 -3
  137. data/config/i18n-tasks.yml +0 -18
  138. data/config/routes.rb +0 -2
  139. data/config/unicorn.rb +0 -30
@@ -9,7 +9,7 @@ module Administrate
9
9
  end
10
10
 
11
11
  def namespace
12
- controller_path.split("/").first
12
+ controller_path.split("/").first.to_sym
13
13
  end
14
14
 
15
15
  def resource_class
@@ -21,7 +21,7 @@ module Administrate
21
21
  end
22
22
 
23
23
  def resource_title
24
- model_path_parts.join(" ")
24
+ resource_class.model_name.human
25
25
  end
26
26
 
27
27
  private
@@ -35,7 +35,8 @@ module Administrate
35
35
  end
36
36
 
37
37
  def controller_path_parts
38
- controller_path.split("/")[1..-1].map(&:singularize)
38
+ path_parts = controller_path.split("/")[1..-1]
39
+ path_parts << path_parts.pop.singularize
39
40
  end
40
41
 
41
42
  attr_reader :controller_path
@@ -4,14 +4,15 @@ require "active_support/core_ext/object/blank"
4
4
  module Administrate
5
5
  class Search
6
6
  class Query
7
- attr_reader :filters
7
+ attr_reader :filters, :valid_filters
8
8
 
9
9
  def blank?
10
10
  terms.blank? && filters.empty?
11
11
  end
12
12
 
13
- def initialize(original_query)
13
+ def initialize(original_query, valid_filters = nil)
14
14
  @original_query = original_query
15
+ @valid_filters = valid_filters
15
16
  @filters, @terms = parse_query(original_query)
16
17
  end
17
18
 
@@ -30,7 +31,7 @@ module Administrate
30
31
  private
31
32
 
32
33
  def filter?(word)
33
- word.match?(/^\w+:$/)
34
+ valid_filters&.any? { |filter| word.match?(/^#{filter}:/) }
34
35
  end
35
36
 
36
37
  def parse_query(query)
@@ -38,7 +39,7 @@ module Administrate
38
39
  terms = []
39
40
  query.to_s.split.each do |word|
40
41
  if filter?(word)
41
- filters << word.split(":").first
42
+ filters << word
42
43
  else
43
44
  terms << word
44
45
  end
@@ -47,10 +48,10 @@ module Administrate
47
48
  end
48
49
  end
49
50
 
50
- def initialize(scoped_resource, dashboard_class, term)
51
- @dashboard_class = dashboard_class
51
+ def initialize(scoped_resource, dashboard, term)
52
+ @dashboard = dashboard
52
53
  @scoped_resource = scoped_resource
53
- @query = Query.new(term)
54
+ @query = Query.new(term, valid_filters.keys)
54
55
  end
55
56
 
56
57
  def run
@@ -65,15 +66,20 @@ module Administrate
65
66
 
66
67
  private
67
68
 
68
- def apply_filter(filter, resources)
69
+ def apply_filter(filter, filter_param, resources)
69
70
  return resources unless filter
70
- filter.call(resources)
71
+ if filter.parameters.size == 1
72
+ filter.call(resources)
73
+ else
74
+ filter.call(resources, filter_param)
75
+ end
71
76
  end
72
77
 
73
78
  def filter_results(resources)
74
- query.filters.each do |filter_name|
79
+ query.filters.each do |filter_query|
80
+ filter_name, filter_param = filter_query.split(":")
75
81
  filter = valid_filters[filter_name]
76
- resources = apply_filter(filter, resources)
82
+ resources = apply_filter(filter, filter_param, resources)
77
83
  end
78
84
  resources
79
85
  end
@@ -81,43 +87,59 @@ module Administrate
81
87
  def query_template
82
88
  search_attributes.map do |attr|
83
89
  table_name = query_table_name(attr)
84
- attr_name = column_to_query(attr)
85
-
86
- "LOWER(CAST(#{table_name}.#{attr_name} AS CHAR(256))) LIKE ?"
90
+ searchable_fields(attr).map do |field|
91
+ column_name = column_to_query(field)
92
+ "LOWER(CAST(#{table_name}.#{column_name} AS CHAR(256))) LIKE ?"
93
+ end.join(" OR ")
87
94
  end.join(" OR ")
88
95
  end
89
96
 
97
+ def searchable_fields(attr)
98
+ return [attr] unless association_search?(attr)
99
+
100
+ attribute_types[attr].searchable_fields
101
+ end
102
+
90
103
  def query_values
91
- ["%#{term.mb_chars.downcase}%"] * search_attributes.count
104
+ fields_count = search_attributes.sum do |attr|
105
+ searchable_fields(attr).count
106
+ end
107
+ ["%#{term.mb_chars.downcase}%"] * fields_count
92
108
  end
93
109
 
94
110
  def search_attributes
95
- attribute_types.keys.select do |attribute|
96
- attribute_types[attribute].searchable?
97
- end
111
+ @dashboard.search_attributes
98
112
  end
99
113
 
100
114
  def search_results(resources)
101
115
  resources.
102
- joins(tables_to_join).
116
+ left_joins(tables_to_join).
103
117
  where(query_template, *query_values)
104
118
  end
105
119
 
106
120
  def valid_filters
107
- if @dashboard_class.const_defined?(:COLLECTION_FILTERS)
108
- @dashboard_class.const_get(:COLLECTION_FILTERS).stringify_keys
121
+ if @dashboard.class.const_defined?(:COLLECTION_FILTERS)
122
+ @dashboard.class.const_get(:COLLECTION_FILTERS).stringify_keys
109
123
  else
110
124
  {}
111
125
  end
112
126
  end
113
127
 
114
128
  def attribute_types
115
- @dashboard_class::ATTRIBUTE_TYPES
129
+ @dashboard.class.const_get(:ATTRIBUTE_TYPES)
116
130
  end
117
131
 
118
132
  def query_table_name(attr)
119
133
  if association_search?(attr)
120
- ActiveRecord::Base.connection.quote_table_name(attr.to_s.pluralize)
134
+ provided_class_name = attribute_types[attr].options[:class_name]
135
+ unquoted_table_name =
136
+ if provided_class_name
137
+ Administrate.warn_of_deprecated_option(:class_name)
138
+ provided_class_name.constantize.table_name
139
+ else
140
+ @scoped_resource.reflect_on_association(attr).klass.table_name
141
+ end
142
+ ActiveRecord::Base.connection.quote_table_name(unquoted_table_name)
121
143
  else
122
144
  ActiveRecord::Base.connection.
123
145
  quote_table_name(@scoped_resource.table_name)
@@ -125,12 +147,7 @@ module Administrate
125
147
  end
126
148
 
127
149
  def column_to_query(attr)
128
- if association_search?(attr)
129
- ActiveRecord::Base.connection.
130
- quote_column_name(attribute_types[attr].searchable_field)
131
- else
132
- ActiveRecord::Base.connection.quote_column_name(attr)
133
- end
150
+ ActiveRecord::Base.connection.quote_column_name(attr)
134
151
  end
135
152
 
136
153
  def tables_to_join
@@ -140,13 +157,7 @@ module Administrate
140
157
  end
141
158
 
142
159
  def association_search?(attribute)
143
- return unless attribute_types[attribute].respond_to?(:deferred_class)
144
-
145
- [
146
- Administrate::Field::BelongsTo,
147
- Administrate::Field::HasMany,
148
- Administrate::Field::HasOne,
149
- ].include?(attribute_types[attribute].deferred_class)
160
+ attribute_types[attribute].associative?
150
161
  end
151
162
 
152
163
  def term
@@ -1,3 +1,3 @@
1
1
  module Administrate
2
- VERSION = "0.12.0".freeze
2
+ VERSION = "0.20.1".freeze
3
3
  end
@@ -1,11 +1,16 @@
1
1
  require "rails/generators/base"
2
2
  require "administrate/generator_helpers"
3
+ require "administrate/namespace"
3
4
 
4
5
  module Administrate
5
6
  class ViewGenerator < Rails::Generators::Base
6
7
  include Administrate::GeneratorHelpers
7
-
8
- private
8
+ class_option(
9
+ :namespace,
10
+ type: :string,
11
+ desc: "Namespace where the admin dashboards live",
12
+ default: "admin",
13
+ )
9
14
 
10
15
  def self.template_source_path
11
16
  File.expand_path(
@@ -14,12 +19,18 @@ module Administrate
14
19
  )
15
20
  end
16
21
 
22
+ private
23
+
24
+ def namespace
25
+ options[:namespace]
26
+ end
27
+
17
28
  def copy_resource_template(template_name)
18
29
  template_file = "#{template_name}.html.erb"
19
30
 
20
31
  copy_file(
21
32
  template_file,
22
- "app/views/admin/#{resource_path}/#{template_file}",
33
+ "app/views/#{namespace}/#{resource_path}/#{template_file}",
23
34
  )
24
35
  end
25
36
 
data/lib/administrate.rb CHANGED
@@ -1,4 +1,46 @@
1
1
  require "administrate/engine"
2
+ require "administrate/version"
2
3
 
3
4
  module Administrate
5
+ def self.warn_of_missing_resource_class
6
+ deprecator.warn(
7
+ "Calling Field::Base.permitted_attribute without the option " +
8
+ ":resource_class is deprecated. If you are seeing this " +
9
+ "message, you are probably using a custom field type that" +
10
+ "does this. Please make sure to update it to a version that " +
11
+ "does not use a deprecated API",
12
+ )
13
+ end
14
+
15
+ def self.warn_of_deprecated_option(name)
16
+ deprecator.warn(
17
+ "The option :#{name} is deprecated. " +
18
+ "Administrate should detect it automatically. " +
19
+ "Please file an issue at " +
20
+ "https://github.com/thoughtbot/administrate/issues " +
21
+ "if you think otherwise.",
22
+ )
23
+ end
24
+
25
+ def self.warn_of_deprecated_method(klass, method)
26
+ deprecator.warn(
27
+ "The method #{klass}##{method} is deprecated. " +
28
+ "If you are seeing this message you are probably " +
29
+ "using a dashboard that depends explicitly on it. " +
30
+ "Please make sure you update it to a version that " +
31
+ "does not use a deprecated API",
32
+ )
33
+ end
34
+
35
+ def self.warn_of_deprecated_authorization_method(method)
36
+ deprecator.warn(
37
+ "The method `#{method}` is deprecated. " +
38
+ "Please use `accessible_action?` instead, " +
39
+ "or see the documentation for other options.",
40
+ )
41
+ end
42
+
43
+ def self.deprecator
44
+ @deprecator ||= ActiveSupport::Deprecation.new(VERSION, "Administrate")
45
+ end
4
46
  end
@@ -5,18 +5,21 @@ module Administrate
5
5
  class DashboardGenerator < Rails::Generators::NamedBase
6
6
  ATTRIBUTE_TYPE_MAPPING = {
7
7
  boolean: "Field::Boolean",
8
- date: "Field::DateTime",
8
+ date: "Field::Date",
9
9
  datetime: "Field::DateTime",
10
- enum: "Field::String",
10
+ enum: "Field::Select",
11
11
  float: "Field::Number",
12
12
  integer: "Field::Number",
13
13
  time: "Field::Time",
14
14
  text: "Field::Text",
15
15
  string: "Field::String",
16
+ uuid: "Field::String",
16
17
  }
17
18
 
18
19
  ATTRIBUTE_OPTIONS_MAPPING = {
19
- enum: { searchable: false },
20
+ # procs must be defined in one line!
21
+ enum: { searchable: false,
22
+ collection: ->(field) { field.resource.class.send(field.attribute.to_s.pluralize).keys } },
20
23
  float: { decimals: 2 },
21
24
  }
22
25
 
@@ -24,7 +27,12 @@ module Administrate
24
27
  COLLECTION_ATTRIBUTE_LIMIT = 4
25
28
  READ_ONLY_ATTRIBUTES = %w[id created_at updated_at]
26
29
 
27
- class_option :namespace, type: :string, default: "admin"
30
+ class_option(
31
+ :namespace,
32
+ type: :string,
33
+ desc: "Namespace where the admin dashboards live",
34
+ default: "admin",
35
+ )
28
36
 
29
37
  source_root File.expand_path("../templates", __FILE__)
30
38
 
@@ -50,9 +58,22 @@ module Administrate
50
58
  end
51
59
 
52
60
  def attributes
53
- klass.reflections.keys +
61
+ attrs = (
62
+ klass.reflections.keys +
54
63
  klass.columns.map(&:name) -
55
64
  redundant_attributes
65
+ )
66
+
67
+ primary_key = attrs.delete(klass.primary_key)
68
+ created_at = attrs.delete("created_at")
69
+ updated_at = attrs.delete("updated_at")
70
+
71
+ [
72
+ primary_key,
73
+ *attrs.sort,
74
+ created_at,
75
+ updated_at,
76
+ ].compact
56
77
  end
57
78
 
58
79
  def form_attributes
@@ -107,11 +128,11 @@ module Administrate
107
128
  if relationship.has_one?
108
129
  "Field::HasOne"
109
130
  elsif relationship.collection?
110
- "Field::HasMany" + relationship_options_string(relationship)
131
+ "Field::HasMany"
111
132
  elsif relationship.polymorphic?
112
133
  "Field::Polymorphic"
113
134
  else
114
- "Field::BelongsTo" + relationship_options_string(relationship)
135
+ "Field::BelongsTo"
115
136
  end
116
137
  end
117
138
 
@@ -119,14 +140,6 @@ module Administrate
119
140
  @klass ||= Object.const_get(class_name)
120
141
  end
121
142
 
122
- def relationship_options_string(relationship)
123
- if relationship.class_name != relationship.name.to_s.classify
124
- options_string(class_name: relationship.class_name)
125
- else
126
- ""
127
- end
128
- end
129
-
130
143
  def options_string(options)
131
144
  if options.any?
132
145
  ".with_options(#{inspect_hash_as_ruby(options)})"
@@ -136,7 +149,16 @@ module Administrate
136
149
  end
137
150
 
138
151
  def inspect_hash_as_ruby(hash)
139
- hash.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
152
+ hash.map do |key, value|
153
+ v_str = value.respond_to?(:call) ? proc_string(value) : value.inspect
154
+ "#{key}: #{v_str}"
155
+ end.join(", ")
156
+ end
157
+
158
+ def proc_string(value)
159
+ source = value.source_location
160
+ proc_string = IO.readlines(source.first)[source.second - 1]
161
+ proc_string[/->[^}]*} | (lambda|proc).*end/x]
140
162
  end
141
163
  end
142
164
  end
@@ -1,12 +1,11 @@
1
- module <%= namespace.classify %>
2
- class <%= class_name.pluralize %>Controller < <%= namespace.classify %>::ApplicationController
1
+ module <%= namespace.to_s.camelize %>
2
+ class <%= class_name.pluralize %>Controller < <%= namespace.to_s.camelize %>::ApplicationController
3
3
  # Overwrite any of the RESTful controller actions to implement custom behavior
4
4
  # For example, you may want to send an email after a foo is updated.
5
5
  #
6
6
  # def update
7
- # foo = Foo.find(params[:id])
8
- # foo.update(params[:foo])
9
- # send_foo_updated_email
7
+ # super
8
+ # send_foo_updated_email(requested_resource)
10
9
  # end
11
10
 
12
11
  # Override this method to specify custom lookup behavior.
@@ -17,18 +16,31 @@ module <%= namespace.classify %>
17
16
  # Foo.find_by!(slug: param)
18
17
  # end
19
18
 
19
+ # The result of this lookup will be available as `requested_resource`
20
+
20
21
  # Override this if you have certain roles that require a subset
21
22
  # this will be used to set the records shown on the `index` action.
22
23
  #
23
24
  # def scoped_resource
24
- # if current_user.super_admin?
25
- # resource_class
26
- # else
27
- # resource_class.with_less_stuff
28
- # end
25
+ # if current_user.super_admin?
26
+ # resource_class
27
+ # else
28
+ # resource_class.with_less_stuff
29
+ # end
30
+ # end
31
+
32
+ # Override `resource_params` if you want to transform the submitted
33
+ # data before it's persisted. For example, the following would turn all
34
+ # empty values into nil values. It uses other APIs such as `resource_class`
35
+ # and `dashboard`:
36
+ #
37
+ # def resource_params
38
+ # params.require(resource_class.model_name.param_key).
39
+ # permit(dashboard.permitted_attributes(action_name)).
40
+ # transform_values { |value| value == "" ? nil : value }
29
41
  # end
30
42
 
31
- # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
43
+ # See https://administrate-demo.herokuapp.com/customizing_controller_actions
32
44
  # for more information
33
45
  end
34
46
  end
@@ -21,7 +21,7 @@ class <%= class_name %>Dashboard < Administrate::BaseDashboard
21
21
  COLLECTION_ATTRIBUTES = %i[
22
22
  <%=
23
23
  attributes.first(COLLECTION_ATTRIBUTE_LIMIT).map do |attr|
24
- " #{attr}"
24
+ " #{attr}"
25
25
  end.join("\n")
26
26
  %>
27
27
  ].freeze
@@ -31,7 +31,7 @@ class <%= class_name %>Dashboard < Administrate::BaseDashboard
31
31
  SHOW_PAGE_ATTRIBUTES = %i[
32
32
  <%=
33
33
  attributes.map do |attr|
34
- " #{attr}"
34
+ " #{attr}"
35
35
  end.join("\n")
36
36
  %>
37
37
  ].freeze
@@ -42,7 +42,7 @@ class <%= class_name %>Dashboard < Administrate::BaseDashboard
42
42
  FORM_ATTRIBUTES = %i[
43
43
  <%=
44
44
  form_attributes.map do |attr|
45
- " #{attr}"
45
+ " #{attr}"
46
46
  end.join("\n")
47
47
  %>
48
48
  ].freeze
@@ -55,7 +55,7 @@ class <%= class_name %>Dashboard < Administrate::BaseDashboard
55
55
  # in the search field:
56
56
  #
57
57
  # COLLECTION_FILTERS = {
58
- # open: ->(resources) { where(open: true) }
58
+ # open: ->(resources) { resources.where(open: true) }
59
59
  # }.freeze
60
60
  COLLECTION_FILTERS = {}.freeze
61
61
 
@@ -1,3 +1,9 @@
1
+ if defined?(Zeitwerk)
2
+ Zeitwerk::Loader.eager_load_all
3
+ else
4
+ Rails.application.eager_load!
5
+ end
6
+
1
7
  require "rails/generators/base"
2
8
  require "administrate/generator_helpers"
3
9
  require "administrate/namespace"
@@ -8,12 +14,17 @@ module Administrate
8
14
  include Administrate::GeneratorHelpers
9
15
  source_root File.expand_path("../templates", __FILE__)
10
16
 
11
- class_option :namespace, type: :string, default: "admin"
17
+ class_option(
18
+ :namespace,
19
+ type: :string,
20
+ desc: "Namespace where the admin dashboards will live",
21
+ default: "admin",
22
+ )
12
23
 
13
24
  def run_routes_generator
14
25
  if dashboard_resources.none?
15
26
  call_generator("administrate:routes", "--namespace", namespace)
16
- load Rails.root.join("config/routes.rb")
27
+ Rails.application.reload_routes!
17
28
  end
18
29
  end
19
30
 
@@ -31,6 +42,12 @@ module Administrate
31
42
  end
32
43
  end
33
44
 
45
+ def model_check
46
+ if valid_dashboard_models.none?
47
+ puts "WARNING: Add models before installing Administrate."
48
+ end
49
+ end
50
+
34
51
  private
35
52
 
36
53
  def namespace
@@ -44,6 +61,30 @@ module Administrate
44
61
  def dashboard_resources
45
62
  Administrate::Namespace.new(namespace).resources
46
63
  end
64
+
65
+ def valid_dashboard_models
66
+ database_models - invalid_dashboard_models
67
+ end
68
+
69
+ def database_models
70
+ ActiveRecord::Base.descendants.reject(&:abstract_class?)
71
+ end
72
+
73
+ def invalid_dashboard_models
74
+ (models_without_tables + namespaced_models + unnamed_constants).uniq
75
+ end
76
+
77
+ def models_without_tables
78
+ database_models.reject(&:table_exists?)
79
+ end
80
+
81
+ def namespaced_models
82
+ database_models.select { |model| model.to_s.include?("::") }
83
+ end
84
+
85
+ def unnamed_constants
86
+ ActiveRecord::Base.descendants.reject { |d| d.name == d.to_s }
87
+ end
47
88
  end
48
89
  end
49
90
  end
@@ -1,10 +1,10 @@
1
- # All Administrate controllers inherit from this `Admin::ApplicationController`,
2
- # making it the ideal place to put authentication logic or other
3
- # before_actions.
1
+ # All Administrate controllers inherit from this
2
+ # `Administrate::ApplicationController`, making it the ideal place to put
3
+ # authentication logic or other before_actions.
4
4
  #
5
5
  # If you want to add pagination or other controller-level concerns,
6
6
  # you're free to overwrite the RESTful controller actions.
7
- module <%= namespace.classify %>
7
+ module <%= namespace.camelize %>
8
8
  class ApplicationController < Administrate::ApplicationController
9
9
  before_action :authenticate_admin
10
10
 
@@ -5,30 +5,38 @@ else
5
5
  end
6
6
 
7
7
  require "rails/generators/base"
8
+ require "administrate/generator_helpers"
8
9
  require "administrate/namespace"
10
+ require "generators/administrate/test_record"
9
11
 
10
12
  module Administrate
11
13
  module Generators
12
14
  class RoutesGenerator < Rails::Generators::Base
15
+ include Administrate::GeneratorHelpers
13
16
  source_root File.expand_path("../templates", __FILE__)
14
- class_option :namespace, type: :string, default: "admin"
17
+ class_option(
18
+ :namespace,
19
+ type: :string,
20
+ desc: "Namespace where the admin dashboards live",
21
+ default: "admin",
22
+ )
15
23
 
16
24
  def insert_dashboard_routes
17
- if should_route_dashboard?
25
+ if valid_dashboard_models.any?
18
26
  route(dashboard_routes)
19
27
  end
20
28
  end
21
29
 
22
30
  def warn_about_invalid_models
23
- namespaced_models.each do |invalid_model|
24
- puts "WARNING: Unable to generate a dashboard for #{invalid_model}."
25
- puts " Administrate does not yet support namespaced models."
26
- end
27
-
28
- models_without_tables.each do |invalid_model|
29
- puts "WARNING: Unable to generate a dashboard for #{invalid_model}."
30
- puts " It is not connected to a database table."
31
- puts " Make sure your database migrations are up to date."
31
+ invalid_dashboard_models.each do |model|
32
+ puts "WARNING: Unable to generate a dashboard for #{model}."
33
+ if namespaced_models.include?(model)
34
+ puts " - Administrate does not yet support namespaced models."
35
+ end
36
+ if models_without_tables.include?(model)
37
+ puts " - It is not connected to a database table."
38
+ puts " Make sure your database migrations are up to date."
39
+ end
32
40
  end
33
41
 
34
42
  unnamed_constants.each do |invalid_model|
@@ -49,15 +57,18 @@ module Administrate
49
57
  end
50
58
 
51
59
  def valid_dashboard_models
52
- database_models - invalid_database_models
60
+ database_models - invalid_dashboard_models
53
61
  end
54
62
 
55
63
  def database_models
56
- ActiveRecord::Base.descendants.reject(&:abstract_class?)
64
+ ActiveRecord::Base.descendants.
65
+ reject(&:abstract_class?).
66
+ reject { |k| k < Administrate::Generators::TestRecord }.
67
+ sort_by(&:to_s)
57
68
  end
58
69
 
59
- def invalid_database_models
60
- models_without_tables + namespaced_models + unnamed_constants
70
+ def invalid_dashboard_models
71
+ (models_without_tables + namespaced_models + unnamed_constants).uniq
61
72
  end
62
73
 
63
74
  def models_without_tables
@@ -76,21 +87,9 @@ module Administrate
76
87
  ERB.new(File.read(routes_file_path)).result(binding)
77
88
  end
78
89
 
79
- def routes_includes_resources?
80
- File.read(rails_routes_file_path).include?(dashboard_routes)
81
- end
82
-
83
- def rails_routes_file_path
84
- Rails.root.join("config/routes.rb")
85
- end
86
-
87
90
  def routes_file_path
88
91
  File.expand_path(find_in_source_paths("routes.rb.erb"))
89
92
  end
90
-
91
- def should_route_dashboard?
92
- routes_includes_resources? || valid_dashboard_models.any?
93
- end
94
93
  end
95
94
  end
96
95
  end