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
@@ -1,11 +1,11 @@
1
1
 
2
- Thank you for using dry_crud. Feel free to adapt all generated classes to
3
- your needs. To integrate dry_crud into your code, only a few additions are
2
+ Thank you for using dry_crud. Feel free to adapt all generated classes to
3
+ your needs. To integrate dry_crud into your code, only a few additions are
4
4
  required:
5
5
 
6
- * For uniform CRUD functionallity, just subclass your controllers from
7
- CrudController.
8
- * Overwrite the :to_s method of your models for a human-friendly
6
+ * For uniform CRUD functionallity, just subclass your controllers from
7
+ CrudController.
8
+ * Overwrite the #to_s method of your models for a human-friendly
9
9
  representation.
10
10
 
11
11
 
@@ -7,26 +7,6 @@
7
7
  text-align: center;
8
8
  }
9
9
 
10
- .labeled {
11
- vertical-align: top;
12
- padding: 2px 0 2px;
13
- clear: both;
14
- }
15
-
16
- .labeled label {
17
- width: 120px;
18
- padding-right: 5px;
19
- float: left;
20
- }
21
-
22
- .labeled .value {
23
- margin-left: 130px;
24
- }
25
-
26
- .labeled .value p {
27
- margin: 0;
28
- }
29
-
30
10
  #content {
31
11
  clear: both;
32
12
  padding-top: 5px;
@@ -38,7 +38,7 @@ h1 {
38
38
  background-color: #F8F8F8;
39
39
  }
40
40
 
