dry_crud 2.1.1 → 2.1.2

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 (37) hide show
  1. checksums.yaml +9 -9
  2. data/VERSION +1 -1
  3. data/app/assets/stylesheets/sample.scss +1 -1
  4. data/app/controllers/crud_controller.rb +1 -1
  5. data/app/controllers/dry_crud/generic_model.rb +45 -45
  6. data/app/controllers/dry_crud/nestable.rb +1 -1
  7. data/app/controllers/dry_crud/render_callbacks.rb +2 -0
  8. data/app/controllers/dry_crud/responder.rb +3 -0
  9. data/app/controllers/list_controller.rb +1 -1
  10. data/app/helpers/dry_crud/form/builder.rb +286 -261
  11. data/app/helpers/dry_crud/form/control.rb +156 -153
  12. data/app/helpers/dry_crud/table/actions.rb +69 -67
  13. data/app/helpers/dry_crud/table/builder.rb +96 -95
  14. data/app/helpers/dry_crud/table/col.rb +17 -16
  15. data/app/helpers/dry_crud/table/sorting.rb +48 -46
  16. data/app/helpers/format_helper.rb +2 -2
  17. data/app/helpers/table_helper.rb +2 -2
  18. data/lib/generators/dry_crud/file_generator.rb +2 -2
  19. data/lib/generators/dry_crud/templates/spec/controllers/crud_test_models_controller_spec.rb +4 -6
  20. data/lib/generators/dry_crud/templates/spec/helpers/dry_crud/form/builder_spec.rb +11 -11
  21. data/lib/generators/dry_crud/templates/spec/helpers/form_helper_spec.rb +21 -21
  22. data/lib/generators/dry_crud/templates/spec/helpers/format_helper_spec.rb +21 -17
  23. data/lib/generators/dry_crud/templates/spec/support/crud_controller_examples.rb +8 -8
  24. data/lib/generators/dry_crud/templates/spec/support/crud_controller_test_helper.rb +11 -1
  25. data/lib/generators/dry_crud/templates/test/controllers/crud_test_models_controller_test.rb +6 -6
  26. data/lib/generators/dry_crud/templates/test/helpers/custom_assertions_test.rb +1 -0
  27. data/lib/generators/dry_crud/templates/test/helpers/dry_crud/form/builder_test.rb +250 -245
  28. data/lib/generators/dry_crud/templates/test/helpers/dry_crud/table/builder_test.rb +141 -128
  29. data/lib/generators/dry_crud/templates/test/helpers/form_helper_test.rb +54 -54
  30. data/lib/generators/dry_crud/templates/test/helpers/format_helper_test.rb +4 -4
  31. data/lib/generators/dry_crud/templates/test/helpers/table_helper_test.rb +1 -1
  32. data/lib/generators/dry_crud/templates/test/support/crud_controller_test_helper.rb +3 -2
  33. data/lib/generators/dry_crud/templates/test/support/crud_test_helper.rb +8 -8
  34. data/lib/generators/dry_crud/templates/test/support/crud_test_model.rb +0 -2
  35. data/lib/generators/dry_crud/templates/test/support/crud_test_models_controller.rb +7 -7
  36. data/lib/generators/dry_crud/templates/test/support/custom_assertions.rb +3 -3
  37. metadata +6 -6
@@ -1,179 +1,182 @@
1
1
  # encoding: UTF-8
2
2
 
