administrate 0.12.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/administrate/components/associative.js +5 -0
  3. data/app/assets/javascripts/administrate/components/date_time_picker.js +6 -2
  4. data/app/assets/javascripts/administrate/components/table.js +1 -1
  5. data/app/assets/stylesheets/administrate/base/_tables.scss +3 -0
  6. data/app/assets/stylesheets/administrate/components/_attributes.scss +4 -3
  7. data/app/assets/stylesheets/administrate/components/_buttons.scss +11 -0
  8. data/app/assets/stylesheets/administrate/components/_cells.scss +2 -0
  9. data/app/assets/stylesheets/administrate/components/_field-unit.scss +17 -4
  10. data/app/assets/stylesheets/administrate/components/_flashes.scss +0 -8
  11. data/app/assets/stylesheets/administrate/components/_main-content.scss +1 -0
  12. data/app/assets/stylesheets/administrate/components/_navigation.scss +2 -3
  13. data/app/assets/stylesheets/administrate/library/_variables.scss +10 -8
  14. data/app/controllers/administrate/application_controller.rb +47 -13
  15. data/app/helpers/administrate/application_helper.rb +32 -14
  16. data/app/views/administrate/application/_collection.html.erb +24 -26
  17. data/app/views/administrate/application/_collection_header_actions.html.erb +4 -0
  18. data/app/views/administrate/application/_collection_item_actions.html.erb +17 -0
  19. data/app/views/administrate/application/_flashes.html.erb +1 -0
  20. data/app/views/administrate/application/_form.html.erb +3 -3
  21. data/app/views/administrate/application/_icons.html.erb +1 -1
  22. data/app/views/administrate/application/_index_header.html.erb +28 -0
  23. data/app/views/administrate/application/_navigation.html.erb +5 -3
  24. data/app/views/administrate/application/index.html.erb +9 -29
  25. data/app/views/administrate/application/show.html.erb +1 -1
  26. data/app/views/fields/belongs_to/_form.html.erb +3 -3
  27. data/app/views/fields/belongs_to/_index.html.erb +1 -1
  28. data/app/views/fields/belongs_to/_show.html.erb +1 -1
  29. data/app/views/fields/date/_form.html.erb +24 -0
  30. data/app/views/fields/date/_index.html.erb +21 -0
  31. data/app/views/fields/date/_show.html.erb +21 -0
  32. data/app/views/fields/has_one/_index.html.erb +1 -1
  33. data/app/views/fields/has_one/_show.html.erb +4 -4
  34. data/app/views/fields/number/_form.html.erb +1 -1
  35. data/app/views/fields/polymorphic/_show.html.erb +1 -1
  36. data/app/views/fields/select/_form.html.erb +23 -9
  37. data/app/views/fields/string/_show.html.erb +2 -2
  38. data/app/views/fields/text/_show.html.erb +2 -3
  39. data/app/views/fields/time/_form.html.erb +3 -2
  40. data/app/views/fields/time/_index.html.erb +3 -1
  41. data/app/views/fields/time/_show.html.erb +3 -1
  42. data/app/views/fields/url/_index.html.erb +1 -1
  43. data/app/views/fields/url/_show.html.erb +1 -1
  44. data/app/views/layouts/administrate/application.html.erb +1 -0
  45. data/config/locales/administrate.ar.yml +2 -0
  46. data/config/locales/administrate.bs.yml +2 -0
  47. data/config/locales/administrate.ca.yml +2 -0
  48. data/config/locales/administrate.da.yml +2 -0
  49. data/config/locales/administrate.de.yml +2 -0
  50. data/config/locales/administrate.en.yml +2 -0
  51. data/config/locales/administrate.es.yml +2 -0
  52. data/config/locales/administrate.fi.yml +30 -0
  53. data/config/locales/administrate.fr.yml +4 -2
  54. data/config/locales/administrate.id.yml +2 -0
  55. data/config/locales/administrate.it.yml +2 -0
  56. data/config/locales/administrate.ja.yml +2 -0
  57. data/config/locales/administrate.ko.yml +2 -0
  58. data/config/locales/administrate.nl.yml +7 -5
  59. data/config/locales/administrate.pl.yml +2 -0
  60. data/config/locales/administrate.pt-BR.yml +4 -2
  61. data/config/locales/administrate.pt.yml +4 -2
  62. data/config/locales/administrate.ru.yml +2 -0
  63. data/config/locales/{administrate.al.yml → administrate.sq.yml} +3 -1
  64. data/config/locales/administrate.sv.yml +2 -0
  65. data/config/locales/administrate.tr.yml +30 -0
  66. data/config/locales/administrate.uk.yml +2 -0
  67. data/config/locales/administrate.vi.yml +2 -0
  68. data/config/locales/administrate.zh-CN.yml +2 -0
  69. data/config/locales/administrate.zh-TW.yml +2 -0
  70. data/config/unicorn.rb +8 -13
  71. data/docs/adding_controllers_without_related_model.md +52 -0
  72. data/docs/adding_custom_field_types.md +3 -1
  73. data/docs/authentication.md +3 -1
  74. data/docs/authorization.md +5 -3
  75. data/docs/customizing_attribute_partials.md +4 -1
  76. data/docs/customizing_controller_actions.md +48 -1
  77. data/docs/customizing_dashboards.md +90 -37
  78. data/docs/customizing_page_views.md +18 -4
  79. data/docs/extending_administrate.md +27 -0
  80. data/docs/getting_started.md +35 -11
  81. data/docs/guides/hiding_dashboards_from_sidebar.md +19 -0
  82. data/docs/guides.md +5 -0
  83. data/docs/rails_api.md +5 -3
  84. data/lib/administrate/base_dashboard.rb +35 -12
  85. data/lib/administrate/custom_dashboard.rb +15 -0
  86. data/lib/administrate/engine.rb +7 -0
  87. data/lib/administrate/field/associative.rb +49 -5
  88. data/lib/administrate/field/base.rb +35 -9
  89. data/lib/administrate/field/belongs_to.rb +13 -3
  90. data/lib/administrate/field/date.rb +20 -0
  91. data/lib/administrate/field/deferred.rb +22 -3
  92. data/lib/administrate/field/has_many.rb +15 -2
  93. data/lib/administrate/field/has_one.rb +32 -12
  94. data/lib/administrate/field/number.rb +19 -2
  95. data/lib/administrate/field/polymorphic.rb +5 -5
  96. data/lib/administrate/field/select.rb +10 -1
  97. data/lib/administrate/field/time.rb +11 -0
  98. data/lib/administrate/namespace.rb +5 -1
  99. data/lib/administrate/order.rb +17 -7
  100. data/lib/administrate/page/base.rb +1 -3
  101. data/lib/administrate/page/form.rb +10 -3
  102. data/lib/administrate/resource_resolver.rb +2 -2
  103. data/lib/administrate/search.rb +47 -36
  104. data/lib/administrate/version.rb +1 -1
  105. data/lib/administrate/view_generator.rb +9 -3
  106. data/lib/administrate.rb +19 -0
  107. data/lib/generators/administrate/dashboard/dashboard_generator.rb +19 -15
  108. data/lib/generators/administrate/dashboard/templates/controller.rb.erb +22 -10
  109. data/lib/generators/administrate/dashboard/templates/dashboard.rb.erb +4 -4
  110. data/lib/generators/administrate/install/install_generator.rb +37 -1
  111. data/lib/generators/administrate/install/templates/application_controller.rb.erb +4 -4
  112. data/lib/generators/administrate/routes/routes_generator.rb +15 -25
  113. data/lib/generators/administrate/views/views_generator.rb +5 -4
  114. metadata +29 -43
  115. data/app/assets/javascripts/administrate/components/has_many_form.js +0 -3
