activeadmin 2.1.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activeadmin might be problematic. Click here for more details.

Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +112 -27
  3. data/CONTRIBUTING.md +50 -26
  4. data/README.md +8 -1
  5. data/app/assets/javascripts/active_admin/base.js +509 -0
  6. data/app/assets/stylesheets/active_admin/_base.scss +29 -29
  7. data/app/assets/stylesheets/active_admin/_header.scss +3 -5
  8. data/app/assets/stylesheets/active_admin/_mixins.scss +1 -1
  9. data/{vendor → app}/assets/stylesheets/active_admin/_normalize.scss +0 -0
  10. data/app/assets/stylesheets/active_admin/components/_tables.scss +1 -2
  11. data/app/assets/stylesheets/active_admin/mixins/_all.scss +8 -8
  12. data/app/assets/stylesheets/active_admin/mixins/_variables.scss +5 -0
  13. data/app/assets/stylesheets/active_admin/print.scss +2 -2
  14. data/app/assets/stylesheets/active_admin/structure/_main_structure.scss +1 -1
  15. data/app/javascript/active_admin/base.js +19 -0
  16. data/app/{assets/javascripts/active_admin/ext/jquery-ui.es6 → javascript/active_admin/ext/jquery-ui.js} +0 -0
  17. data/app/{assets/javascripts/active_admin/ext/jquery.es6 → javascript/active_admin/ext/jquery.js} +0 -0
  18. data/app/{assets/javascripts/active_admin/lib/batch_actions.es6 → javascript/active_admin/initializers/batch-actions.js} +9 -3
  19. data/app/javascript/active_admin/initializers/checkbox-toggler.js +3 -0
  20. data/app/{assets/javascripts/active_admin/initializers/datepicker.es6 → javascript/active_admin/initializers/datepicker.js} +0 -0
  21. data/app/javascript/active_admin/initializers/dropdown-menu.js +9 -0
  22. data/app/javascript/active_admin/initializers/filters.js +10 -0
  23. data/app/{assets/javascripts/active_admin/lib/has_many.es6 → javascript/active_admin/initializers/has-many.js} +0 -0
  24. data/app/javascript/active_admin/initializers/per-page.js +13 -0
  25. data/app/javascript/active_admin/initializers/table-checkbox-toggler.js +3 -0
  26. data/app/{assets/javascripts/active_admin/initializers/tabs.es6 → javascript/active_admin/initializers/tabs.js} +0 -0
  27. data/app/{assets/javascripts/active_admin/lib/checkbox-toggler.es6 → javascript/active_admin/lib/checkbox-toggler.js} +2 -2
  28. data/app/{assets/javascripts/active_admin/lib/dropdown-menu.es6 → javascript/active_admin/lib/dropdown-menu.js} +2 -9
  29. data/app/javascript/active_admin/lib/filters.js +39 -0
  30. data/app/{assets/javascripts/active_admin/lib/modal_dialog.es6 → javascript/active_admin/lib/modal-dialog.js} +3 -1
  31. data/app/javascript/active_admin/lib/per-page.js +38 -0
  32. data/app/{assets/javascripts/active_admin/lib/table-checkbox-toggler.es6 → javascript/active_admin/lib/table-checkbox-toggler.js} +4 -2
  33. data/app/javascript/active_admin/lib/utils.js +40 -0
  34. data/app/views/kaminari/active_admin_countless/_first_page.html.erb +11 -0
  35. data/app/views/kaminari/active_admin_countless/_gap.html.erb +8 -0
  36. data/app/views/kaminari/active_admin_countless/_next_page.html.erb +11 -0
  37. data/app/views/kaminari/active_admin_countless/_page.html.erb +12 -0
  38. data/app/views/kaminari/active_admin_countless/_paginator.html.erb +24 -0
  39. data/app/views/kaminari/active_admin_countless/_prev_page.html.erb +11 -0
  40. data/config/locales/ar.yml +3 -2
  41. data/config/locales/az.yml +138 -0
  42. data/config/locales/bg.yml +1 -0
  43. data/config/locales/bs.yml +1 -0
  44. data/config/locales/ca.yml +1 -1
  45. data/config/locales/cs.yml +1 -0
  46. data/config/locales/da.yml +1 -0
  47. data/config/locales/de-CH.yml +1 -0
  48. data/config/locales/de.yml +19 -0
  49. data/config/locales/el.yml +1 -0
  50. data/config/locales/en-CA.yml +1 -0
  51. data/config/locales/en-GB.yml +1 -0
  52. data/config/locales/en.yml +1 -0
  53. data/config/locales/eo.yml +1 -0
  54. data/config/locales/es-MX.yml +1 -0
  55. data/config/locales/es.yml +1 -0
  56. data/config/locales/fa.yml +1 -0
  57. data/config/locales/fi.yml +1 -0
  58. data/config/locales/fr.yml +2 -1
  59. data/config/locales/he.yml +1 -0
  60. data/config/locales/hr.yml +1 -0
  61. data/config/locales/hu.yml +1 -0
  62. data/config/locales/id.yml +1 -0
  63. data/config/locales/it.yml +1 -0
  64. data/config/locales/ja.yml +1 -0
  65. data/config/locales/ko.yml +1 -0
  66. data/config/locales/lt.yml +1 -0
  67. data/config/locales/lv.yml +1 -0
  68. data/config/locales/mk.yml +134 -0
  69. data/config/locales/nb.yml +1 -0
  70. data/config/locales/nl.yml +1 -0
  71. data/config/locales/pl.yml +1 -0
  72. data/config/locales/pt-BR.yml +1 -0
  73. data/config/locales/pt-PT.yml +1 -0
  74. data/config/locales/ro.yml +1 -0
  75. data/config/locales/ru.yml +1 -0
  76. data/config/locales/sk.yml +60 -0
  77. data/config/locales/sv-SE.yml +1 -0
  78. data/config/locales/tr.yml +1 -0
  79. data/config/locales/uk.yml +1 -0
  80. data/config/locales/vi.yml +1 -0
  81. data/config/locales/zh-CN.yml +1 -0
  82. data/config/locales/zh-TW.yml +1 -0
  83. data/docs/1-general-configuration.md +20 -0
  84. data/docs/12-arbre-components.md +13 -0
  85. data/docs/13-authorization-adapter.md +2 -2
  86. data/docs/2-resource-customization.md +1 -1
  87. data/docs/3-index-pages/index-as-table.md +7 -0
  88. data/docs/Gemfile +0 -1
  89. data/docs/Gemfile.lock +58 -58
  90. data/docs/_config.yml +2 -0
  91. data/docs/_includes/top-menu.html +2 -2
  92. data/docs/index.html +108 -7
  93. data/docs/stylesheets/main.css +29 -0
  94. data/lib/active_admin.rb +0 -1
  95. data/lib/active_admin/application.rb +12 -3
  96. data/lib/active_admin/batch_actions/resource_extension.rb +5 -1
  97. data/lib/active_admin/controller_action.rb +2 -1
  98. data/lib/active_admin/csv_builder.rb +3 -2
  99. data/lib/active_admin/dependency.rb +0 -4
  100. data/lib/active_admin/error.rb +3 -1
  101. data/lib/active_admin/filters/active_filter.rb +3 -4
  102. data/lib/active_admin/filters/resource_extension.rb +24 -0
  103. data/lib/active_admin/generators/boilerplate.rb +12 -4
  104. data/lib/active_admin/inputs/filters/date_range_input.rb +4 -4
  105. data/lib/active_admin/namespace_settings.rb +13 -0
  106. data/lib/active_admin/order_clause.rb +1 -1
  107. data/lib/active_admin/page_presenter.rb +2 -1
  108. data/lib/active_admin/pundit_adapter.rb +7 -3
  109. data/lib/active_admin/resource.rb +16 -2
  110. data/lib/active_admin/resource/belongs_to.rb +6 -1
  111. data/lib/active_admin/resource/model.rb +15 -0
  112. data/lib/active_admin/resource/routes.rb +11 -3
  113. data/lib/active_admin/resource_controller.rb +2 -0
  114. data/lib/active_admin/resource_controller/decorators.rb +2 -2
  115. data/lib/active_admin/resource_controller/polymorphic_routes.rb +37 -0
  116. data/lib/active_admin/router.rb +2 -1
  117. data/lib/active_admin/scope.rb +7 -3
  118. data/lib/active_admin/sidebar_section.rb +3 -1
  119. data/lib/active_admin/version.rb +1 -1
  120. data/lib/active_admin/view_helpers/breadcrumb_helper.rb +2 -2
  121. data/lib/active_admin/view_helpers/display_helper.rb +3 -2
  122. data/lib/active_admin/views/components/paginated_collection.rb +3 -2
  123. data/lib/active_admin/views/components/status_tag.rb +5 -1
  124. data/lib/active_admin/views/components/table_for.rb +1 -0
  125. data/lib/active_admin/views/index_as_table.rb +7 -0
  126. data/lib/active_admin/views/pages/base.rb +1 -1
  127. data/lib/active_admin/views/pages/index.rb +1 -0
  128. data/lib/generators/active_admin/install/templates/active_admin.rb.erb +14 -1
  129. data/lib/generators/active_admin/resource/templates/admin.rb.erb +40 -37
  130. data/lib/ransack_ext.rb +2 -2
  131. metadata +38 -45
  132. data/app/assets/images/active_admin/nested_menu_arrow.gif +0 -0
  133. data/app/assets/images/active_admin/nested_menu_arrow_dark.gif +0 -0
  134. data/app/assets/images/active_admin/orderable.png +0 -0
  135. data/app/assets/javascripts/active_admin/base.es6 +0 -23
  136. data/app/assets/javascripts/active_admin/initializers/filters.es6 +0 -45
  137. data/app/assets/javascripts/active_admin/lib/active_admin.es6 +0 -41
  138. data/app/assets/javascripts/active_admin/lib/per_page.es6 +0 -47
