dry_crud 1.2.7 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. data/README.rdoc +60 -27
  2. data/Rakefile +3 -1
  3. data/VERSION +1 -1
  4. data/lib/generators/dry_crud/dry_crud_generator.rb +3 -3
  5. data/lib/generators/dry_crud/templates/INSTALL +3 -1
  6. data/lib/generators/dry_crud/templates/app/controllers/crud_controller.rb +106 -90
  7. data/lib/generators/dry_crud/templates/app/controllers/list_controller.rb +90 -74
  8. data/lib/generators/dry_crud/templates/app/controllers/render_inheritable.rb +34 -33
  9. data/lib/generators/dry_crud/templates/app/helpers/crud_helper.rb +39 -23
  10. data/lib/generators/dry_crud/templates/app/helpers/list_helper.rb +11 -9
  11. data/lib/generators/dry_crud/templates/app/helpers/standard_form_builder.rb +55 -47
  12. data/lib/generators/dry_crud/templates/app/helpers/standard_helper.rb +134 -86
  13. data/lib/generators/dry_crud/templates/app/helpers/standard_table_builder.rb +41 -35
  14. data/lib/generators/dry_crud/templates/app/views/crud/_actions_edit.html.erb +1 -0
  15. data/lib/generators/dry_crud/templates/app/views/crud/edit.html.erb +3 -3
  16. data/lib/generators/dry_crud/templates/app/views/crud/new.html.erb +2 -2
  17. data/lib/generators/dry_crud/templates/app/views/crud/show.html.erb +3 -3
  18. data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.erb +9 -7
  19. data/lib/generators/dry_crud/templates/app/views/list/_search.html.erb +1 -1
  20. data/lib/generators/dry_crud/templates/app/views/list/index.html.erb +4 -4
  21. data/lib/generators/dry_crud/templates/app/views/shared/_error_messages.html.erb +3 -1
  22. data/lib/generators/dry_crud/templates/config/locales/en_crud.yml +63 -0
  23. data/lib/generators/dry_crud/templates/test/crud_test_model.rb +93 -58
  24. data/lib/generators/dry_crud/templates/test/custom_assertions.rb +24 -13
  25. data/lib/generators/dry_crud/templates/test/functional/crud_controller_test_helper.rb +26 -56
  26. data/lib/generators/dry_crud/templates/test/functional/crud_test_models_controller_test.rb +47 -41
  27. data/lib/generators/dry_crud/templates/test/unit/custom_assertions_test.rb +28 -24
  28. data/lib/generators/dry_crud/templates/test/unit/helpers/crud_helper_test.rb +20 -34
  29. data/lib/generators/dry_crud/templates/test/unit/helpers/list_helper_test.rb +39 -53
  30. data/lib/generators/dry_crud/templates/test/unit/helpers/render_inheritable_test.rb +33 -33
  31. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_form_builder_test.rb +27 -27
  32. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_helper_test.rb +103 -50
  33. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_table_builder_test.rb +52 -24
  34. data/test/templates/Gemfile +34 -0
  35. data/test/templates/app/controllers/ajax_controller.rb +3 -3
  36. data/test/templates/app/controllers/application_controller.rb +1 -1
  37. data/test/templates/app/controllers/cities_controller.rb +2 -5
  38. data/test/templates/app/controllers/people_controller.rb +5 -5
  39. data/test/templates/app/controllers/vips_controller.rb +6 -11
  40. data/test/templates/app/helpers/people_helper.rb +2 -2
  41. data/test/templates/app/models/city.rb +9 -9
  42. data/test/templates/app/models/person.rb +5 -4
  43. data/test/templates/app/views/ajax/_actions_index.html.erb +2 -2
  44. data/test/templates/app/views/cities/_form.html.erb +5 -1
  45. data/test/templates/app/views/layouts/_menu.html.erb +3 -3
  46. data/test/templates/app/views/people/_attrs.html.erb +3 -3
  47. data/test/templates/config/database.yml +22 -0
  48. data/test/templates/config/locales/en_cities.yml +56 -0
  49. data/test/templates/config/routes.rb +5 -5
  50. data/test/templates/db/migrate/20100511174904_create_people_and_cities.rb +5 -2
  51. data/test/templates/db/seeds.rb +38 -29
  52. data/test/templates/test/functional/cities_controller_test.rb +12 -12
  53. data/test/templates/test/functional/people_controller_test.rb +10 -10
  54. metadata +11 -7
