dry_crud 1.7.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +126 -87
  4. data/VERSION +1 -1
  5. data/lib/generators/dry_crud/dry_crud_generator.rb +42 -22
  6. data/lib/generators/dry_crud/templates/INSTALL +5 -5
  7. data/lib/generators/dry_crud/templates/app/assets/stylesheets/crud.scss +0 -20
  8. data/lib/generators/dry_crud/templates/app/assets/stylesheets/sample.scss +24 -4
  9. data/lib/generators/dry_crud/templates/app/controllers/crud/generic_model.rb +89 -0
  10. data/lib/generators/dry_crud/templates/app/controllers/crud/nestable.rb +70 -0
  11. data/lib/generators/dry_crud/templates/app/controllers/crud/rememberable.rb +64 -0
  12. data/lib/generators/dry_crud/templates/app/controllers/crud/render_callbacks.rb +46 -0
  13. data/lib/generators/dry_crud/templates/app/controllers/crud/responder.rb +31 -0
  14. data/lib/generators/dry_crud/templates/app/controllers/crud/searchable.rb +55 -0
  15. data/lib/generators/dry_crud/templates/app/controllers/crud/sortable.rb +63 -0
  16. data/lib/generators/dry_crud/templates/app/controllers/crud_controller.rb +66 -69
  17. data/lib/generators/dry_crud/templates/app/controllers/list_controller.rb +23 -326
  18. data/lib/generators/dry_crud/templates/app/helpers/actions_helper.rb +64 -0
  19. data/lib/generators/dry_crud/templates/app/helpers/crud/form_builder.rb +331 -0
  20. data/lib/generators/dry_crud/templates/app/helpers/crud/table_builder.rb +280 -0
  21. data/lib/generators/dry_crud/templates/app/helpers/form_helper.rb +52 -0
  22. data/lib/generators/dry_crud/templates/app/helpers/format_helper.rb +164 -0
  23. data/lib/generators/dry_crud/templates/app/helpers/i18n_helper.rb +85 -0
  24. data/lib/generators/dry_crud/templates/app/helpers/table_helper.rb +83 -0
  25. data/lib/generators/dry_crud/templates/app/helpers/utility_helper.rb +84 -0
  26. data/lib/generators/dry_crud/templates/app/views/crud/_actions_edit.html.erb +3 -3
  27. data/lib/generators/dry_crud/templates/app/views/crud/_actions_edit.html.haml +3 -3
  28. data/lib/generators/dry_crud/templates/app/views/crud/_actions_index.html.erb +1 -1
  29. data/lib/generators/dry_crud/templates/app/views/crud/_actions_index.html.haml +1 -1
  30. data/lib/generators/dry_crud/templates/app/views/crud/_actions_show.html.erb +3 -3
  31. data/lib/generators/dry_crud/templates/app/views/crud/_actions_show.html.haml +3 -3
  32. data/lib/generators/dry_crud/templates/app/views/crud/_attrs.html.erb +1 -1
  33. data/lib/generators/dry_crud/templates/app/views/crud/_attrs.html.haml +1 -1
  34. data/lib/generators/dry_crud/templates/app/views/crud/_form.html.erb +1 -1
  35. data/lib/generators/dry_crud/templates/app/views/crud/_form.html.haml +1 -1
  36. data/lib/generators/dry_crud/templates/app/views/crud/edit.html.erb +1 -1
  37. data/lib/generators/dry_crud/templates/app/views/crud/edit.html.haml +1 -1
  38. data/lib/generators/dry_crud/templates/app/views/crud/new.html.erb +2 -2
  39. data/lib/generators/dry_crud/templates/app/views/crud/new.html.haml +2 -2
  40. data/lib/generators/dry_crud/templates/app/views/crud/show.html.erb +1 -1
  41. data/lib/generators/dry_crud/templates/app/views/crud/show.html.haml +1 -1
  42. data/lib/generators/dry_crud/templates/app/views/layouts/_flash.html.haml +1 -1
  43. data/lib/generators/dry_crud/templates/app/views/layouts/_nav.html.erb +1 -1
  44. data/lib/generators/dry_crud/templates/app/views/layouts/_nav.html.haml +1 -1
  45. data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.erb +15 -7
  46. data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.haml +18 -8
  47. data/lib/generators/dry_crud/templates/app/views/list/_search.html.erb +3 -3
  48. data/lib/generators/dry_crud/templates/app/views/list/_search.html.haml +3 -3
  49. data/lib/generators/dry_crud/templates/app/views/list/index.html.erb +1 -1
  50. data/lib/generators/dry_crud/templates/app/views/list/index.html.haml +1 -1
  51. data/lib/generators/dry_crud/templates/app/views/shared/_error_messages.html.erb +1 -1
  52. data/lib/generators/dry_crud/templates/app/views/shared/_error_messages.html.haml +1 -1
  53. data/lib/generators/dry_crud/templates/app/views/shared/_labeled.html.erb +2 -4
  54. data/lib/generators/dry_crud/templates/app/views/shared/_labeled.html.haml +2 -3
  55. data/lib/generators/dry_crud/templates/config/initializers/field_error_proc.rb +5 -1
  56. data/lib/generators/dry_crud/templates/config/locales/crud.de.yml +64 -0
  57. data/lib/generators/dry_crud/templates/config/locales/{en_crud.yml → crud.en.yml} +2 -2
  58. data/lib/generators/dry_crud/templates/spec/controllers/crud_test_models_controller_spec.rb +241 -231
  59. data/lib/generators/dry_crud/templates/spec/helpers/crud/form_builder_spec.rb +226 -0
  60. data/lib/generators/dry_crud/templates/spec/helpers/{standard_table_builder_spec.rb → crud/table_builder_spec.rb} +36 -34
  61. data/lib/generators/dry_crud/templates/spec/helpers/form_helper_spec.rb +238 -0
  62. data/lib/generators/dry_crud/templates/spec/helpers/format_helper_spec.rb +244 -0
  63. data/lib/generators/dry_crud/templates/spec/helpers/i18n_helper_spec.rb +132 -0
  64. data/lib/generators/dry_crud/templates/spec/helpers/table_helper_spec.rb +265 -0
  65. data/lib/generators/dry_crud/templates/spec/helpers/utility_helper_spec.rb +74 -0
  66. data/lib/generators/dry_crud/templates/spec/support/crud_controller_examples.rb +185 -100
  67. data/lib/generators/dry_crud/templates/spec/support/crud_controller_test_helper.rb +58 -49
  68. data/lib/generators/dry_crud/templates/test/{functional → controllers}/crud_test_models_controller_test.rb +112 -91
  69. data/lib/generators/dry_crud/templates/test/{unit/helpers/standard_form_builder_test.rb → helpers/crud/form_builder_test.rb} +79 -62
  70. data/lib/generators/dry_crud/templates/test/{unit/helpers/standard_table_builder_test.rb → helpers/crud/table_builder_test.rb} +31 -28
  71. data/lib/generators/dry_crud/templates/test/helpers/custom_assertions_test.rb +85 -0
  72. data/lib/generators/dry_crud/templates/test/helpers/form_helper_test.rb +129 -0
  73. data/lib/generators/dry_crud/templates/test/helpers/format_helper_test.rb +163 -0
  74. data/lib/generators/dry_crud/templates/test/helpers/i18n_helper_test.rb +79 -0
  75. data/lib/generators/dry_crud/templates/test/helpers/table_helper_test.rb +217 -0
  76. data/lib/generators/dry_crud/templates/test/helpers/utility_helper_test.rb +63 -0
  77. data/lib/generators/dry_crud/templates/test/{functional → support}/crud_controller_test_helper.rb +70 -59
  78. data/lib/generators/dry_crud/templates/test/{crud_test_model.rb → support/crud_test_model.rb} +107 -75
  79. data/lib/generators/dry_crud/templates/test/support/custom_assertions.rb +83 -0
  80. metadata +83 -146
  81. data/Rakefile +0 -211
  82. data/lib/generators/dry_crud/templates/app/helpers/crud_helper.rb +0 -168
  83. data/lib/generators/dry_crud/templates/app/helpers/list_helper.rb +0 -27
  84. data/lib/generators/dry_crud/templates/app/helpers/standard_form_builder.rb +0 -261
  85. data/lib/generators/dry_crud/templates/app/helpers/standard_helper.rb +0 -304
  86. data/lib/generators/dry_crud/templates/app/helpers/standard_table_builder.rb +0 -178
  87. data/lib/generators/dry_crud/templates/spec/helpers/crud_helper_spec.rb +0 -146
  88. data/lib/generators/dry_crud/templates/spec/helpers/list_helper_spec.rb +0 -154
  89. data/lib/generators/dry_crud/templates/spec/helpers/standard_form_builder_spec.rb +0 -215
  90. data/lib/generators/dry_crud/templates/spec/helpers/standard_helper_spec.rb +0 -387
  91. data/lib/generators/dry_crud/templates/test/custom_assertions.rb +0 -78
  92. data/lib/generators/dry_crud/templates/test/unit/custom_assertions_test.rb +0 -117
  93. data/lib/generators/dry_crud/templates/test/unit/helpers/crud_helper_test.rb +0 -111
  94. data/lib/generators/dry_crud/templates/test/unit/helpers/list_helper_test.rb +0 -123
  95. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_helper_test.rb +0 -281
  96. data/test/templates/Gemfile +0 -46
  97. data/test/templates/app/controllers/admin/cities_controller.rb +0 -7
  98. data/test/templates/app/controllers/admin/countries_controller.rb +0 -13
  99. data/test/templates/app/controllers/ajax_controller.rb +0 -9
  100. data/test/templates/app/controllers/people_controller.rb +0 -13
  101. data/test/templates/app/controllers/vips_controller.rb +0 -19
  102. data/test/templates/app/helpers/cities_helper.rb +0 -9
  103. data/test/templates/app/helpers/people_helper.rb +0 -8
  104. data/test/templates/app/models/city.rb +0 -28
  105. data/test/templates/app/models/country.rb +0 -16
  106. data/test/templates/app/models/person.rb +0 -12
  107. data/test/templates/app/views/admin/cities/_actions_index.html.erb +0 -2
  108. data/test/templates/app/views/admin/cities/_actions_index.html.haml +0 -2
  109. data/test/templates/app/views/admin/cities/_attrs.html.erb +0 -1
  110. data/test/templates/app/views/admin/cities/_attrs.html.haml +0 -1
  111. data/test/templates/app/views/admin/cities/_form.html.erb +0 -7
  112. data/test/templates/app/views/admin/cities/_form.html.haml +0 -5
  113. data/test/templates/app/views/admin/cities/_hello.html.erb +0 -1
  114. data/test/templates/app/views/admin/cities/_hello.html.haml +0 -1
  115. data/test/templates/app/views/admin/cities/_list.html.erb +0 -3
  116. data/test/templates/app/views/admin/cities/_list.html.haml +0 -3
  117. data/test/templates/app/views/admin/countries/_list.html.erb +0 -4
  118. data/test/templates/app/views/admin/countries/_list.html.haml +0 -3
  119. data/test/templates/app/views/ajax/_actions_index.html.erb +0 -8
  120. data/test/templates/app/views/ajax/_actions_index.html.haml +0 -8
  121. data/test/templates/app/views/ajax/_actions_show.html.erb +0 -4
  122. data/test/templates/app/views/ajax/_actions_show.html.haml +0 -4
  123. data/test/templates/app/views/ajax/_form.html.erb +0 -2
  124. data/test/templates/app/views/ajax/_form.html.haml +0 -2
  125. data/test/templates/app/views/ajax/_hello.html.erb +0 -1
  126. data/test/templates/app/views/ajax/_hello.html.haml +0 -1
  127. data/test/templates/app/views/ajax/ajax.js.erb +0 -1
  128. data/test/templates/app/views/ajax/ajax.js.haml +0 -1
  129. data/test/templates/app/views/ajax/edit.js.erb +0 -1
  130. data/test/templates/app/views/ajax/edit.js.haml +0 -1
  131. data/test/templates/app/views/ajax/show.js.erb +0 -1
  132. data/test/templates/app/views/ajax/show.js.haml +0 -1
  133. data/test/templates/app/views/ajax/update.js.erb +0 -5
  134. data/test/templates/app/views/ajax/update.js.haml +0 -5
  135. data/test/templates/app/views/layouts/_nav.html.erb +0 -6
  136. data/test/templates/app/views/layouts/_nav.html.haml +0 -5
  137. data/test/templates/app/views/layouts/bootstrap.html.erb +0 -68
  138. data/test/templates/app/views/layouts/bootstrap.html.haml +0 -49
  139. data/test/templates/app/views/people/_attrs.html.erb +0 -5
  140. data/test/templates/app/views/people/_attrs.html.haml +0 -4
  141. data/test/templates/app/views/people/_list.html.erb +0 -1
  142. data/test/templates/app/views/people/_list.html.haml +0 -1
  143. data/test/templates/config/database.yml +0 -21
  144. data/test/templates/config/locales/en_cities.yml +0 -56
  145. data/test/templates/config/routes.rb +0 -32
  146. data/test/templates/db/migrate/20100511174904_create_people_and_cities.rb +0 -26
  147. data/test/templates/db/seeds.rb +0 -74
  148. data/test/templates/spec/controllers/admin/cities_controller_spec.rb +0 -74
  149. data/test/templates/spec/controllers/admin/countries_controller_spec.rb +0 -56
  150. data/test/templates/spec/controllers/people_controller_spec.rb +0 -80
  151. data/test/templates/spec/routing/cities_routing_spec.rb +0 -11
  152. data/test/templates/spec/routing/countries_routing_spec.rb +0 -11
  153. data/test/templates/test/fixtures/cities.yml +0 -11
  154. data/test/templates/test/fixtures/countries.yml +0 -11
  155. data/test/templates/test/fixtures/people.yml +0 -14
  156. data/test/templates/test/functional/admin/cities_controller_test.rb +0 -59
  157. data/test/templates/test/functional/admin/countries_controller_test.rb +0 -42
  158. data/test/templates/test/functional/people_controller_test.rb +0 -68