@@ -615,6 +615,35 @@ body #tidelift a .cta {
615
615
  padding-left: 30px;
616
616
  }
617
617
 
618
+ body .tidelift-buttons a {
619
+ display: table;
620
+ width: 200px;
621
+ border: 2px solid #407985;
622
+ border-radius: 4px;
623
+ text-decoration: none;
624
+ font-family: 'Yanone Kaffeesatz', 'Helvetica Neue', Arial, Helvetica, sans-serif;
625
+ font-size: 18px;
626
+ letter-spacing: 1px;
627
+ margin: 0 10px;
628
+ }
629
+
630
+ body .tidelift-buttons a:first-child {
631
+ float: left;
632
+ color: #407985;
633
+ background: #FFF;
634
+ }
635
+
636
+ body .tidelift-buttons a:last-child {
637
+ color: #FFF;
638
+ background: #407985;
639
+ }
640
+
641
+ body .tidelift-buttons a span {
642
+ display: table-cell;
643
+ vertical-align: middle;
644
+ text-align: center;
645
+ }
646
+
618
647
  body .clear {
619
648
  clear: both;
620
649
  }
@@ -10,7 +10,6 @@ require 'inherited_resources'
10
10
  require 'jquery-rails'
11
11
  require 'sassc-rails'
12
12
  require 'arbre'