@@ -11,10 +11,19 @@ module Administrate
11
11
  collection
12
12
  end
13
13
 
14
+ def include_blank_option
15
+ options.fetch(:include_blank, false)
16
+ end
17
+
14
18
  private
15
19
 
16
20
  def collection
17
- @collection ||= options.fetch(:collection, [])
21
+ values = options.fetch(:collection, [])
22
+ if values.respond_to? :call
23
+ return values.arity.positive? ? values.call(self) : values.call
24
+ end
25
+
26
+ @collection ||= values
18
27
  end
19
28
  end
20
29
  end
@@ -3,6 +3,17 @@ require_relative "base"
3
3
  module Administrate
4
4
  module Field
5
5
  class Time < Base
6
+ def time
7
+ return I18n.localize(data, format: format) if options[:format]
8
+
9
+ data.strftime("%I:%M%p")
10
+ end
11
+
12
+ private
13
+
14
+ def format
15
+ options[:format]
16
+ end
6
17
  end
7
18
  end
8
19
  end
@@ -1,7 +1,7 @@
1
1
  module Administrate
2
2
  class Namespace
3
3
  def initialize(namespace)
4
- @namespace = namespace
4
+ @namespace = namespace.to_sym
5
5
  end
6
6
 
7
7
  def resources
@@ -18,6 +18,10 @@ module Administrate
18
18
  end
19
19
  end
20
20
 
21
+ def resources_with_index_route
22
+ routes.select { |_resource, route| route == "index" }.map(&:first).uniq
23
+ end
24
+
21
25
  private