@@ -1,56 +1,72 @@
1
- # Extension of StandardHelper functionality to provide a set of default
1
+ # Extension of StandardHelper functionality to provide a set of default
2
2
  # attributes for the current model to be used in tables and forms. This helper
3
3
  # is included in CrudController.
4
4
  module CrudHelper
5
5
 
6
- # Renders a generic form for the current entry with :default_attrs or the
7
- # given attribute array, using the StandardFormBuilder.
6
+ # Renders a generic form for the current entry with :default_attrs or the
7
+ # given attribute array, using the StandardFormBuilder. An options hash
8
+ # may be given as the last argument.
8
9
  # If a block is given, a custom form may be rendered and attrs is ignored.
9
- def crud_form(attrs = nil, options = {}, &block)
10
- attrs = default_attrs - [:created_at, :updated_at] unless attrs
11
- standard_form(@entry, attrs, &block)
10
+ def crud_form(*attrs, &block)
11
+ attrs = attrs_or_default(attrs) { default_attrs - [:created_at, :updated_at] }
12
+ standard_form(@entry, *attrs, &block)
12
13
  end
13
-
14
- # Create a table of the @entries variable with the default or
15
- # the passed attributes in its columns.
14
+
15
+ # Create a table of the @entries variable with the default or
16
+ # the passed attributes in its columns. An options hash may be given
17
+ # as the last argument.
16
18
  def crud_table(*attrs, &block)
17
19
  if block_given?
18
20
  list_table(*attrs, &block)
19
- else
20
- attrs = default_attrs if attrs.blank?
21
- list_table(*attrs) do |t|
21
+ else
22
+ attrs = attrs_or_default(attrs) { default_attrs }
23
+ list_table(*attrs) do |t|
22
24
  add_table_actions(t)
23
25
  end
24
26
  end
25
27
  end
26
-
28
+
27
29
  # Adds a set of standard action link column (show, edit, destroy) to the given table.
28
30
  def add_table_actions(table)
29
31
  action_col(table) { |e| link_table_action_show(e) }
30
32
  action_col(table) { |e| link_table_action_edit(e) }
31
33
  action_col(table) { |e| link_table_action_destroy(e) }
32
34
  end
33
-
35
+
36
+ # Action link to show inside a table.
34
37
  def link_table_action_show(record)
35
38
  link_table_action('show', record)
36
39
  end
37
-
40
+
41
+ # Action link to edit inside a table.
38
42
  def link_table_action_edit(record)
39
- link_table_action('edit', edit_polymorphic_path(record))
43
+ link_table_action('edit', edit_polymorphic_path(record))
40
44
  end
41
-
45
+
46
+ # Action link to destroy inside a table.
42
47
  def link_table_action_destroy(record)
43
- link_table_action('delete', record,
44
- :confirm => StandardHelper::CONFIRM_DELETE_MESSAGE,
45
- :method => :delete)
48
+ link_table_action('delete', record,
49
+ :confirm => ti(:confirm_delete),
50
+ :method => :delete)
46
51
  end
47
-
52
+
53
+ # Generic action link inside a table.
48
54
  def link_table_action(image, url, html_options = {})
49
- link_to(action_icon(image), url, html_options)
55
+ link_to(action_icon(image), url, html_options)
50
56
  end
51
-
57
+
58
+ # Defines a column with an action link.
52
59
  def action_col(table, &block)
53
60
  table.col('', :class => 'center', &block)
54
61
  end
55
62
 
63
+ private
64
+
65
+ # Returns default attrs for a crud table if no others are passed.
66
+ def attrs_or_default(attrs)
67
+ options = attrs.extract_options!
68
+ attrs = yield if attrs.blank?
69
+ attrs << options
70
+ end
71
+
56
72
  end