13
- require 'sprockets/es6'
14
13
 
15
14
  require 'active_admin/helpers/i18n'
16
15
 
@@ -73,7 +73,7 @@ module ActiveAdmin
73
73
  def namespace(name)
74
74
  name ||= :root
75
75
 
76
- namespace = namespaces[name] ||= begin
76
+ namespace = namespaces[name.to_sym] ||= begin
77
77
  namespace = Namespace.new(self, name)
78
78
  ActiveSupport::Notifications.publish ActiveAdmin::Namespace::RegisterEvent, namespace
79
79
  namespace
@@ -187,8 +187,17 @@ module ActiveAdmin
187
187
  # regenerate the routes as well.
188
188
  def attach_reloader
189
189
  Rails.application.config.after_initialize do |app|
190
- ActiveSupport::Reloader.after_class_unload do
191
- ActiveAdmin.application.unload!
190
+ unload_active_admin = -> { ActiveAdmin.application.unload! }
191
+
192
+ if app.config.reload_classes_only_on_change
193
+ # Rails is about to unload all the app files (e.g. models), so we
194
+ # should first unload the classes generated by Active Admin, otherwise
195
+ # they will contain references to the stale (unloaded) classes.
196
+ ActiveSupport::Reloader.to_prepare(prepend: true, &unload_active_admin)
197
+ else
198
+ # If the user has configured the app to always reload app files after
199
+ # each request, so we should unload the generated classes too.
200
+ ActiveSupport::Reloader.to_complete(&unload_active_admin)
192
201
  end