22
26
 
23
27
  attr_reader :namespace
@@ -2,7 +2,7 @@ module Administrate
2
2
  class Order
3
3
  def initialize(attribute = nil, direction = nil)
4
4
  @attribute = attribute
5
- @direction = direction || :asc
5
+ @direction = sanitize_direction(direction)
6
6
  end
7
7
 
8
8
  def apply(relation)
@@ -11,7 +11,7 @@ module Administrate
11
11
 
12
12
  order = "#{relation.table_name}.#{attribute} #{direction}"
13
13
 
14
- return relation.reorder(order) if
14
+ return relation.reorder(Arel.sql(order)) if
15
15
  relation.columns_hash.keys.include?(attribute.to_s)
16
16
 
17
17
  relation
@@ -34,6 +34,10 @@ module Administrate
34
34
 
35
35
  attr_reader :attribute
36
36
 
37
+ def sanitize_direction(direction)
38
+ %w[asc desc].include?(direction.to_s) ? direction.to_sym : :asc
39
+ end
40
+
37
41
  def reversed_direction_param_for(attr)
38
42
  if ordered_by?(attr)
39
43
  opposite_direction
@@ -43,7 +47,7 @@ module Administrate
43
47
  end
44
48
 
45
49
  def opposite_direction
46
- direction.to_sym == :asc ? :desc : :asc
50
+ direction == :asc ? :desc : :asc
47
51
  end
48
52
 
49
53
  def order_by_association(relation)
@@ -55,14 +59,16 @@ module Administrate
55
59
  end
56
60
 
57
61
  def order_by_count(relation)
62
+ klass = reflect_association(relation).klass
63
+ query = "COUNT(#{klass.table_name}.#{klass.primary_key}) #{direction}"
58
64
  relation.
59
- left_joins(attribute.to_sym).
60
- group(:id).
61
- reorder("COUNT(#{attribute}.id) #{direction}")
65
+ left_joins(attribute.to_sym).
66
+ group(:id).
67
+ reorder(Arel.sql(query))
62
68
  end
63
69
 
64
70
  def order_by_id(relation)
65
- relation.reorder("#{attribute}_id #{direction}")
71
+ relation.reorder("#{foreign_key(relation)} #{direction}")
66
72
  end
67
73
 
68
74
  def has_many_attribute?(relation)
@@ -76,5 +82,9 @@ module Administrate
76
82
  def reflect_association(relation)
77
83
  relation.klass.reflect_on_association(attribute.to_s)
78
84
  end
85
+
86
+ def foreign_key(relation)
87
+ reflect_association(relation).foreign_key
88
+ end
79
89
  end
80
90
  end
@@ -23,7 +23,7 @@ module Administrate
23
23
  dashboard.try(:item_includes) || []
24
24
  end
25
25
 
26
- protected
26
+ private
27
27
 
28
28
  def attribute_field(dashboard, resource, attribute_name, page)
29
29
  value = get_attribute_value(resource, attribute_name)
@@ -33,8 +33,6 @@ module Administrate
33
33
 
34
34
  def get_attribute_value(resource, attribute_name)
35
35
  resource.public_send(attribute_name)
36
- rescue NameError
37
- nil
38
36
  end
39
37
 
40
38
  attr_reader :dashboard, :options
@@ -10,8 +10,15 @@ module Administrate
10
10
 
11
11
  attr_reader :resource
12
12
 
13
- def attributes
14
- dashboard.form_attributes.map do |attribute|
13
+ def attributes(action = nil)
14
+ action =
15
+ case action
16
+ when "update" then "edit"
17
+ when "create" then "new"
18
+ else action
19
+ end
20
+
21
+ dashboard.form_attributes(action).map do |attribute|
15
22
  attribute_field(dashboard, resource, attribute, :form)
16
23
  end
17
24
  end
@@ -20,7 +27,7 @@ module Administrate
20
27
  dashboard.display_resource(resource)
21
28
  end
22
29
 
23
- protected
30
+ private
24
31
 
25
32
  attr_reader :dashboard
26
33
  end
@@ -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
@@ -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}:\w*$/) }
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.17.0".freeze
3
3
  end
@@ -1,11 +1,11 @@
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 :namespace, type: :string, default: :admin
9
9
 
10
10
  def self.template_source_path
11
11
  File.expand_path(
@@ -14,12 +14,18 @@ module Administrate
14
14
  )
15
15
  end
16
16
 
17
+ private
18
+
19
+ def namespace
20
+ options[:namespace]
21
+ end
22
+
17
23
  def copy_resource_template(template_name)
18
24
  template_file = "#{template_name}.html.erb"
19
25
 