41
- .table tr:nth-child(even) {
41
+ .table tr:nth-child(even) {
42
42
  background-color: #F0F0F0;
43
43
  }
44
44
 
@@ -67,6 +67,27 @@ a img {
67
67
  border: none;
68
68
  }
69
69
 
70
+ dl {
71
+ vertical-align: top;
72
+ padding: 2px 0 2px;
73
+ clear: both;
74
+ }
75
+
76
+ dt {
77
+ width: 120px;
78
+ padding-right: 5px;
79
+ float: left;
80
+ font-style: italic;
81
+ }
82
+
83
+ dd {
84
+ margin-left: 130px;
85
+ }
86
+
87
+ dd p {
88
+ margin: 0;
89
+ }
90
+
70
91
  .table {
71
92
  margin-top: 10px;
72
93
  }
@@ -81,7 +102,6 @@ table.table {
81
102
  div.table {}
82
103
 
83
104
  table.table th {
84
- text-align: left;
85
105
  background-color: $theme_color;
86
106
  color: white;
87
107
  font-weight: bold;
@@ -89,12 +109,12 @@ table.table th {
89
109
  }
90
110
 
91
111
  table.table th a {
92
- color: white;
112
+ color: white;
93
113
  text-decoration: none;
94
114
  }
95
115
 
96
116
  table.table td {
97
- padding: 2px 4px;
117
+ padding: 2px 4px;
98
118
  }
99
119
 
100
120
  label {
@@ -0,0 +1,89 @@
1
+ # encoding: UTF-8
2
+
3
+ module Crud
4
+ # Connects the including controller to the model whose name corrsponds to
5
+ # the controller's name.
6
+ #
7
+ # The two main methods are +model_class+ and +model_scope+.
8
+ # Additional helper methods store and retrieve values in instance variables
9
+ # named after their class.
10
+ module GenericModel
11
+ extend ActiveSupport::Concern
12
+
13
+ included do
14
+ helper_method :model_class, :models_label, :path_args
15
+
16
+ private
17
+
18
+ delegate :model_class, :models_label, :model_identifier, to: 'self.class'
19
+ end
20
+
21
+ private
22
+
23
+ # The scope where model entries will be listed and created.
24
+ # This is mainly used for nested models to provide the
25
+ # required context.
26
+ def model_scope
27
+ <% if Rails.version < '4.0' -%>
28
+ model_class.scoped
29
+ <% else -%>
30
+ model_class.all
31
+ <% end -%><%# > fixing rdoc -%>
32
+ end
33
+
34
+ # The path arguments to link to the given model entry.
35
+ # If the controller is nested, this provides the required context.
36
+ def path_args(last)
37
+ last
38
+ end
39
+
40
+ # Get the instance variable named after the +model_class+.
41
+ # If the collection variable is required, pass true as the second argument.
42
+ def get_model_ivar(plural = false)
43
+ name = ivar_name(model_class)
44
+ name = name.pluralize if plural
45
+ instance_variable_get(:"@#{name}")
46
+ end
47
+
48
+ # Sets an instance variable with the underscored class name if the given
49
+ # value. If the value is a collection, sets the plural name.
50
+ def set_model_ivar(value)
51
+ name = if value.respond_to?(:klass) # ActiveRecord::Relation
52
+ ivar_name(value.klass).pluralize
53
+ elsif value.respond_to?(:each) # Array
54
+ ivar_name(value.first.class).pluralize
55
+ else
56
+ ivar_name(value.class)
57
+ end
58
+ instance_variable_set(:"@#{name}", value)
59
+ end
60
+
61
+ def ivar_name(klass)
62
+ klass.model_name.param_key
63
+ end
64
+
65
+ # Class methods from GenericModel.
66
+ module ClassMethods
67
+ # The ActiveRecord class of the model.
68
+ def model_class
69
+ @model_class ||= controller_name.classify.constantize
70
+ end
71
+
72
+ # The identifier of the model used for form parameters.
73
+ # I.e., the symbol of the underscored model name.
74
+ def model_identifier
75
+ @model_identifier ||= model_class.model_name.param_key
76
+ end
77
+
78
+ # A human readable plural name of the model.
79
+ def models_label(plural = true)
80
+ opts = { count: (plural ? 3 : 1) }
81
+ opts[:default] = model_class.model_name.human.titleize
82
+ opts[:default] = opts[:default].pluralize if plural
83
+
84
+ model_class.model_name.human(opts)
85
+ end
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,70 @@
1
+ # encoding: UTF-8
2
+
3
+ module Crud
4
+ # Provides functionality to nest controllers/resources.
5
+ # If a controller is nested, the parent classes and namespaces
6
+ # may be defined as an array in the +nesting+ class attribute.
7
+ #
8
+ # For example, a cities controller, nested in country and a admin
9
+ # namespace, may define this attribute as follows:
10
+ # self.nesting = :admin, Country
11
+ module Nestable
12
+ extend ActiveSupport::Concern
13
+
14
+ # Adds the :nesting class attribute and parent helper methods
15
+ # to the including controller.
16
+ included do
17
+ class_attribute :nesting
18
+
19
+ helper_method :parent, :parents
20
+
21
+ alias_method_chain :path_args, :nesting
22
+ alias_method_chain :model_scope, :nesting
23
+ end
24
+
25
+ private
26
+
27
+ # Returns the direct parent ActiveRecord of the current request, if any.
28
+ def parent
29
+ parents.select { |p| p.is_a?(ActiveRecord::Base) }.last
30
+ end
31
+
32
+ # Returns the parent entries of the current request, if any.
33
+ # These are ActiveRecords or namespace symbols, corresponding
34
+ # to the defined nesting attribute.
35
+ def parents
36
+ @parents ||= Array(nesting).map do |p|
37
+ if p.is_a?(Class) && p < ActiveRecord::Base
38
+ parent_entry(p)
39
+ else
40
+ p
41
+ end
42
+ end
43
+ end
44
+
45
+ # Loads the parent entry for the given ActiveRecord class.
46
+ # By default, performs a find with the class_name_id param.
47
+ def parent_entry(clazz)
48
+ set_model_ivar(clazz.find(params["#{clazz.name.underscore}_id"]))
49
+ end
50
+
51
+ # An array of objects used in url_for and related functions.
52
+ def path_args_with_nesting(last)
53
+ parents + [last]
54
+ end
55
+
56
+ # Uses the parent entry (if any) to constrain the model scope.
57
+ def model_scope_with_nesting
58
+ if parent.present?
59
+ parent_scope
60
+ else
61
+ model_scope_without_nesting
62
+ end
63
+ end
64
+
65
+ # The model scope for the current parent resource.
66
+ def parent_scope
67
+ parent.send(model_class.name.underscore.pluralize)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: UTF-8
2
+
3
+ module Crud
4
+ # Remembers certain params of the index action in order to return
5
+ # to the same list after an entry was viewed or edited.
6
+ # If the index is called with a param :returning, the remembered params
7
+ # will be re-used to present the user the same list as she left it.
8
+ #
9
+ # Define a list of param keys that should be remembered for the list action
10
+ # with the class attribute +remember_params+.
11
+ #
12
+ # The params are stored separately for each different +remember_key+, which
13
+ # defaults to the current request's path.
14
+ module Rememberable
15
+ extend ActiveSupport::Concern
16
+
17
+ included do
18
+ class_attribute :remember_params
19
+ self.remember_params = [:q, :sort, :sort_dir, :page]
20
+
21
+ before_filter :handle_remember_params, only: [:index]
22
+ end
23
+
24
+ private
25
+
26
+ # Store and restore the corresponding params.
27
+ def handle_remember_params
28
+ remembered = remembered_params
29
+
30
+ restore_params_on_return(remembered)
31
+ store_current_params(remembered)
32
+ clear_void_params(remembered)
33
+ end
34
+
35
+ def restore_params_on_return(remembered)
36
+ if params[:returning]
37
+ remember_params.each { |p| params[p] ||= remembered[p] }
38
+ end
39
+ end
40
+
41
+ def store_current_params(remembered)
42
+ remember_params.each do |p|
43
+ remembered[p] = params[p].presence
44
+ remembered.delete(p) if remembered[p].nil?
45
+ end
46
+ end
47
+
48
+ def clear_void_params(remembered)
49
+ session[:list_params].delete(remember_key) if remembered.blank?
50
+ end
51
+
52
+ # Get the params stored in the session.
53
+ def remembered_params
54
+ session[:list_params] ||= {}
55
+ session[:list_params][remember_key] ||= {}
56
+ end
57
+
58
+ # Params are stored by request path to play nice when a controller
59
+ # is used in different routes.
60
+ def remember_key
61
+ request.path
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,46 @@
1
+ # encoding: UTF-8
2
+
3
+ module Crud
4
+ # Provide +before_render+ callbacks.
5
+ module RenderCallbacks
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ extend ActiveModel::Callbacks
10
+
11
+ alias_method_chain :render, :callbacks
12
+ end
13
+
14
+ # Helper method to run +before_render+ callbacks and render the action.
15
+ # If a callback renders or redirects, the action is not rendered.
16
+ def render_with_callbacks(*args, &block)
17
+ options = _normalize_render(*args, &block)
18
+ callback = "render_#{options[:template]}"
19
+
20
+ run_callbacks(callback) if respond_to?(:"_#{callback}_callbacks", true)
21
+
22
+ render_without_callbacks(*args, &block) unless performed?
23
+ end
24
+
25
+ private
26
+
27
+ # Helper method the run the given block in between the before and after
28
+ # callbacks of the given kinds.
29
+ def with_callbacks(*kinds, &block)
30
+ kinds.reverse.reduce(block) do |a, e|
31
+ -> { run_callbacks(e, &a) }
32
+ end.call
33
+ end
34
+
35
+ # Class methods for callbacks.
36
+ module ClassMethods
37
+ # Defines before callbacks for the render actions.
38
+ def define_render_callbacks(*actions)
39
+ args = actions.map { |a| :"render_#{a}" }
40
+ args << { only: :before,
41
+ terminator: 'result == false || performed?' }
42
+ define_model_callbacks(*args)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: UTF-8
2
+
3
+ module Crud
4
+ # Custom Responder that handles the controller's +path_args+.
5
+ # An additional :success option is used to handle action callback
6
+ # chain halts.
7
+ class Responder < ActionController::Responder
8
+
9
+ def initialize(controller, resources, options = {})
10
+ super(controller, with_path_args(resources, controller), options)
11
+ end
12
+
13
+ private
14
+
15
+ # Check whether the resource has errors. Additionally checks the :success
16
+ # option.
17
+ def has_errors?
18
+ options[:success] == false || super
19
+ end
20
+
21
+ # Wraps the resources with the path_args for correct nesting.
22
+ def with_path_args(resources, controller)
23
+ if resources.size == 1
24
+ Array(controller.send(:path_args, resources.first))
25
+ else
26
+ resources
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: UTF-8
2
+
3
+ module Crud
4
+ # The search functionality for the index table.
5
+ # Define an array of searchable columns in your subclassing controllers
6
+ # using the class attribute +search_columns+.
7
+ module Searchable
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ class_attribute :search_columns
12
+ self.search_columns = []
13
+
14
+ helper_method :search_support?
15
+
16
+ alias_method_chain :list_entries, :search
17
+ end
18
+
19
+ private
20
+
21
+ # Enhance the list entries with an optional search criteria
22
+ def list_entries_with_search
23
+ list_entries_without_search.where(search_condition)
24
+ end
25
+
26
+ # Compose the search condition with a basic SQL OR query.
27
+ def search_condition
28
+ if search_support? && params[:q].present?
29
+ col_clause = search_column_clause
30
+ terms = params[:q].split(/\s+/).map { |t| "%#{t}%" }
31
+ term_clause = terms.map { |t| "(#{col_clause})" }.join(' AND ')
32
+
33
+ term_params = terms.map { |t| [t] * search_columns.size }.flatten
34
+ ["(#{term_clause})", *term_params]
35
+ end
36
+ end
37
+
38
+ # SQL where clause with all search colums or'ed.
39
+ def search_column_clause
40
+ search_columns.map do |f|
41
+ if f.to_s.include?('.')
42
+ "#{f} LIKE ?"
43
+ else
44
+ "#{model_class.table_name}.#{f} LIKE ?"
45
+ end
46
+ end.join(' OR ')
47
+ end
48
+
49
+ # Returns true if this controller has searchable columns.
50
+ def search_support?
51
+ search_columns.present?
52
+ end
53
+
54
+ end
55
+ end