193
202
 
194
203
  admin_dirs = {}
@@ -112,7 +112,11 @@ module ActiveAdmin
112
112
  # => You can pass a hash of options to `:form` that will be rendered as form input fields for the user to fill out.
113
113
  #
114
114
  def initialize(sym, title, options = {}, &block)
115
- @sym, @title, @options, @block, @confirm = sym, title, options, block, options[:confirm]
115
+ @sym = sym
116
+ @title = title
117
+ @options = options
118
+ @block = block
119
+ @confirm = options[:confirm]
116
120
  @block ||= proc {}
117
121
  end
118
122
 
@@ -2,7 +2,8 @@ module ActiveAdmin
2
2
  class ControllerAction
3
3
  attr_reader :name
4
4
  def initialize(name, options = {})
5
- @name, @options = name, options
5
+ @name = name
6
+ @options = options
6
7
  end
7
8
 
8
9
  def http_verb
@@ -32,7 +32,9 @@ module ActiveAdmin
32
32
 
33
33
  def initialize(options = {}, &block)
34
34
  @resource = options.delete(:resource)
35
- @columns, @options, @block = [], options, block
35
+ @columns = []
36
+ @options = ActiveAdmin.application.csv_options.merge options
37
+ @block = block
36
38
  end
37
39
 
38
40
  def column(name, options = {}, &block)
@@ -42,7 +44,6 @@ module ActiveAdmin
42
44
  def build(controller, csv)
43
45
  @collection = controller.send :find_collection, except: :pagination
44
46
  columns = exec_columns controller.view_context
45
- options = ActiveAdmin.application.csv_options.merge self.options
46
47
  bom = options.delete :byte_order_mark
47
48
  column_names = options.delete(:column_names) { true }
48
49
  csv_options = options.except :encoding_options, :humanize_name
@@ -55,10 +55,6 @@ module ActiveAdmin
55
55
  Matcher.new name.to_s
56
56
  end
57
57
 
58
- def self.rails_version
59
- rails.spec.version
60
- end
61
-
62
58
  def self.supports_zeitwerk?
63
59
  rails >= "6.0.0.beta3" && RUBY_ENGINE != "jruby"
64
60
  end
@@ -6,7 +6,9 @@ module ActiveAdmin
6
6
  attr_reader :user, :action, :subject
7
7
 
8
8
  def initialize(user, action, subject = nil)
9
- @user, @action, @subject = user, action, subject
9
+ @user = user
10
+ @action = action
11
+ @subject = subject
10
12
 
11
13
  super()
12
14
  end
@@ -26,8 +26,7 @@ module ActiveAdmin
26
26
  end
27
27
 
28
28
  def label
29
- # TODO: to remind us to go back to the simpler str.downcase once we support ruby >= 2.4 only.
30
- translated_predicate = predicate_name.mb_chars.downcase.to_s
29
+ translated_predicate = predicate_name.downcase
31
30
  if filter_label && filter_label.is_a?(Proc)
32
31
  "#{filter_label.call} #{translated_predicate}"
33
32
  elsif filter_label
@@ -67,7 +66,7 @@ module ActiveAdmin
67
66
  def filter_label
68
67
  return unless filter
69
68
 