3
- module DryCrud::Form
4
-
5
- # Internal class to handle the rendering of a single form control,
6
- # consisting of a label, input field, addon, help text or
7
- # required mark.
8
- class Control
9
-
10
- attr_reader :builder, :attr, :args, :options, :span, :addon, :help
11
-
12
- delegate :content_tag, :object,
13
- to: :builder
14
-
15
- # Html displayed to mark an input as required.
16
- REQUIRED_MARK = '*'
17
-
18
- # Number of default input field span columns depending
19
- # on the #field_method.
20
- INPUT_SPANS = Hash.new(8)
21
- INPUT_SPANS[:number_field] =
22
- INPUT_SPANS[:integer_field] =
23
- INPUT_SPANS[:float_field] =
24
- INPUT_SPANS[:decimal_field] = 2
25
- INPUT_SPANS[:date_field] =
26
- INPUT_SPANS[:time_field] = 3
27
-
28
- # Create a new control instance.
29
- # Takes the form builder, the attribute to build the control for
30
- # as well as any additional arguments for the field method.
31
- # This includes an options hash as the last argument, that
32
- # may contain the following special options:
33
- #
34
- # * <tt>:addon</tt> - Addon content displayd just after the input field.
35
- # * <tt>:help</tt> - A help text displayd below the input field.
36
- # * <tt>:span</tt> - Number of columns the input field should span.
37
- # * <tt>:caption</tt> - Different caption for the label.
38
- # * <tt>:field_method</tt> - Different method to create the input field.
39
- # * <tt>:required</tt> - Sets the field as required
40
- # (The value for this option usually is 'required').
41
- #
42
- # All the other options will go to the field_method.
43
- def initialize(builder, attr, *args)
44
- @builder = builder
45
- @attr = attr
46
- @options = args.extract_options!
47
- @args = args
48
-
49
- @addon = options.delete(:addon)
50
- @help = options.delete(:help)
51
- @span = options.delete(:span)
52
- @caption = options.delete(:caption)
53
- @field_method = options.delete(:field_method)
54
- @required = options[:required]
55
- end
3
+ module DryCrud
4
+ module Form
5
+
6
+ # Internal class to handle the rendering of a single form control,
7
+ # consisting of a label, input field, addon, help text or
8
+ # required mark.
9
+ class Control
10
+
11
+ attr_reader :builder, :attr, :args, :options, :span, :addon, :help
12
+
13
+ delegate :content_tag, :object,
14
+ to: :builder
15
+
16
+ # Html displayed to mark an input as required.
17
+ REQUIRED_MARK = '*'
18
+
19
+ # Number of default input field span columns depending
20
+ # on the #field_method.
21
+ INPUT_SPANS = Hash.new(8)
22
+ INPUT_SPANS[:number_field] =
23
+ INPUT_SPANS[:integer_field] =
24
+ INPUT_SPANS[:float_field] =
25
+ INPUT_SPANS[:decimal_field] = 2
26
+ INPUT_SPANS[:date_field] =
27
+ INPUT_SPANS[:time_field] = 3
28
+
29
+ # Create a new control instance.
30
+ # Takes the form builder, the attribute to build the control for
31
+ # as well as any additional arguments for the field method.
32
+ # This includes an options hash as the last argument, that
33
+ # may contain the following special options:
34
+ #
35
+ # * <tt>:addon</tt> - Addon content displayd just after the input field.
36
+ # * <tt>:help</tt> - A help text displayd below the input field.
37
+ # * <tt>:span</tt> - Number of columns the input field should span.
38
+ # * <tt>:caption</tt> - Different caption for the label.
39
+ # * <tt>:field_method</tt> - Different method to create the input field.
40
+ # * <tt>:required</tt> - Sets the field as required
41
+ # (The value for this option usually is 'required').
42
+ #
43
+ # All the other options will go to the field_method.
44
+ def initialize(builder, attr, *args)
45
+ @builder = builder
46
+ @attr = attr
47
+ @options = args.extract_options!
48
+ @args = args
49
+
50
+ @addon = options.delete(:addon)
51
+ @help = options.delete(:help)
52
+ @span = options.delete(:span)
53
+ @caption = options.delete(:caption)
54
+ @field_method = options.delete(:field_method)
55
+ @required = options[:required]
56
+ end
56
57
 
57
- # Renders only the content of the control.
58
- # I.e. no label and span divs.
59
- def render_content
60
- content
61
- end
58
+ # Renders only the content of the control.
59
+ # I.e. no label and span divs.
60
+ def render_content
61
+ content
62
+ end
62
63
 
63
- # Renders the complete control with label and everything.
64
- # Render the content given or the default one.
65
- def render_labeled(content = nil)
66
- @content = content if content
67
- labeled
68
- end
64
+ # Renders the complete control with label and everything.
65
+ # Render the content given or the default one.
66
+ def render_labeled(content = nil)
67
+ @content = content if content
68
+ labeled
69
+ end
69
70
 
70
- private
71
+ private
71
72
 