@@ -1,24 +1,26 @@
1
- # Extension of StandardHelper functionality to provide a set of default
1
+ # Extension of StandardHelper functionality to provide a set of default
2
2
  # attributes for the current model to be used in tables and forms. This helper
3
3
  # is included in CrudController.
4
4
  module ListHelper
5
-
6
- # Create a table of the @entries variable with the default or
7
- # the passed attributes in its columns.
5
+
6
+ # Create a table of the @entries variable with the default or
7
+ # the passed attributes in its columns. An options hash may be given
8
+ # as the last argument.
8
9
  def list_table(*attrs, &block)
10
+ options = attrs.extract_options!
9
11
  # only use default attrs if no attrs and no block are given
10
12
  attributes = (block_given? || attrs.present?) ? attrs : default_attrs
11
- table(@entries) do |t|
12
- t.sortable_attrs(*attributes)
13
- yield t if block_given?
13
+ table(@entries, options) do |t|
14
+ t.sortable_attrs(*attributes)
15
+ yield t if block_given?
14
16
  end
15
17
  end
16
-
18
+
17
19
  # The default attributes to use in attrs, list and form partials.
18
20
  # These are all defined attributes except certain special ones like 'id' or 'position'.
19
21
  def default_attrs
20
22
  attrs = model_class.column_names.collect(&:to_sym)
21
23
  attrs - [:id, :position, :password]
22
24
  end
23
-
25
+
24
26
  end
@@ -1,23 +1,22 @@
1
1
  # A form builder that automatically selects the corresponding input field
2
2
  # for ActiveRecord column types. Convenience methods for each column type allow
3
- # one to customize the different fields.
3
+ # one to customize the different fields.
4
4
  # All field methods may be prefixed with 'labeled_' in order to render
5
5
  # a standard label with them.
6
6
  class StandardFormBuilder < ActionView::Helpers::FormBuilder
7
-
8
- BLANK_SELECT_LABEL = 'Please select'
9
- REQUIRED_MARK = '<span class="required">*</span>'.html_safe
10
-
11
- attr_reader :template
12
-
13
- delegate :association, :column_type, :column_property, :captionize,
7
+
8
+ REQUIRED_MARK = '<span class="required">*</span>'.html_safe
9
+
10
+ attr_reader :template
11
+
12
+ delegate :association, :column_type, :column_property, :captionize, :ta,
14
13
  :to => :template
15
-
14
+
16
15
  # Render multiple input fields together with a label for the given attributes.
17
16
  def labeled_input_fields(*attrs)
18
17
  attrs.collect {|a| labeled_input_field(a) }.join("\n").html_safe
19
18
  end
20
-
19
+
21
20
  # Render a standartized label.
22
21
  def label(attr, text = nil, options = {})
23
22
  if attr.is_a?(Symbol) && text.nil? && options.blank?
@@ -26,7 +25,7 @@ class StandardFormBuilder < ActionView::Helpers::FormBuilder
26
25
  super(attr, text, options)
27
26
  end
28
27
  end
29
-
28
+
30
29
  # Render a corresponding input field for the given attribute.
31
30
  # The input field is chosen based on the ActiveRecord column type.
32
31
  # Use additional html_options for the input element.
@@ -47,58 +46,68 @@ class StandardFormBuilder < ActionView::Helpers::FormBuilder
47
46
  end
48
47
  end
49
48
  end
50
-
49
+
51
50
  # Render a standard text field.
52
51
  def text_field(attr, html_options = {})
53
52
  super(attr, {:size => 30}.merge(html_options))
54
53
  end
55
-
54
+
56
55
  # Render a standard password field.
57
56
  def password_field(attr, html_options = {})
58
57
  super(attr, {:size => 30}.merge(html_options))
59
58
  end
60
-
59
+
61
60
  # Render a standard text area.
62
61
  def text_area(attr, html_options = {})
63
62
  super(attr, {:rows => 5, :cols => 30}.merge(html_options))
64
63
  end
65
-
64
+
66
65
  # Render a standard string field with column contraints.
67
66
  def string_field(attr, html_options = {})
68
67
  limit = column_property(@object, attr, :limit)
69
68
  html_options = {:maxlength => limit}.merge(html_options) if limit