70
- filter[:label]
69
+ filter[:label] || I18n.t(name, scope: ['formtastic', 'labels'], default: nil)
71
70
  end
72
71
 
73
72
  #@return Ransack::Nodes::Attribute
@@ -97,7 +96,7 @@ module ActiveAdmin
97
96
  end
98
97
 
99
98
  def filter
100
- resource.filters[name.to_sym]
99
+ resource.filters[name.to_sym] || resource.filters[condition.key.to_sym]
101
100
  end
102
101
 
103
102
  def related_primary_key
@@ -129,12 +129,36 @@ module ActiveAdmin
129
129
  not_poly.reject! { |r| r.chain.length > 2 }
130
130
 
131
131
  filters = poly.map(&:foreign_type) + not_poly.map(&:name)
132
+
133
+ # Check high-arity associations for filterable columns
134
+ max = namespace.maximum_association_filter_arity
135
+ if max != :unlimited
136
+ high_arity, low_arity = not_poly.partition do |r|
137
+ r.klass.reorder(nil).limit(max + 1).count > max
138
+ end
139
+
140
+ # Remove high-arity associations with no searchable column
141
+ high_arity = high_arity.select(&method(:searchable_column_for))
142
+
143
+ high_arity = high_arity.map { |r| r.name.to_s + "_" + searchable_column_for(r) + namespace.filter_method_for_large_association }
144
+
145
+ filters = poly.map(&:foreign_type) + low_arity.map(&:name) + high_arity
146
+ end
147
+
132
148
  filters.map &:to_sym
133
149
  else
134
150
  []
135
151
  end
136
152
  end
137
153
 
154
+ def search_columns
155
+ @search_columns ||= namespace.filter_columns_for_large_association.map(&:to_s)
156
+ end
157
+
158
+ def searchable_column_for(relation)
159
+ relation.klass.column_names.find { |name| search_columns.include?(name) }
160
+ end
161
+
138
162
  def add_filters_sidebar_section
139
163
  self.sidebar_sections << filters_sidebar_section
140
164
  end
@@ -9,8 +9,16 @@ module ActiveAdmin
9
9
  @class_name.constantize.new.attributes.keys
10
10
  end
11
11
 
12
+ def assignable_attributes
13
+ attributes - %w(id created_at updated_at)
14
+ end
15
+
16
+ def permit_params
17
+ assignable_attributes.map { |a| a.to_sym.inspect }.join(', ')
18
+ end
19
+
12
20
  def rows
13
- attributes.map { |a| row(a) }.join("\n")
21
+ attributes.map { |a| row(a) }.join("\n ")
14
22
  end
15
23
 
16
24
  def row(name)
@@ -18,7 +26,7 @@ module ActiveAdmin
18
26
  end
19
27
 
20
28
  def columns
21
- attributes.map { |a| column(a) }.join("\n")
29
+ attributes.map { |a| column(a) }.join("\n ")
22
30
  end
23
31
 
24
32
  def column(name)
@@ -26,7 +34,7 @@ module ActiveAdmin
26
34
  end
27
35
 
28
36
  def filters
29
- attributes.map { |a| filter(a) }.join("\n")
37
+ attributes.map { |a| filter(a) }.join("\n ")
30
38
  end
31
39
 
32
40
  def filter(name)
@@ -34,7 +42,7 @@ module ActiveAdmin
34
42
  end
35
43
 
36
44
  def form_inputs
37
- attributes.reject { |a| %w(id created_at updated_at).include? a }.map { |a| form_input(a) }.join("\n")
45
+ assignable_attributes.map { |a| form_input(a) }.join("\n ")
38
46
  end
39
47
 
40
48
  def form_input(name)
@@ -7,8 +7,8 @@ module ActiveAdmin
7
7
  def to_html
8
8
  input_wrapping do
9
9
  [ label_html,
10
- builder.text_field(gt_input_name, input_html_options(gt_input_name, gt_input_placeholder)),
11
- builder.text_field(lt_input_name, input_html_options(lt_input_name, lt_input_placeholder)),
10
+ builder.text_field(gt_input_name, input_html_options_for(gt_input_name, gt_input_placeholder)),
11
+ builder.text_field(lt_input_name, input_html_options_for(lt_input_name, lt_input_placeholder)),
12
12
  ].join("\n").html_safe