@@ -0,0 +1,52 @@
1
+ # encoding: UTF-8
2
+
3
+ # Defines forms to edit models. The helper methods come in different
4
+ # granularities:
5
+ # * #plain_form - A form using Crud::FormBuilder.
6
+ # * #standard_form - A #plain_form for a given object and attributes with error
7
+ # messages and save and cancel buttons.
8
+ # * #crud_form - A #standard_form for the current +entry+, with the given
9
+ # attributes or default.
10
+ module FormHelper
11
+
12
+ # Renders a form using Crud::FormBuilder.
13
+ def plain_form(object, options = {}, &block)
14
+ options[:html] ||= {}
15
+ add_css_class(options[:html], 'form-horizontal')
16
+ options[:builder] ||= Crud::FormBuilder
17
+ options[:cancel_url] ||= polymorphic_path(object, returning: true)
18
+
19
+ form_for(object, options, &block)
20
+ end
21
+
22
+ # Renders a standard form for the given entry and attributes.
23
+ # The form is rendered with a basic save and cancel button.
24
+ # If a block is given, custom input fields may be rendered and attrs is
25
+ # ignored. Before the input fields, the error messages are rendered,
26
+ # if present. An options hash may be given as the last argument.
27
+ def standard_form(object, *attrs, &block)
28
+ plain_form(object, attrs.extract_options!) do |form|
29
+ content = form.error_messages
30
+
31
+ if block_given?
32
+ content << capture(form, &block)
33
+ else
34
+ content << form.labeled_input_fields(*attrs)
35
+ end
36
+
37
+ content << form.standard_actions
38
+ content.html_safe
39
+ end
40
+ end
41
+
42
+ # Renders a crud form for the current entry with default_crud_attrs or the
43
+ # given attribute array. An options hash may be given as the last argument.
44
+ # If a block is given, a custom form may be rendered and attrs is ignored.
45
+ def crud_form(*attrs, &block)
46
+ options = attrs.extract_options!
47
+ attrs = default_crud_attrs - [:created_at, :updated_at] if attrs.blank?
48
+ attrs << options
49
+ standard_form(path_args(entry), *attrs, &block)
50
+ end
51
+
52
+ end
@@ -0,0 +1,164 @@
1
+ # encoding: UTF-8
2
+
3
+ # Provides uniform formatting of basic data types, based on Ruby class (#f)
4
+ # or database column type (#format_attr). If other helpers define methods
5
+ # with names like 'format_{class}_{attr}', these methods are used for
6
+ # formatting.
7
+ #
8
+ # Futher helpers standartize the layout of multiple attributes (#render_attrs),
9
+ # values with labels (#labeled) and simple lists.
10
+ module FormatHelper
11
+
12
+ # Formats a basic value based on its Ruby class.
13
+ def f(value)
14
+ case value
15
+ when Float, BigDecimal then
16
+ number_with_precision(value, precision: t('number.format.precision'),
17
+ delimiter: t('number.format.delimiter'))
18
+ when Date then l(value)
19
+ when Time then "#{l(value.to_date)} #{l(value, format: :time)}"
20
+ when true then t('global.yes')
21
+ when false then t('global.no')
22
+ when nil then UtilityHelper::EMPTY_STRING
23
+ else value.to_s
24
+ end
25
+ end
26
+
27
+ # Formats an arbitrary attribute of the given ActiveRecord object.
28
+ # If no specific format_{class}_{attr} or format_{attr} method is found,
29
+ # formats the value as follows:
30
+ # If the value is an associated model, renders the label of this object.
31
+ # Otherwise, calls format_type.
32
+ def format_attr(obj, attr)
33
+ format_with_helper(obj, attr) ||
34
+ format_association(obj, attr) ||
35
+ format_type(obj, attr)
36
+ end
37
+
38
+ # Renders a simple unordered list, which will
39
+ # simply render all passed items or yield them
40
+ # to your block.
41
+ def simple_list(items, ul_options = {}, &block)
42
+ content_tag_nested(:ul, items, ul_options) do |item|
43
+ content_tag(:li, block_given? ? yield(item) : f(item))
44
+ end
45
+ end
46
+
47
+ # Renders a list of attributes with label and value for a given object.
48
+ # Optionally surrounded with a div.
49
+ def render_attrs(obj, *attrs)
50
+ content_tag_nested(:dl, attrs, class: 'dl-horizontal') do |a|
51
+ labeled_attr(obj, a)
52
+ end
53
+ end
54
+
55
+ # Renders the formatted content of the given attribute with a label.
56
+ def labeled_attr(obj, attr)
57
+ labeled(captionize(attr, obj.class), format_attr(obj, attr))
58
+ end
59
+
60
+ # Renders an arbitrary content with the given label. Used for uniform
61
+ # presentation.
62
+ def labeled(label, content = nil, &block)
63
+ content = capture(&block) if block_given?
64
+ render('shared/labeled', label: label, content: content)
65
+ end
66
+
67
+ # Transform the given text into a form as used by labels or table headers.
68
+ def captionize(text, clazz = nil)
69
+ text = text.to_s
70
+ if clazz.respond_to?(:human_attribute_name)
71
+ text_without_id = text.end_with?('_ids') ? text[0..-5].pluralize : text
72
+ clazz.human_attribute_name(text_without_id)
73
+ else
74
+ text.humanize.titleize
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ # Checks whether a format_{class}_{attr} or format_{attr} helper method is
81
+ # defined and calls it if is.
82
+ def format_with_helper(obj, attr)
83
+ class_name = obj.class.name.underscore.gsub('/', '_')
84
+ format_type_attr_method = :"format_#{class_name}_#{attr}"
85
+ format_attr_method = :"format_#{attr}"
86
+
87
+ if respond_to?(format_type_attr_method)
88
+ send(format_type_attr_method, obj)
89
+ elsif respond_to?(format_attr_method)
90
+ send(format_attr_method, obj)
91
+ else
92
+ false
93
+ end
94
+ end
95
+
96
+ # Checks whether the given attr is an association of obj and formats it
97
+ # accordingly if it is.
98
+ def format_association(obj, attr)
99
+ belongs_to = association(obj, attr, :belongs_to)
100
+ has_many = association(obj, attr, :has_many, :has_and_belongs_to_many)
101
+ if belongs_to
102
+ format_belongs_to(obj, belongs_to)
103
+ elsif has_many
104
+ format_has_many(obj, has_many)
105
+ else
106
+ false
107
+ end
108
+ end
109
+
110
+ # Formats an arbitrary attribute of the given object depending on its data
111
+ # type. For Active Records, take the defined data type into account for
112
+ # special types that have no own object class.
113
+ def format_type(obj, attr)
114
+ val = obj.send(attr)
115
+ return UtilityHelper::EMPTY_STRING if val.blank?
116
+
117
+ case column_type(obj, attr)
118
+ when :time then l(val, format: :time)
119
+ when :date then f(val.to_date)
120
+ when :datetime, :timestamp then f(val.time)
121
+ when :text then simple_format(h(val))
122
+ when :decimal then
123
+ number_with_precision(val.to_s.to_f,
124
+ precision: column_property(obj, attr, :scale),
125
+ delimiter: t('number.format.delimiter'))
126
+ else f(val)
127
+ end
128
+ end
129
+
130
+ # Formats an ActiveRecord +belongs_to+ association
131
+ def format_belongs_to(obj, assoc)
132
+ val = obj.send(assoc.name)
133
+ if val
134
+ assoc_link(assoc, val)
135
+ else
136
+ ta(:no_entry, assoc)
137
+ end
138
+ end
139
+
140
+ # Formats an ActiveRecord +has_and_belongs_to_many+ or
141
+ # +has_many+ association.
142
+ def format_has_many(obj, assoc)
143
+ values = obj.send(assoc.name)
144
+ if values.size == 1
145
+ assoc_link(assoc, values.first)
146
+ elsif values.present?
147
+ simple_list(values) { |val| assoc_link(assoc, val) }
148
+ else
149
+ ta(:no_entry, assoc)
150
+ end
151
+ end
152
+
153
+ # Renders a link to the given association entry.
154
+ def assoc_link(assoc, val)
155
+ link_to_unless(no_assoc_link?(assoc, val), val.to_s, val)
156
+ end
157
+
158
+ # Returns true if no link should be created when formatting the given
159
+ # association.
160
+ def no_assoc_link?(assoc, val)
161
+ !respond_to?("#{val.class.model_name.singular_route_key}_path".to_sym)
162
+ end
163
+
164
+ end
@@ -0,0 +1,85 @@
1
+ # encoding: UTF-8
2
+
3
+ # Translation helpers extending the Rails +translate+ helper to support
4
+ # translation inheritance over the controller class hierarchy.
5
+ module I18nHelper
6
+
7
+ # Translates the passed key by looking it up over the controller hierarchy.
8
+ # The key is searched in the following order:
9
+ # - {controller}.{current_partial}.{key}
10
+ # - {controller}.{current_action}.{key}
11
+ # - {controller}.global.{key}
12
+ # - {parent_controller}.{current_partial}.{key}
13
+ # - {parent_controller}.{current_action}.{key}
14
+ # - {parent_controller}.global.{key}
15
+ # - ...
16
+ # - global.{key}
17
+ def translate_inheritable(key, variables = {})
18
+ partial = @virtual_path ? @virtual_path.gsub(/.*\/_?/, '') : nil
19
+ defaults = inheritable_translation_defaults(key, partial)
20
+ variables[:default] ||= defaults
21
+ t(defaults.shift, variables)
22
+ end
23
+
24
+ alias_method :ti, :translate_inheritable
25
+
26
+ # Translates the passed key for an active record association. This helper is
27
+ # used for rendering association dependent keys in forms like :no_entry,
28
+ # :none_available or :please_select.
29
+ # The key is looked up in the following order:
30
+ # - activerecord.associations.models.{model_name}.{association_name}.{key}
31
+ # - activerecord.associations.{association_model_name}.{key}
32
+ # - global.associations.{key}
33
+ def translate_association(key, assoc = nil, variables = {})
34
+ if assoc
35
+ variables[:default] ||= [association_klass_key(assoc, key).to_sym,
36
+ :"global.associations.#{key}"]
37
+ t(association_owner_key(assoc, key), variables)
38
+ else
39
+ t("global.associations.#{key}", variables)
40
+ end
41
+ end
42
+
43
+ alias_method :ta, :translate_association
44
+
45
+ private
46
+
47
+ # General translation key based on the klass of the association.
48
+ def association_klass_key(assoc, key)
49
+ k = 'activerecord.associations.'
50
+ k << assoc.klass.model_name.singular
51
+ k << '.'
52
+ k << key.to_s
53
+ end
54
+
55
+ # Specific translation key based on the owner model and the name
56
+ # of the association.
57
+ def association_owner_key(assoc, key)
58
+ k = 'activerecord.associations.models.'
59
+ k << assoc.active_record.model_name.singular
60
+ k << '.'
61
+ k << assoc.name.to_s
62
+ k << '.'
63
+ k << key.to_s
64
+ end
65
+
66
+ def inheritable_translation_defaults(key, partial)
67
+ defaults = []
68
+ current = controller.class
69
+ while current < ActionController::Base
70
+ folder = current.controller_path
71
+ if folder.present?
72
+ append_controller_translation_keys(defaults, folder, partial, key)
73
+ end
74
+ current = current.superclass
75
+ end
76
+ defaults << :"global.#{key}"
77
+ end
78
+
79
+ def append_controller_translation_keys(defaults, folder, partial, key)
80
+ defaults << :"#{folder}.#{partial}.#{key}" if partial
81
+ defaults << :"#{folder}.#{action_name}.#{key}"
82
+ defaults << :"#{folder}.global.#{key}"
83
+ end
84
+
85
+ end
@@ -0,0 +1,83 @@
1
+ # encoding: UTF-8
2
+
3
+ # Defines tables to display a list of entries. The helper methods come in
4
+ # different granularities:
5
+ # * #plain_table - A basic table for the given entries and attributes using
6
+ # the Crud::TableBuilder.
7
+ # * #list_table - A sortable #plain_table for the current +entries+, with the
8
+ # given attributes or default.
9
+ # * #crud_table - A sortable #plain_table for the current +entries+, with the
10
+ # given attributes or default and the standard crud action links.
11
+ module TableHelper
12
+
13
+ # Renders a table for the given entries. One column is rendered for each
14
+ # attribute passed. If a block is given, the columns defined therein are
15
+ # appended to the attribute columns.
16
+ # If entries is empty, an appropriate message is rendered.
17
+ # An options hash may be given as the last argument.
18
+ def plain_table(entries, *attrs, &block)
19
+ options = attrs.extract_options!
20
+ add_css_class(options, 'table')
21
+ Crud::TableBuilder.table(entries, self, options) do |t|
22
+ t.attrs(*attrs)
23
+ yield t if block_given?
24
+ end
25
+ end
26
+
27
+ # Renders a #plain_table for the given entries.
28
+ # If entries is empty, an appropriate message is rendered.
29
+ def plain_table_or_message(entries, *attrs, &block)
30
+ entries.to_a # force evaluation of relations
31
+ if entries.present?
32
+ plain_table(entries, *attrs, &block)
33
+ else
34
+ content_tag(:div, ti(:no_list_entries), class: 'table')
35
+ end
36
+ end
37
+
38
+ # Create a table of the +entries+ with the default or
39
+ # the passed attributes in its columns. An options hash may be given
40
+ # as the last argument.
41
+ def list_table(*attrs, &block)
42
+ attrs, options = explode_attrs_with_options(attrs, &block)
43
+ plain_table_or_message(entries, options) do |t|
44
+ t.sortable_attrs(*attrs)
45
+ yield t if block_given?
46
+ end
47
+ end
48
+
49
+ # Create a table of the current +entries+ with the default or the passed
50
+ # attributes in its columns. Edit and destroy actions are added to each row.
51
+ # If attrs are present, the first column will link to the show
52
+ # action. Edit and destroy actions are appended to the end of each row.
53
+ # If a block is given, the column defined there will be inserted
54
+ # between the given attributes and the actions.
55
+ # An options hash for the table builder may be given as the last argument.
56
+ def crud_table(*attrs, &block)
57
+ attrs, options = explode_attrs_with_options(attrs, &block)
58
+ first = attrs.shift
59
+ plain_table_or_message(entries, options) do |t|
60
+ t.attr_with_show_link(first) if first
61
+ t.sortable_attrs(*attrs)
62
+ yield t if block_given?
63
+ standard_table_actions(t)
64
+ end
65
+ end
66
+
67
+ # Adds standard action link columns (edit, destroy) to the given table.
68
+ def standard_table_actions(table)
69
+ table.edit_action_col
70
+ table.destroy_action_col
71
+ end
72
+
73
+ private
74
+
75
+ def explode_attrs_with_options(attrs, &block)
76
+ options = attrs.extract_options!
77
+ if !block_given? && attrs.blank?
78
+ attrs = default_crud_attrs
79
+ end
80
+ [attrs, options]
81
+ end
82
+
83
+ end
@@ -0,0 +1,84 @@
1
+ # encoding: UTF-8
2
+
3
+ # View helpers for basic functions used in various other helpers.
4
+ module UtilityHelper
5
+
6
+ EMPTY_STRING = '&nbsp;'.html_safe # non-breaking space asserts better css.
7
+
8
+ # Render a content tag with the collected contents rendered
9
+ # by &block for each item in collection.
10
+ def content_tag_nested(tag, collection, options = {}, &block)
11
+ content_tag(tag, safe_join(collection, &block), options)
12
+ end
13
+
14
+ # Overridden method that takes a block that is executed for each item in
15
+ # array before appending the results.
16
+ def safe_join(array, sep = $OUTPUT_FIELD_SEPARATOR, &block)
17
+ super(block_given? ? array.map(&block) : array, sep)
18
+ end
19
+
20
+ # Returns the css class for the given flash level.
21
+ def flash_class(level)
22
+ case level
23
+ when :notice then 'success'
24
+ when :alert then 'error'
25
+ else level.to_s
26
+ end
27
+ end
28
+
29
+ # Adds a class to the given options, even if there are already classes.
30
+ def add_css_class(options, classes)
31
+ if options[:class]
32
+ options[:class] += ' ' + classes if classes
33
+ else
34
+ options[:class] = classes
35
+ end
36
+ end
37
+
38
+ # The default attributes to use in attrs, list and form partials.
39
+ # These are all defined attributes except certain special ones like
40
+ # 'id' or 'position'.
41
+ def default_crud_attrs
42
+ attrs = model_class.column_names.map(&:to_sym)
43
+ attrs - [:id, :position, :password]
44
+ end
45
+
46
+ # Returns the ActiveRecord column type or nil.
47
+ def column_type(obj, attr)
48
+ column_property(obj, attr, :type)
49
+ end
50
+
51
+ # Returns an ActiveRecord column property for the passed attr or nil
52
+ def column_property(obj, attr, property)
53
+ if obj.respond_to?(:column_for_attribute)
54
+ column = obj.column_for_attribute(attr)
55
+ column.try(property)
56
+ end
57
+ end
58
+
59
+ # Returns the association proxy for the given attribute. The attr parameter
60
+ # may be the _id column or the association name. If a macro (e.g.
61
+ # :belongs_to) is given, the association must be of this type, otherwise,
62
+ # any association is returned. Returns nil if no association (or not of the
63
+ # given macro) was found.
64
+ def association(obj, attr, *macros)
65
+ if obj.class.respond_to?(:reflect_on_association)
66
+ name = assoc_and_id_attr(attr).first.to_sym
67
+ assoc = obj.class.reflect_on_association(name)
68
+ assoc if assoc && (macros.blank? || macros.include?(assoc.macro))
69
+ end
70
+ end
71
+
72
+ # Returns the name of the attr and it's corresponding field
73
+ def assoc_and_id_attr(attr)
74
+ attr = attr.to_s
75
+ if attr.end_with?('_id')
76
+ [attr[0..-4], attr]
77
+ elsif attr.end_with?('_ids')
78
+ [attr[0..-5].pluralize, attr]
79
+ else
80
+ [attr, "#{attr}_id"]
81
+ end
82
+ end
83
+
84
+ end