70
69
  text_field(attr, html_options)
71
70
  end
72
-
71
+
73
72
  # Render a standard number field.
74
73
  def number_field(attr, html_options = {})
75
74
  super(attr, {:size => 15}.merge(html_options))
76
75
  end
77
-
76
+
78
77
  # Render an integer field.
79
78
  def integer_field(attr, html_options = {})
80
79
  number_field(attr, html_options)
81
80
  end
82
-
81
+
83
82
  # Render a float field.
84
83
  def float_field(attr, html_options = {})
85
84
  number_field(attr, html_options)
86
- end
87
-
85
+ end
86
+
88
87
  # Render a decimal field.
89
88
  def decimal_field(attr, html_options = {})
90
89
  number_field(attr, html_options)
91
90
  end
92
-
91
+
93
92
  # Render a boolean field.
94
93
  def boolean_field(attr, html_options = {})
95
94
  check_box(attr, html_options)
96
95
  end
97
-
96
+
98
97
  # Render a field to select a date. You might want to customize this.
99
98
  def date_field(attr, html_options = {})
100
99
  date_select(attr, {}, html_options)
101
100
  end
101
+
102
+ # Render a field to enter a time. You might want to customize this.
103
+ def time_field(attr, html_options = {})
104
+ time_select(attr, {}, html_options)
105
+ end
106
+
107
+ # Render a field to enter a date and time. You might want to customize this.
108
+ def datetime_field(attr, html_options = {})
109
+ datetime_select(attr, {}, html_options)
110
+ end
102
111
 
103
112
  # Render a select element for a :belongs_to association defined by attr.
104
113
  # Use additional html_options for the select element.
@@ -107,38 +116,45 @@ class StandardFormBuilder < ActionView::Helpers::FormBuilder
107
116
  def belongs_to_field(attr, html_options = {})
108
117
  list = association_entries(attr, html_options)
109
118
  if list.present?
110
- collection_select(attr, list, :id, :label, select_options(attr), html_options)
119
+ collection_select(attr, list, :id, :to_s, select_options(attr), html_options)
111
120
  else
112
- '(none available)'
121
+ ta(:none_available, association(@object, attr))
113
122
  end
114
123
  end
115
-
124
+
116
125
  # Renders a marker if the given attr has to be present.
117
126
  def required_mark(attr)
118
127
  required?(attr) ? REQUIRED_MARK : ''
119
128
  end
120
-
129
+
121
130
  # Render a label for the given attribute with the passed field html section.
122
131
  def labeled(attr, field_html = nil, &block)
123
132
  template.labeled(label(attr), field_html, &block)
124
133
  end
134
+
135
+ # Depending if the given attribute must be present, return
136
+ # only an initial selection prompt or a blank option, respectively.
137
+ def select_options(attr)
138
+ assoc = association(@object, attr)
139
+ required?(attr) ? { :prompt => ta(:please_select, assoc) } :
140
+ { :include_blank => ta(:no_entry, assoc) }
141
+ end
125
142
 
126
- # Dispatch methods starting with 'labeled_' to render a label and the corresponding
143
+ # Dispatch methods starting with 'labeled_' to render a label and the corresponding
127
144
  # input field. E.g. labeled_boolean_field(:checked, {:class => 'bold'})
128
145
  def method_missing(name, *args)
129
146
  if field_method = labeled_field_method?(name)
130
147
  labeled(args.first, send(field_method, *args) + required_mark(args.first))
131
- else
148
+ else
132
149
  super(name, *args)
133
150
  end
134
151
  end
135
-
152
+
136
153
  def respond_to?(name)
137
154
  labeled_field_method?(name).present? || super(name)
138
155
  end
139
-
140
156
  protected
141
-
157
+
142
158
  # Returns true if attr is a non-polymorphic belongs_to association,
143
159
  # for which an input field may be automatically rendered.
144
160
  def belongs_to_association?(attr, type)
@@ -149,41 +165,33 @@ class StandardFormBuilder < ActionView::Helpers::FormBuilder
149
165
  false
150
166
  end
151
167
  end
152
-
168
+
153
169
  # Returns the list of association entries, either from options[:list],