13
13
  end
14
14
  end
@@ -22,7 +22,7 @@ module ActiveAdmin
22
22
  column && column.type == :date ? "#{method}_lteq" : "#{method}_lteq_datetime"
23
23
  end
24
24
 
25
- def input_html_options(input_name = gt_input_name, placeholder = gt_input_placeholder)
25
+ def input_html_options_for(input_name = gt_input_name, placeholder = gt_input_placeholder)
26
26
  current_value = begin
27
27
  #cast value to date object before rendering input
28
28
  @object.public_send(input_name).to_s.to_date
@@ -33,7 +33,7 @@ module ActiveAdmin
33
33
  class: "datepicker",
34
34
  maxlength: 10,
35
35
  placeholder: placeholder,
36
- value: current_value ? current_value.strftime("%Y-%m-%d") : "" }
36
+ value: current_value ? current_value.strftime("%Y-%m-%d") : "" }.merge(input_html_options)
37
37
  end
38
38
 
39
39
  def gt_input_placeholder
@@ -106,5 +106,18 @@ module ActiveAdmin
106
106
 
107
107
  # Include association filters by default
108
108
  register :include_default_association_filters, true
109
+
110
+ register :maximum_association_filter_arity, :unlimited
111
+
112
+ register :filter_columns_for_large_association, [
113
+ :display_name,
114
+ :full_name,
115
+ :name,
116
+ :username,
117
+ :login,
118
+ :title,
119
+ :email,
120
+ ]
121
+ register :filter_method_for_large_association, '_starts_with'
109
122
  end
110
123
  end
@@ -3,7 +3,7 @@ module ActiveAdmin
3
3
  attr_reader :field, :order, :active_admin_config
4
4
 
5
5
  def initialize(active_admin_config, clause)
6
- clause =~ /^([\w\_\.]+)(->'\w+')?_(desc|asc)$/
6
+ clause =~ /^([\w\.]+)(->'\w+')?_(desc|asc)$/
7
7
  @column = $1
8
8
  @op = $2
9
9
  @order = $3
@@ -21,7 +21,8 @@ module ActiveAdmin
21
21
  delegate :has_key?, :fetch, to: :options
22
22
 
23
23
  def initialize(options = {}, &block)
24
- @options, @block = options, block
24
+ @options = options
25
+ @block = block
25
26
  end
26
27
 
27
28
  def [](key)
@@ -44,7 +44,7 @@ module ActiveAdmin
44
44
  end
45
45
 
46
46
  def format_action(action, subject)
47
- # https://github.com/elabs/pundit/blob/master/lib/generators/pundit/install/templates/application_policy.rb
47
+ # https://github.com/varvet/pundit/blob/master/lib/generators/pundit/install/templates/application_policy.rb
48
48
  case action
49
49
  when Auth::CREATE then :create?
50
50
  when Auth::UPDATE then :update?
@@ -57,8 +57,8 @@ module ActiveAdmin
57
57
  private
58
58
 
59
59
  def namespace(object)
60
- if ActiveAdmin.application.pundit_policy_namespace
61
- [ActiveAdmin.application.pundit_policy_namespace.to_sym, object]
60
+ if default_policy_namespace && !object.class.to_s.include?(default_policy_namespace.to_s.camelize)
61
+ [default_policy_namespace.to_sym, object]
62
62
  else
63
63
  object
64
64
  end
@@ -72,6 +72,10 @@ module ActiveAdmin
72
72
  default_policy_class.new(user, subject)
73
73
  end
74
74
 
75
+ def default_policy_namespace
76
+ ActiveAdmin.application.pundit_policy_namespace
77
+ end
78
+
75
79
  end
76
80
 
77
81
  end
@@ -12,6 +12,7 @@ require 'active_admin/resource/scope_to'
12
12
  require 'active_admin/resource/sidebars'