72
- # Create the HTML markup for any labeled content.
73
- def labeled
74
- errors = errors? ? ' has-error' : ''
73
+ # Create the HTML markup for any labeled content.
74
+ def labeled
75
+ errors = errors? ? ' has-error' : ''
75
76
 
76
- content_tag(:div, class: "form-group#{errors}") do
77
- builder.label(attr, caption, class: 'col-md-2 control-label') +
78
- content_tag(:div, content, class: "col-md-#{span}")
77
+ content_tag(:div, class: "form-group#{errors}") do
78
+ builder.label(attr, caption, class: 'col-md-2 control-label') +
79
+ content_tag(:div, content, class: "col-md-#{span}")
80
+ end
79
81
  end
80
- end
81
82
 
82
- # Return the currently set content or create it
83
- # based on the various options given.
84
- #
85
- # Optionally renders addon, required mark and/or a help block
86
- # additionally to the input field.
87
- def content
88
- @content ||= begin
89
- content = input
90
- if addon
91
- content = builder.with_addon(content, addon)
92
- elsif required
93
- content = builder.with_addon(content, REQUIRED_MARK)
83
+ # Return the currently set content or create it
84
+ # based on the various options given.
85
+ #
86
+ # Optionally renders addon, required mark and/or a help block
87
+ # additionally to the input field.
88
+ def content
89
+ @content ||= begin
90
+ content = input
91
+ if addon
92
+ content = builder.with_addon(content, addon)
93
+ elsif required
94
+ content = builder.with_addon(content, REQUIRED_MARK)
95
+ end
96
+ content << builder.help_block(help) if help.present?
97
+ content
94
98
  end
95
- content << builder.help_block(help) if help.present?
96
- content
97
99
  end
98
- end
99
100
 
100
- # Return the currently set input field or create it
101
- # depending on the attribute.
102
- def input
103
- @input ||= begin
104
- builder.add_css_class(options, 'form-control')
105
- options[:required] = 'required' if required
106
- builder.send(field_method, attr, *(args << options))
101
+ # Return the currently set input field or create it
102
+ # depending on the attribute.
103
+ def input
104
+ @input ||= begin
105
+ options[:required] = 'required' if required
106
+ builder.send(field_method, attr, *(args << options))
107
+ end
107
108
  end
108
- end
109
109
 
110
- # The field method used to create the input.
111
- # If none is set, detect it from the attribute type.
112
- def field_method
113
- @field_method ||= detect_field_method
114
- end
110
+ # The field method used to create the input.
111
+ # If none is set, detect it from the attribute type.
112
+ def field_method
113
+ @field_method ||= detect_field_method
114
+ end
115
115
 
116
- # True if the attr is required, false otherwise.
117
- def required
118
- @required = @required.nil? ? builder.required?(attr) : @required
119
- end
116
+ # True if the attr is required, false otherwise.
117
+ def required
118
+ @required = @required.nil? ? builder.required?(attr) : @required
119
+ end
120
120
 
121
- # Number of grid columns the input field should span.
122
- def span
123
- @span ||= INPUT_SPANS[field_method]
124
- end
121
+ # Number of grid columns the input field should span.
122
+ def span
123
+ @span ||= INPUT_SPANS[field_method]
124
+ end
125
125
 
126
- # The caption of the label.
127
- # If none is set, uses the I18n value of the attribute.
128
- def caption
129
- @caption ||= builder.captionize(attr, object.class)
130
- end
126
+ # The caption of the label.
127
+ # If none is set, uses the I18n value of the attribute.
128
+ def caption
129
+ @caption ||= builder.captionize(attr, object.class)
130
+ end
131
131
 
132
- # Returns true if any errors are found on the passed attribute or its
133
- # association.
134
- def errors?
135
- attr_plain, attr_id = builder.assoc_and_id_attr(attr)
136
- # errors aint a Hash
137
- # rubocop:disable HashMethods
138
- object.errors.has_key?(attr_plain.to_sym) ||
139
- object.errors.has_key?(attr_id.to_sym)
140
- # rubocop:enable HashMethods
141
- end
132
+ # Returns true if any errors are found on the passed attribute or its
133
+ # association.
134
+ def errors?
135
+ attr_plain, attr_id = builder.assoc_and_id_attr(attr)
136
+ # errors aint a Hash
137
+ # rubocop:disable DeprecatedHashMethods
138
+ object.errors.has_key?(attr_plain.to_sym) ||
139
+ object.errors.has_key?(attr_id.to_sym)
140
+ # rubocop:enable DeprecatedHashMethods
141
+ end
142
142
 