154
170
  # the instance variable with the pluralized association name or all
155
171
  # entries of the association klass.
156
172
  def association_entries(attr, options)
157
- list = options.delete(:list)
173
+ list = options.delete(:list)
158
174
  unless list
159
175
  assoc = association(@object, attr)
160
176
  list = @template.send(:instance_variable_get, :"@#{assoc.name.to_s.pluralize}")
161
177
  unless list
162
- list = assoc.klass.all(:conditions => assoc.options[:conditions],
163
- :order => assoc.options[:order])
178
+ list = assoc.klass.where(assoc.options[:conditions]).order(assoc.options[:order])
164
179
  end
165
180
  end
166
181
  list
167
182
  end
168
-
183
+
169
184
  # Returns true if the given attribute must be present.
170
185
  def required?(attr)
171
186
  attr = attr.to_s
172
187
  attr, attr_id = attr.end_with?('_id') ? [attr[0..-4], attr] : [attr, "#{attr}_id"]
173
- validators = @object.class.validators_on(attr) +
188
+ validators = @object.class.validators_on(attr) +
174
189
  @object.class.validators_on(attr_id)
175
190
  validators.any? {|v| v.kind == :presence }
176
191
  end
177
-
178
- # Depending if the given attribute must be present, return
179
- # only an initial selection prompt or a blank option, respectively.
180
- def select_options(attr)
181
- required?(attr) ? { :prompt => BLANK_SELECT_LABEL } :
182
- { :include_blank => StandardHelper::NO_ENTRY }
183
- end
184
-
192
+
185
193
  private
186
-
194
+
187
195
  def labeled_field_method?(name)
188
196
  prefix = 'labeled_'
189
197
  if name.to_s.start_with?(prefix)
@@ -191,5 +199,5 @@ class StandardFormBuilder < ActionView::Helpers::FormBuilder
191
199
  field_method if respond_to?(field_method)
192
200
  end
193
201
  end
194
-
202
+
195
203
  end
@@ -1,36 +1,29 @@
1
- # A view helper to standartize often used functions like formatting,
2
- # tables, forms or action links. This helper is ideally defined in the
1
+ # A view helper to standartize often used functions like formatting,
2
+ # tables, forms or action links. This helper is ideally defined in the
3
3
  # ApplicationController.
4
4
  module StandardHelper
5
-
6
- NO_LIST_ENTRIES_MESSAGE = "No entries found"
7
- NO_ENTRY = '(none)'
8
- CONFIRM_DELETE_MESSAGE = 'Do you really want to delete this entry?'
9
-
10
- FLOAT_FORMAT = "%.2f"
11
- TIME_FORMAT = "%H:%M"
5
+
12
6
  EMPTY_STRING = "&nbsp;".html_safe # non-breaking space asserts better css styling.
13
-
7
+
14
8
  ################ FORMATTING HELPERS ##################################
15
9
 
16
10
  # Define an array of associations symbols in your helper that should not get automatically linked.
17
11
  #def no_assoc_links = [:city]
18
-
12
+
19
13
  # Formats a single value
20
14
  def f(value)
21
15
  case value
22
16
  when Fixnum then number_with_delimiter(value)
23
- when Float then FLOAT_FORMAT % value
24
- when Date then value.to_s
25
- when Time then value.strftime(TIME_FORMAT)
26
- when true then 'yes'
27
- when false then 'no'
17
+ when Float then number_with_precision(value, :precision => 2)
18
+ when Date then l(value)
19
+ when Time then l(value, :format => :time)
20
+ when true then t(:"global.yes")
21
+ when false then t(:"global.no")
28
22
  when nil then EMPTY_STRING
29
- else
30
- value.respond_to?(:label) ? value.label : value.to_s
23
+ else value.to_s
31
24
  end
32
25
  end
33
-
26
+
34
27
  # Formats an arbitrary attribute of the given ActiveRecord object.
35
28
  # If no specific format_{attr} method is found, formats the value as follows:
36
29
  # If the value is an associated model, renders the label of this object.
@@ -45,150 +38,190 @@ module StandardHelper
45
38
  format_type(obj, attr)