13
13
  require 'active_admin/resource/belongs_to'
14
14
  require 'active_admin/resource/ordering'
15
+ require 'active_admin/resource/model'
15
16
 
16
17
  module ActiveAdmin
17
18
 
@@ -69,9 +70,10 @@ module ActiveAdmin
69
70
  def initialize(namespace, resource_class, options = {})
70
71
  @namespace = namespace
71
72
  @resource_class_name = "::#{resource_class.name}"
72
- @options = options
73
+ @options = options
73
74
  @sort_order = options[:sort_order]
74
- @member_actions, @collection_actions = [], []
75
+ @member_actions = []
76
+ @collection_actions = []
75
77
  end
76
78
  end
77
79
 
@@ -103,6 +105,10 @@ module ActiveAdmin
103
105
  ActiveSupport::Dependencies.constantize(decorator_class_name) if decorator_class_name
104
106
  end
105
107
 
108
+ def resource_name_extension
109
+ @resource_name_extension ||= define_resource_name_extension(self)
110
+ end
111
+
106
112
  def resource_table_name
107
113
  resource_class.quoted_table_name
108
114
  end
@@ -132,6 +138,7 @@ module ActiveAdmin
132
138
  def belongs_to(target, options = {})
133
139
  @belongs_to = Resource::BelongsTo.new(self, target, options)
134
140
  self.menu_item_options = false if @belongs_to.required?
141
+ options[:class_name] ||= @belongs_to.resource.resource_class_name if @belongs_to.resource
135
142
  controller.send :belongs_to, target, options.dup
136
143
  end
137
144
 
@@ -202,5 +209,12 @@ module ActiveAdmin
202
209
  @default_csv_builder ||= CSVBuilder.default_for_resource(self)
203
210
  end
204
211
 
212
+ def define_resource_name_extension(resource)
213
+ Module.new do
214
+ define_method :model_name do
215
+ resource.resource_name
216
+ end
217
+ end
218
+ end
205
219
  end # class Resource
206
220
  end # module ActiveAdmin
@@ -14,8 +14,13 @@ module ActiveAdmin
14
14
  # The resource which initiated this relationship
15
15
  attr_reader :owner
16
16
 
17
+ # The name of the relation
18
+ attr_reader :target_name
19
+
17
20
  def initialize(owner, target_name, options = {})
18
- @owner, @target_name, @options = owner, target_name, options
21
+ @owner = owner
22
+ @target_name = target_name
23
+ @options = options
19
24
  end
20
25
 
21
26
  # Returns the target resource class or raises an exception if it doesn't exist
@@ -0,0 +1,15 @@
1
+ module ActiveAdmin
2
+ class Model
3
+ def initialize(resource, record)
4
+ @record = record
5
+
6
+ if resource
7
+ @record.extend(resource.resource_name_extension)
8
+ end
9
+ end
10
+
11
+ def to_model
12
+ @record
13
+ end
14
+ end
15
+ end
@@ -110,7 +110,7 @@ module ActiveAdmin
110
110
  # @return params to pass to instance path
111
111
  def route_instance_params(instance)
112
112
  if nested?
113
- [instance.public_send(belongs_to_name).to_param, instance.to_param]
113
+ [instance.public_send(belongs_to_target_name).to_param, instance.to_param]
114
114
  else
115
115
  instance.to_param
116
116
  end
@@ -123,11 +123,19 @@ module ActiveAdmin
123
123
  end
124
124
 
125
125
  def nested?
126
- resource.belongs_to? && resource.belongs_to_config.required?
126
+ resource.belongs_to? && belongs_to_config.required?
127
+ end
128
+
129
+ def belongs_to_target_name
130
+ belongs_to_config.target_name
127
131
  end
128
132
 
129
133
  def belongs_to_name
130
- resource.belongs_to_config.target.resource_name.singular if nested?
134
+ belongs_to_config.target.resource_name.singular
135
+ end
136
+
137
+ def belongs_to_config
138
+ resource.belongs_to_config
131
139
  end
132
140
 
133
141
  def routes