143
- # Defines the field method to use based on the attribute
144
- # type, association or name.
145
- def detect_field_method
146
- if type == :text
147
- :text_area
148
- elsif association_kind?(:belongs_to)
149
- :belongs_to_field
150
- elsif association_kind?(:has_and_belongs_to_many, :has_many)
151
- :has_many_field
152
- elsif attr.to_s.include?('password')
153
- :password_field
154
- elsif attr.to_s.include?('email')
155
- :email_field
156
- elsif builder.respond_to?(:"#{type}_field")
157
- :"#{type}_field"
158
- else
159
- :text_field
143
+ # Defines the field method to use based on the attribute
144
+ # type, association or name.
145
+ # rubocop:disable PerceivedComplexity
146
+ def detect_field_method
147
+ if type == :text
148
+ :text_area
149
+ elsif association_kind?(:belongs_to)
150
+ :belongs_to_field
151
+ elsif association_kind?(:has_and_belongs_to_many, :has_many)
152
+ :has_many_field
153
+ elsif attr.to_s.include?('password')
154
+ :password_field
155
+ elsif attr.to_s.include?('email')
156
+ :email_field
157
+ elsif builder.respond_to?(:"#{type}_field")
158
+ :"#{type}_field"
159
+ else
160
+ :text_field
161
+ end
160
162
  end
161
- end
163
+ # rubocop:enable PerceivedComplexity
162
164
 
163
- # The column type of the attribute.
164
- def type
165
- @type ||= builder.column_type(object, attr)
166
- end
165
+ # The column type of the attribute.
166
+ def type
167
+ @type ||= builder.column_type(object, attr)
168
+ end
167
169
 
168
- # Returns true if attr is a non-polymorphic association.
169
- # If one or more macros are given, the association must be of this kind.
170
- def association_kind?(*macros)
171
- if type == :integer || type.nil?
172
- assoc = builder.association(object, attr, *macros)
170
+ # Returns true if attr is a non-polymorphic association.
171
+ # If one or more macros are given, the association must be of this kind.
172
+ def association_kind?(*macros)
173
+ if type == :integer || type.nil?
174
+ assoc = builder.association(object, attr, *macros)
173
175
 
174
- assoc.present? && assoc.options[:polymorphic].nil?
175
- else
176
- false
176
+ assoc.present? && assoc.options[:polymorphic].nil?
177
+ else
178
+ false
179
+ end
177
180
  end
178
181
  end
179
182
  end
@@ -1,88 +1,90 @@
1
1
  # encoding: UTF-8
2
2
 
3
- module DryCrud::Table
4
- # Adds action columns to the table builder.
5
- # Predefined actions are available for show, edit and destroy.
6
- # Additionally, a special col type to define cells linked to the show page
7
- # of the row entry is provided.
8
- module Actions
9
- extend ActiveSupport::Concern
3
+ module DryCrud
4
+ module Table
5
+ # Adds action columns to the table builder.
6
+ # Predefined actions are available for show, edit and destroy.
7
+ # Additionally, a special col type to define cells linked to the show page
8
+ # of the row entry is provided.
9
+ module Actions
10
+ extend ActiveSupport::Concern
10
11
 
11
- included do
12
- delegate :link_to, :path_args, :edit_polymorphic_path, :ti,
13
- to: :template
14
- end
12
+ included do
13
+ delegate :link_to, :path_args, :edit_polymorphic_path, :ti,
14
+ to: :template
15
+ end
15
16
 
16
- # Renders the passed attr with a link to the show action for
17
- # the current entry.
18
- # A block may be given to define the link path for the row entry.
19
- def attr_with_show_link(attr, &block)
20
- sortable_attr(attr) do |e|
21
- link_to(format_attr(e, attr), action_path(e, &block))
17
+ # Renders the passed attr with a link to the show action for
18
+ # the current entry.
19
+ # A block may be given to define the link path for the row entry.
20
+ def attr_with_show_link(attr, &block)
21
+ sortable_attr(attr) do |e|
22
+ link_to(format_attr(e, attr), action_path(e, &block))
23
+ end
22
24
  end