46
39
  end
47
40
  end
48
-
49
-
41
+
42
+
50
43
  ############## STANDARD HTML SECTIONS ############################
51
-
52
-
44
+
45
+
53
46
  # Renders an arbitrary content with the given label. Used for uniform presentation.
54
47
  def labeled(label, content = nil, &block)
55
48
  content = capture(&block) if block_given?
56
- render(:partial => 'shared/labeled',
57
- :locals => { :label => label, :content => content})
49
+ render 'shared/labeled', :label => label, :content => content
58
50
  end
59
-
51
+
60
52
  # Transform the given text into a form as used by labels or table headers.
61
53
  def captionize(text, clazz = nil)
62
54
  if clazz.respond_to?(:human_attribute_name)
63
55
  clazz.human_attribute_name(text)
64
56
  else
65
- text.to_s.humanize.titleize
57
+ text.to_s.humanize.titleize
66
58
  end
67
59
  end
68
-
69
- # Renders a list of attributes with label and value for a given object.
60
+
61
+ # Renders a list of attributes with label and value for a given object.
70
62
  # Optionally surrounded with a div.
71
63
  def render_attrs(obj, *attrs)
72
- attrs.collect do |a|
64
+ attrs.collect do |a|
73
65
  labeled_attr(obj, a)
74
66
  end.join("\n").html_safe
75
67
  end
76
-
68
+
77
69
  # Renders the formatted content of the given attribute with a label.
78
70
  def labeled_attr(obj, attr)
79
71
  labeled(captionize(attr, obj.class), format_attr(obj, attr))
80
72
  end
81
-
82
- # Renders a table for the given entries. One column is rendered for each attribute passed.
73
+
74
+ # Renders a table for the given entries. One column is rendered for each attribute passed.
83
75
  # If a block is given, the columns defined therein are appended to the attribute columns.
84
76
  # If entries is empty, an appropriate message is rendered.
77
+ # An options hash may be given as the last argument.
85
78
  def table(entries, *attrs, &block)
86
79
  if entries.present?
87
- StandardTableBuilder.table(entries, self) do |t|
80
+ StandardTableBuilder.table(entries, self, attrs.extract_options!) do |t|
88
81
  t.attrs(*attrs)
89
82
  yield t if block_given?
90
83
  end
91
84
  else
92
- content_tag(:div, NO_LIST_ENTRIES_MESSAGE, :class => 'list')
85
+ content_tag(:div, ti(:no_list_entries), :class => 'list')
93
86
  end
94
87
  end
95
-
88
+
96
89
  # Renders a generic form for all given attributes using StandardFormBuilder.
97
90
  # Before the input fields, the error messages are rendered, if present.
98
91
  # The form is rendered with a basic save button.
99
92
  # If a block is given, custom input fields may be rendered and attrs is ignored.
100
- def standard_form(object, attrs = [], options = {}, &block)
101
- form_for(object, {:builder => StandardFormBuilder}.merge(options)) do |form|
102
- content = render(:partial => 'shared/error_messages',
103
- :locals => {:errors => object.errors})
104
-
105
- content << if block_given?
106
- capture(form, &block)
93
+ # An options hash may be given as the last argument.
94
+ def standard_form(object, *attrs, &block)
95
+ form_for(object, {:builder => StandardFormBuilder}.merge(attrs.extract_options!)) do |form|
96
+ content = render('shared/error_messages', :errors => object.errors, :object => object)
97
+
98
+ content << if block_given?
99
+ capture(form, &block)
107
100
  else
108
101
  form.labeled_input_fields(*attrs)
109
102
  end
110
-
111
- content << labeled(nil, form.submit("Save") + cancel_link(object))
103
+
104
+ content << labeled(nil, form.submit(ti(:"button.save")) + cancel_link(object))
112
105
  content.html_safe
113
106
  end
114
107
  end
115
-
108
+
116
109
  def cancel_link(object)
117
- link_to("Cancel", polymorphic_path(object), :class => 'cancel')
110
+ link_to(ti(:"button.cancel"), polymorphic_path(object), :class => 'cancel')
118
111
  end