20
26
  copy_file(
21
27
  template_file,
22
- "app/views/admin/#{resource_path}/#{template_file}",
28
+ "app/views/#{namespace}/#{resource_path}/#{template_file}",
23
29
  )
24
30
  end
25
31
 
data/lib/administrate.rb CHANGED
@@ -1,4 +1,23 @@
1
1
  require "administrate/engine"
2
2
 
3
3
  module Administrate
4
+ def self.warn_of_missing_resource_class
5
+ ActiveSupport::Deprecation.warn(
6
+ "Calling Field::Base.permitted_attribute without the option " +
7
+ ":resource_class is deprecated. If you are seeing this " +
8
+ "message, you are probably using a custom field type that" +
9
+ "does this. Please make sure to update it to a version that " +
10
+ "does not use a deprecated API",
11
+ )
12
+ end
13
+
14
+ def self.warn_of_deprecated_option(name)
15
+ ActiveSupport::Deprecation.warn(
16
+ "The option :#{name} is deprecated. " +
17
+ "Administrate should detect it automatically. " +
18
+ "Please file an issue at " +
19
+ "https://github.com/thoughtbot/administrate/issues " +
20
+ "if you think otherwise.",
21
+ )
22
+ end
4
23
  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,7 @@ 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 :namespace, type: :string, default: :admin
28
31
 
29
32
  source_root File.expand_path("../templates", __FILE__)
30
33
 
@@ -107,11 +110,11 @@ module Administrate
107
110
  if relationship.has_one?
108
111
  "Field::HasOne"
109
112
  elsif relationship.collection?
110
- "Field::HasMany" + relationship_options_string(relationship)
113
+ "Field::HasMany"
111
114
  elsif relationship.polymorphic?
112
115
  "Field::Polymorphic"
113
116
  else
114
- "Field::BelongsTo" + relationship_options_string(relationship)
117
+ "Field::BelongsTo"
115
118
  end
116
119
  end
117
120
 
@@ -119,14 +122,6 @@ module Administrate
119
122
  @klass ||= Object.const_get(class_name)
120
123
  end
121
124
 
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
125
  def options_string(options)
131
126
  if options.any?
132
127
  ".with_options(#{inspect_hash_as_ruby(options)})"
@@ -136,7 +131,16 @@ module Administrate
136
131
  end
137
132
 
138
133
  def inspect_hash_as_ruby(hash)
139
- hash.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
134
+ hash.map do |key, value|
135
+ v_str = value.respond_to?(:call) ? proc_string(value) : value.inspect
136
+ "#{key}: #{v_str}"
137
+ end.join(", ")
138
+ end
139
+
140
+ def proc_string(value)
141
+ source = value.source_location
142
+ proc_string = IO.readlines(source.first)[source.second - 1]
143
+ proc_string[/->[^}]*} | (lambda|proc).*end/x]
140
144
  end
141
145
  end
142
146
  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,15 +16,28 @@ 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).
40
+ # transform_values { |value| value == "" ? nil : value }
29
41
  # end
30
42
 
31
43
  # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
@@ -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"
@@ -13,7 +19,7 @@ module Administrate
13
19
  def run_routes_generator
14
20
  if dashboard_resources.none?
15
21
  call_generator("administrate:routes", "--namespace", namespace)
16
- load Rails.root.join("config/routes.rb")
22
+ Rails.application.reload_routes!
17
23
  end
18
24
  end
19
25
 
@@ -31,6 +37,12 @@ module Administrate
31
37
  end
32
38
  end
33
39
 
40
+ def model_check
41
+ if valid_dashboard_models.none?
42
+ puts "WARNING: Add models before installing Administrate."
43
+ end
44
+ end
45
+
34
46
  private
35
47
 
36
48
  def namespace
@@ -44,6 +56,30 @@ module Administrate
44
56
  def dashboard_resources
45
57
  Administrate::Namespace.new(namespace).resources
46
58
  end
59
+
60
+ def valid_dashboard_models
61
+ database_models - invalid_dashboard_models
62
+ end
63
+
64
+ def database_models
65
+ ActiveRecord::Base.descendants.reject(&:abstract_class?)
66
+ end
67
+
68
+ def invalid_dashboard_models
69
+ (models_without_tables + namespaced_models + unnamed_constants).uniq
70
+ end
71
+
72
+ def models_without_tables
73
+ database_models.reject(&:table_exists?)
74
+ end
75
+
76
+ def namespaced_models
77
+ database_models.select { |model| model.to_s.include?("::") }
78
+ end
79
+
80
+ def unnamed_constants
81
+ ActiveRecord::Base.descendants.reject { |d| d.name == d.to_s }
82
+ end
47
83
  end
48
84
  end
49
85
  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