23
- end
24
25
 
25
- # Action column to show the row entry.
26
- # A block may be given to define the link path for the row entry.
27
- # If the block returns nil, no link is rendered.
28
- def show_action_col(html_options = {}, &block)
29
- action_col do |e|
30
- path = action_path(e, &block)
31
- if path
32
- table_action_link('zoom-in',
33
- path,
34
- html_options.clone)
26
+ # Action column to show the row entry.
27
+ # A block may be given to define the link path for the row entry.
28
+ # If the block returns nil, no link is rendered.
29
+ def show_action_col(html_options = {}, &block)
30
+ action_col do |e|
31
+ path = action_path(e, &block)
32
+ if path
33
+ table_action_link('zoom-in',
34
+ path,
35
+ html_options.clone)
36
+ end
35
37
  end
36
38
  end
37
- end
38
39
 
39
- # Action column to edit the row entry.
40
- # A block may be given to define the link path for the row entry.
41
- # If the block returns nil, no link is rendered.
42
- def edit_action_col(html_options = {}, &block)
43
- action_col do |e|
44
- path = action_path(e, &block)
45
- if path
46
- path = path.is_a?(String) ? path : edit_polymorphic_path(path)
47
- table_action_link('pencil', path, html_options.clone)
40
+ # Action column to edit the row entry.
41
+ # A block may be given to define the link path for the row entry.
42
+ # If the block returns nil, no link is rendered.
43
+ def edit_action_col(html_options = {}, &block)
44
+ action_col do |e|
45
+ path = action_path(e, &block)
46
+ if path
47
+ path = path.is_a?(String) ? path : edit_polymorphic_path(path)
48
+ table_action_link('pencil', path, html_options.clone)
49
+ end
48
50
  end
49
51
  end
50
- end
51
52
 
52
- # Action column to destroy the row entry.
53
- # A block may be given to define the link path for the row entry.
54
- # If the block returns nil, no link is rendered.
55
- def destroy_action_col(html_options = {}, &block)
56
- action_col do |e|
57
- path = action_path(e, &block)
58
- if path
59
- table_action_link('remove',
60
- path,
61
- html_options.merge(
62
- data: { confirm: ti(:confirm_delete),
63
- method: :delete }))
53
+ # Action column to destroy the row entry.
54
+ # A block may be given to define the link path for the row entry.
55
+ # If the block returns nil, no link is rendered.
56
+ def destroy_action_col(html_options = {}, &block)
57
+ action_col do |e|
58
+ path = action_path(e, &block)
59
+ if path
60
+ table_action_link('remove',
61
+ path,
62
+ html_options.merge(
63
+ data: { confirm: ti(:confirm_delete),
64
+ method: :delete }))
65
+ end
64
66
  end
65
67
  end
66
- end
67
68
 
68
- # Action column inside a table. No header.
69
- # The cell content should be defined in the passed block.
70
- def action_col(&block)
71
- col('', class: 'action', &block)
72
- end
69
+ # Action column inside a table. No header.
70
+ # The cell content should be defined in the passed block.
71
+ def action_col(&block)
72
+ col('', class: 'action', &block)
73
+ end
73
74
 
74
- # Generic action link inside a table.
75
- def table_action_link(icon, url, html_options = {})
76
- add_css_class(html_options, "icon icon-#{icon}")
77
- link_to('', url, html_options)
78
- end
75
+ # Generic action link inside a table.
76
+ def table_action_link(icon, url, html_options = {})
77
+ add_css_class(html_options, "icon icon-#{icon}")
78
+ link_to('', url, html_options)
79
+ end
79
80
 
80
- private
81
+ private
81
82
 
82
- # If a block is given, call it to get the path for the current row entry.
83
- # Otherwise, return the standard path args.
84
- def action_path(e, &block)
85
- block_given? ? yield(e) : path_args(e)
83
+ # If a block is given, call it to get the path for the current row entry.
84
+ # Otherwise, return the standard path args.
85
+ def action_path(e)
86
+ block_given? ? yield(e) : path_args(e)
87
+ end
86
88
  end
87
89
  end
88
90
  end