119
-
112
+
120
113
  # Alternate table row
121
114
  def tr_alt(cycle_name = 'row_class', &block)
122
115
  content_tag(:tr, :class => cycle("even", "odd", :name => cycle_name), &block)
123
116
  end
124
117
 
118
+ # Renders a div with clear:both style.
125
119
  def clear
126
120
  content_tag(:div, '', :class => 'clear')
127
121
  end
128
-
129
-
122
+
123
+
130
124
  ######## ACTION LINKS ###################################################### :nodoc:
131
-
125
+
132
126
  # Standard link action to the show page of a given record.
133
127
  def link_action_show(record)
134
- link_action 'Show', 'show', record
128
+ link_action ti(:"link.show"), 'show', record
135
129
  end
136
-
130
+
137
131
  # Standard link action to the edit page of a given record.
138
132
  def link_action_edit(record)
139
- link_action 'Edit', 'edit', edit_polymorphic_path(record)
133
+ link_action ti(:"link.edit"), 'edit', edit_polymorphic_path(record)
140
134
  end
141
-
135
+
142
136
  # Standard link action to the destroy action of a given record.
143
137
  def link_action_destroy(record)
144
- link_action 'Delete', 'delete', record,
145
- :confirm => CONFIRM_DELETE_MESSAGE,
138
+ link_action ti(:"link.delete"), 'delete', record,
139
+ :confirm => ti(:confirm_delete),
146
140
  :method => :delete
147
141
  end
148
-
142
+
149
143
  # Standard link action to the list page.
150
144
  def link_action_index(url_options = {:action => 'index', :returning => true})
151
- link_action 'List', 'list', url_options
145
+ link_action ti(:"link.list"), 'list', url_options
152
146
  end
153
-
147
+
154
148
  # Standard link action to the new page.
155
149
  def link_action_add(url_options = {:action => 'new'})
156
- link_action 'Add', 'add', url_options
150
+ link_action ti(:"link.add"), 'add', url_options
157
151
  end
158
-
152
+
159
153
  # A generic helper method to create action links.
160
154
  # These link could be styled to look like buttons, for example.
161
155
  def link_action(label, icon = nil, url = {}, html_options = {})
