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.
- data/README.rdoc +60 -27
- data/Rakefile +3 -1
- data/VERSION +1 -1
- data/lib/generators/dry_crud/dry_crud_generator.rb +3 -3
- data/lib/generators/dry_crud/templates/INSTALL +3 -1
- data/lib/generators/dry_crud/templates/app/controllers/crud_controller.rb +106 -90
- data/lib/generators/dry_crud/templates/app/controllers/list_controller.rb +90 -74
- data/lib/generators/dry_crud/templates/app/controllers/render_inheritable.rb +34 -33
- data/lib/generators/dry_crud/templates/app/helpers/crud_helper.rb +39 -23
- data/lib/generators/dry_crud/templates/app/helpers/list_helper.rb +11 -9
- data/lib/generators/dry_crud/templates/app/helpers/standard_form_builder.rb +55 -47
- data/lib/generators/dry_crud/templates/app/helpers/standard_helper.rb +134 -86
- data/lib/generators/dry_crud/templates/app/helpers/standard_table_builder.rb +41 -35
- data/lib/generators/dry_crud/templates/app/views/crud/_actions_edit.html.erb +1 -0
- data/lib/generators/dry_crud/templates/app/views/crud/edit.html.erb +3 -3
- data/lib/generators/dry_crud/templates/app/views/crud/new.html.erb +2 -2
- data/lib/generators/dry_crud/templates/app/views/crud/show.html.erb +3 -3
- data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.erb +9 -7
- data/lib/generators/dry_crud/templates/app/views/list/_search.html.erb +1 -1
- data/lib/generators/dry_crud/templates/app/views/list/index.html.erb +4 -4
- data/lib/generators/dry_crud/templates/app/views/shared/_error_messages.html.erb +3 -1
- data/lib/generators/dry_crud/templates/config/locales/en_crud.yml +63 -0
- data/lib/generators/dry_crud/templates/test/crud_test_model.rb +93 -58
- data/lib/generators/dry_crud/templates/test/custom_assertions.rb +24 -13
- data/lib/generators/dry_crud/templates/test/functional/crud_controller_test_helper.rb +26 -56
- data/lib/generators/dry_crud/templates/test/functional/crud_test_models_controller_test.rb +47 -41
- data/lib/generators/dry_crud/templates/test/unit/custom_assertions_test.rb +28 -24
- data/lib/generators/dry_crud/templates/test/unit/helpers/crud_helper_test.rb +20 -34
- data/lib/generators/dry_crud/templates/test/unit/helpers/list_helper_test.rb +39 -53
- data/lib/generators/dry_crud/templates/test/unit/helpers/render_inheritable_test.rb +33 -33
- data/lib/generators/dry_crud/templates/test/unit/helpers/standard_form_builder_test.rb +27 -27
- data/lib/generators/dry_crud/templates/test/unit/helpers/standard_helper_test.rb +103 -50
- data/lib/generators/dry_crud/templates/test/unit/helpers/standard_table_builder_test.rb +52 -24
- data/test/templates/Gemfile +34 -0
- data/test/templates/app/controllers/ajax_controller.rb +3 -3
- data/test/templates/app/controllers/application_controller.rb +1 -1
- data/test/templates/app/controllers/cities_controller.rb +2 -5
- data/test/templates/app/controllers/people_controller.rb +5 -5
- data/test/templates/app/controllers/vips_controller.rb +6 -11
- data/test/templates/app/helpers/people_helper.rb +2 -2
- data/test/templates/app/models/city.rb +9 -9
- data/test/templates/app/models/person.rb +5 -4
- data/test/templates/app/views/ajax/_actions_index.html.erb +2 -2
- data/test/templates/app/views/cities/_form.html.erb +5 -1
- data/test/templates/app/views/layouts/_menu.html.erb +3 -3
- data/test/templates/app/views/people/_attrs.html.erb +3 -3
- data/test/templates/config/database.yml +22 -0
- data/test/templates/config/locales/en_cities.yml +56 -0
- data/test/templates/config/routes.rb +5 -5
- data/test/templates/db/migrate/20100511174904_create_people_and_cities.rb +5 -2
- data/test/templates/db/seeds.rb +38 -29
- data/test/templates/test/functional/cities_controller_test.rb +12 -12
- data/test/templates/test/functional/people_controller_test.rb +10 -10
- 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
|
10
|
-
attrs = default_attrs - [:created_at, :updated_at]
|
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
|
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 =>
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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, :
|
119
|
+
collection_select(attr, list, :id, :to_s, select_options(attr), html_options)
|
111
120
|
else
|
112
|
-
|
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.
|
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 = " ".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
|
24
|
-
when Date then value
|
25
|
-
when Time then value
|
26
|
-
when true then
|
27
|
-
when false then
|
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
|
-
|
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
|
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,
|
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
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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("
|
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("
|
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
|
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
|
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
|
145
|
-
:confirm =>
|
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
|
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
|
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
|
-
|
174
|
-
|
175
|
-
#
|
176
|
-
|
177
|
-
#
|
178
|
-
|
179
|
-
|
180
|
-
|
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
|
-
|
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
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|