162
- link_to(icon ? action_icon(icon, label) : label,
163
- url,
156
+ link_to(icon ? action_icon(icon, label) : label,
157
+ url,
164
158
  {:class => 'action'}.merge(html_options))
165
159
  end
166
-
160
+
161
+ # Outputs an icon for an action with an optional label.
167
162
  def action_icon(icon, label = nil)
168
- html = image_tag("actions/#{icon}.png", :size => '16x16')
163
+ html = image_tag("actions/#{icon}.png", :size => '16x16')
169
164
  html << ' ' << label if label
170
165
  html
171
166
  end
172
-
173
- protected
174
-
175
- # Helper methods that are not directly called from templates.
176
-
177
- # Formats an active record association
178
- def format_assoc(obj, assoc)
179
- if assoc_val = obj.send(assoc.name)
180
- link_to_unless(no_assoc_link?(assoc, assoc_val), assoc_val.label, assoc_val)
167
+
168
+ # Translates the passed key by looking it up over the template lookup path
169
+ # (i.e., usually the controller hierarchy). The key is searched in the following
170
+ # order:
171
+ # - {controller}.{current_partial}.{key}
172
+ # - {controller}.{current_action}.{key}
173
+ # - {controller}.global.{key}
174
+ # - {parent_controller}.{current_partial}.{key}
175
+ # - {parent_controller}.{current_action}.{key}
176
+ # - {parent_controller}.global.{key}
177
+ # - ...
178
+ # - global.{key}
179
+ def translate_inheritable(key, variables = {})
180
+ defaults = []
181
+ if controller.class.respond_to?(:template_lookup_path)
182
+ partial = @_virtual_path ? @_virtual_path.gsub(%r{.*/_?}, "") : nil
183
+ controller.class.template_lookup_path.each do |folder|
184
+ defaults << :"#{folder}.#{partial}.#{key}" if partial
185
+ defaults << :"#{folder}.#{action_name}.#{key}"
186
+ defaults << :"#{folder}.global.#{key}"
187
+ end
181
188
  else
182
- NO_ENTRY
189
+ defaults << :"#{controller_name}.#{action_name}.#{key}"
190
+ defaults << :"#{controller_name}.global.#{key}"
183
191
  end
192
+ defaults << :"global.#{key}"
193
+
194
+ variables[:default] ||= defaults
195
+ t(defaults.shift, variables)
184
196
  end
185
197
 
186
- # Returns true if no link should be created when formatting the given association.
187
- def no_assoc_link?(assoc, val)
188
- (respond_to?(:no_assoc_links) && no_assoc_links.to_a.include?(assoc.name.to_sym)) ||
189
- !respond_to?("#{val.class.name.underscore}_path".to_sym)
198
+ alias_method :ti, :translate_inheritable
199
+
200
+ # Translates the passed key for an active record association. This helper is used
201
+ # for rendering association dependent keys in forms like :no_entry, :none_available or
202
+ # :please_select.
203
+ # The key is looked up in the following order:
204
+ # - activerecord.associations.models.{model_name}.{association_name}.{key}
205
+ # - activerecord.associations.{association_model_name}.{key}
206
+ # - global.associations.{key}
207
+ def translate_association(key, assoc = nil, variables = {})
208
+ primary = if assoc
209
+ variables[:default] ||= [:"activerecord.associations.#{assoc.klass.name.underscore}.#{key}",
210
+ :"global.associations.#{key}"]
211
+ :"activerecord.associations.models.#{assoc.active_record.name.underscore}.#{assoc.name}.#{key}"
212
+ else
213
+ :"global.associations.#{key}"
214
+ end
215
+ t(primary, variables)
190
216
  end
191
217
 
218
+ alias_method :ta, :translate_association
219
+
220
+
221
+ protected
222
+
223
+ # Helper methods that are not directly called from templates.
224
+
192
225
  # Formats an arbitrary attribute of the given object depending on its data type.
193
226
  # For ActiveRecords, take the defined data type into account for special types
194
227
  # that have no own object class.
@@ -204,24 +237,39 @@ module StandardHelper
204
237
  else f(val)
205
238
  end
206
239
  end
207
-
240
+
208
241
  # Returns the ActiveRecord column type or nil.
209
242
  def column_type(obj, attr)
210
243
  column_property(obj, attr, :type)
211
244
  end
212
-
245
+
213
246
  # Returns an ActiveRecord column property for the passed attr or nil
214
247
  def column_property(obj, attr, property)
215
248
  if obj.respond_to?(:column_for_attribute)
216
249
  column = obj.column_for_attribute(attr)
217
250
  column.try(property)
218
- end
251
+ end
219
252
  end
220
-
253
+
254
+ # Formats an active record association
255
+ def format_assoc(obj, assoc)
256
+ if assoc_val = obj.send(assoc.name)
257
+ link_to_unless(no_assoc_link?(assoc, assoc_val), assoc_val, assoc_val)
258
+ else
259
+ ta(:no_entry, assoc)
260
+ end
261
+ end
262
+
263
+ # Returns true if no link should be created when formatting the given association.
264
+ def no_assoc_link?(assoc, val)
265
+ (respond_to?(:no_assoc_links) && no_assoc_links.to_a.include?(assoc.name.to_sym)) ||
266
+ !respond_to?("#{val.class.name.underscore}_path".to_sym)
267
+ end
268
+
221
269
  # Returns the association proxy for the given attribute. The attr parameter
222
270
  # may be the _id column or the association name. If a macro (e.g. :belongs_to)
223
271
  # is given, the association must be of this type, otherwise, any association
224
- # is returned. Returns nil if no association (or not of the given macro) was
272
+ # is returned. Returns nil if no association (or not of the given macro) was
225
273
  # found.
226
274
  def association(obj, attr, macro = nil)
227
275
  if obj.class.respond_to?(:reflect_on_association)
@@ -230,5 +278,5 @@ module StandardHelper
230
278
  assoc if assoc && (macro.nil? || assoc.macro == macro)
231
279
  end
232
280
  end
233
-
281
+
234
282
  end