hot-glue 0.5.11 → 0.5.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,6 @@
1
+
1
2
  require 'rails/generators/erb/scaffold/scaffold_generator'
3
+ require_relative './default_config_loader'
2
4
  require 'ffaker'
3
5
  require_relative './fields/field'
4
6
  require_relative './field_factory'
@@ -10,1225 +12,1167 @@ require_relative './layout_strategy/bootstrap'
10
12
  require_relative './layout_strategy/hot_glue'
11
13
  require_relative './layout_strategy/tailwind'
12
14
 
13
- module HotGlue
14
- class Error < StandardError
15
- end
16
-
17
- def self.construct_downnest_object(input)
18
- res = input.split(",").map { |child|
19
- child_name = child.gsub("+","")
20
- extra_size = child.count("+")
21
- {child_name => 4+extra_size}
22
- }
23
- Hash[*res.collect{|hash| hash.collect{|key,value| [key,value].flatten}.flatten}.flatten]
24
- end
25
-
26
- def self.optionalized_ternary(namespace: nil,
27
- target:,
28
- nested_set:,
29
- modifier: "",
30
- with_params: false,
31
- top_level: false,
32
- put_form: false)
33
- instance_sym = top_level ? "@" : ""
34
- if nested_set.nil? || nested_set.empty?
35
- return modifier + "#{(namespace + '_') if namespace}#{target}_path" + (("(#{instance_sym}#{target})" if put_form) || "")
36
- elsif nested_set[0][:optional] == false
37
- return modifier + ((namespace + "_" if namespace) || "") + nested_set.collect{|x|
38
- x[:singular] + "_"
39
- }.join() + target + "_path" + (("(#{nested_set.collect{
40
- |x| instance_sym + x[:singular] }.join(",")
41
- }#{ put_form ? ',' + instance_sym + target : '' })" if with_params) || "")
42
-
43
- else
44
- # copy the first item, make a ternery in this cycle, and recursively move to both the
45
- # is present path and the is optional path
46
-
47
- nonoptional = nested_set[0].dup
48
- nonoptional[:optional] = false
49
- rest_of_nest = nested_set[1..-1]
50
-
51
- is_present_path = HotGlue.optionalized_ternary(
52
- namespace: namespace,
53
- target: target,
54
- modifier: modifier,
55
- top_level: top_level,
56
- with_params: with_params,
57
- put_form: put_form,
58
- nested_set: [nonoptional, *rest_of_nest])
59
-
60
- is_missing_path = HotGlue.optionalized_ternary(
61
- namespace: namespace,
62
- target: target,
63
- modifier: modifier,
64
- top_level: top_level,
65
- with_params: with_params,
66
- put_form: put_form,
67
- nested_set: rest_of_nest )
68
- return "defined?(#{instance_sym + nested_set[0][:singular]}2) ? #{is_present_path} : #{is_missing_path}"
69
- end
70
- end
71
15
 
72
- def self.derrive_reference_name(thing_as_string)
73
- assoc_class = eval(thing_as_string)
74
16
 
75
- if assoc_class.new.respond_to?("name")
76
- display_column = "name"
77
- elsif assoc_class.new.respond_to?("to_label")
78
- display_column = "to_label"
79
- elsif assoc_class.new.respond_to?("full_name")
80
- display_column = "full_name"
81
- elsif assoc_class.new.respond_to?("display_name")
82
- display_column = "display_name"
83
- elsif assoc_class.new.respond_to?("email")
84
- display_column = "email"
85
- end
86
- display_column
87
- end
88
-
89
- class ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
90
- hook_for :form_builder, :as => :scaffold
91
-
92
- source_root File.expand_path('templates', __dir__)
93
- attr_accessor :path, :singular, :plural, :singular_class, :nest_with,
94
- :columns, :downnest_children, :layout_object, :alt_lookups,
95
- :update_show_only, :hawk_keys, :auth, :sample_file_path
96
-
97
- class_option :singular, type: :string, default: nil
98
- class_option :plural, type: :string, default: nil
99
- class_option :singular_class, type: :string, default: nil
100
- class_option :nest, type: :string, default: nil # DEPRECATED —— DO NOT USE
101
- class_option :nested, type: :string, default: ""
102
-
103
- class_option :namespace, type: :string, default: nil
104
- class_option :auth, type: :string, default: nil
105
- class_option :auth_identifier, type: :string, default: nil
106
- class_option :exclude, type: :string, default: ""
107
- class_option :include, type: :string, default: ""
108
- class_option :god, type: :boolean, default: false
109
- class_option :gd, type: :boolean, default: false # alias for god
110
-
111
- class_option :specs_only, type: :boolean, default: false
112
- class_option :no_specs, type: :boolean, default: false
113
- class_option :no_delete, type: :boolean, default: false
114
- class_option :no_create, type: :boolean, default: false
115
- class_option :no_edit, type: :boolean, default: false
116
- class_option :no_list, type: :boolean, default: false
117
- class_option :no_paginate, type: :boolean, default: false
118
- class_option :big_edit, type: :boolean, default: false
119
- class_option :show_only, type: :string, default: ""
120
- class_option :update_show_only, type: :string, default: ""
121
-
122
- class_option :ujs_syntax, type: :boolean, default: nil
123
- class_option :downnest, type: :string, default: nil
124
- class_option :magic_buttons, type: :string, default: nil
125
- class_option :small_buttons, type: :boolean, default: nil
126
- class_option :display_list_after_update, type: :boolean, default: false
127
- class_option :smart_layout, type: :boolean, default: false
128
- class_option :markup, type: :string, default: nil # deprecated -- use in app config instead
129
- class_option :layout, type: :string, default: nil # if used here it will override what is in the config
130
- class_option :hawk, type: :string, default: nil
131
- class_option :with_turbo_streams, type: :boolean, default: false
132
-
133
- class_option :label, default: nil
134
- class_option :list_label_heading, default: nil
135
- class_option :new_button_label, default: nil
136
- class_option :new_form_heading, default: nil
137
-
138
- class_option :no_list_label, type: :boolean, default: false
139
- class_option :no_list_heading, type: :boolean, default: false
140
-
141
- # determines if the labels show up BEFORE or AFTER on the NEW/EDIT (form)
142
- class_option :form_labels_position, type: :string, default: 'after' # choices are before, after, omit
143
- class_option :form_placeholder_labels, type: :boolean, default: false # puts the field names into the placeholder labels
144
-
145
- # determines if labels appear within the rows of the VIEWABLE list (does NOT affect the list heading)
146
- class_option :inline_list_labels, default: 'omit' # choices are before, after, omit
147
- class_option :factory_creation, default: ''
148
- class_option :alt_foreign_key_lookup, default: '' #
149
- class_option :attachments, default: ''
150
- class_option :stacked_downnesting, default: false
151
-
152
- def initialize(*meta_args)
153
- super
17
+ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
18
+ include DefaultConfigLoader
19
+ hook_for :form_builder, :as => :scaffold
20
+
21
+ source_root File.expand_path('templates', __dir__)
22
+ attr_accessor :alt_lookups, :attachments, :auth,
23
+ :big_edit, :bootstrap_column_width,
24
+ :columns,
25
+ :downnest_children, :downnest_object,
26
+ :button_icons,
27
+ :hawk_keys, :layout_object,
28
+ :nest_with,
29
+ :path, :plural,
30
+ :sample_file_path, :singular, :singular_class, :smart_layout,
31
+ :stacked_downnesting, :update_show_only
32
+
33
+ class_option :singular, type: :string, default: nil
34
+ class_option :plural, type: :string, default: nil
35
+ class_option :singular_class, type: :string, default: nil
36
+ class_option :nest, type: :string, default: nil # DEPRECATED —— DO NOT USE
37
+ class_option :nested, type: :string, default: ""
38
+
39
+ class_option :namespace, type: :string, default: nil
40
+ class_option :auth, type: :string, default: nil
41
+ class_option :auth_identifier, type: :string, default: nil
42
+ class_option :exclude, type: :string, default: ""
43
+ class_option :include, type: :string, default: ""
44
+ class_option :god, type: :boolean, default: false
45
+ class_option :gd, type: :boolean, default: false # alias for god
46
+
47
+ class_option :specs_only, type: :boolean, default: false
48
+ class_option :no_specs, type: :boolean, default: false
49
+ class_option :no_delete, type: :boolean, default: false
50
+ class_option :no_create, type: :boolean, default: false
51
+ class_option :no_edit, type: :boolean, default: false
52
+ class_option :no_list, type: :boolean, default: false
53
+ class_option :no_paginate, type: :boolean, default: false
54
+ class_option :big_edit, type: :boolean, default: false
55
+ class_option :show_only, type: :string, default: ""
56
+ class_option :update_show_only, type: :string, default: ""
57
+
58
+ class_option :ujs_syntax, type: :boolean, default: nil
59
+ class_option :downnest, type: :string, default: nil
60
+ class_option :magic_buttons, type: :string, default: nil
61
+ class_option :small_buttons, type: :boolean, default: nil
62
+ class_option :display_list_after_update, type: :boolean, default: false
63
+ class_option :smart_layout, type: :boolean, default: false
64
+ class_option :markup, type: :string, default: nil # deprecated -- use in app config instead
65
+ class_option :layout, type: :string, default: nil # if used here it will override what is in the config
66
+ class_option :hawk, type: :string, default: nil
67
+ class_option :with_turbo_streams, type: :boolean, default: false
68
+
69
+ class_option :label, default: nil
70
+ class_option :list_label_heading, default: nil
71
+ class_option :new_button_label, default: nil
72
+ class_option :new_form_heading, default: nil
73
+
74
+ class_option :no_list_label, type: :boolean, default: false
75
+ class_option :no_list_heading, type: :boolean, default: false
76
+
77
+ # determines if the labels show up BEFORE or AFTER on the NEW/EDIT (form)
78
+ class_option :form_labels_position, type: :string, default: 'after' # choices are before, after, omit
79
+ class_option :form_placeholder_labels, type: :boolean, default: false # puts the field names into the placeholder labels
80
+
81
+ # determines if labels appear within the rows of the VIEWABLE list (does NOT affect the list heading)
82
+ class_option :inline_list_labels, default: 'omit' # choices are before, after, omit
83
+ class_option :factory_creation, default: ''
84
+ class_option :alt_foreign_key_lookup, default: '' #
85
+ class_option :attachments, default: ''
86
+ class_option :stacked_downnesting, default: false
87
+ class_option :bootstrap_column_width, default: nil #must be nil to detect if user has not passed
88
+ class_option :button_icons, default: nil
89
+
90
+ def initialize(*meta_args)
91
+ super
92
+
93
+ begin
94
+ @the_object = eval(class_name)
95
+ rescue StandardError => e
96
+ message = "*** Oops: It looks like there is no object for #{class_name}. Please define the object + database table first."
97
+ puts message
98
+ raise(HotGlue::Error, message)
99
+ end
100
+
101
+ @meta_args = meta_args
102
+
103
+ if options['specs_only'] && options['no_specs']
104
+ raise(HotGlue::Error, "*** Oops: You seem to have specified both the --specs-only flag and --no-specs flags. this doesn't make any sense, so I am aborting. Aborting.")
105
+ end
106
+
107
+ if !options['exclude'].empty? && !options['include'].empty?
108
+ exit_message = "*** Oops: You seem to have specified both --include and --exclude. Please use one or the other. Aborting."
109
+ puts exit_message
110
+
111
+ raise(HotGlue::Error, exit_message)
112
+ end
113
+
114
+
115
+ if @stimulus_syntax.nil?
116
+ @stimulus_syntax = true
117
+ end
118
+
119
+ if !options['markup'].nil?
120
+ message = "Using --markup flag in the generator is deprecated; instead, use a file at config/hot_glue.yml with a key markup set to `erb` or `haml`"
121
+ raise(HotGlue::Error, message)
122
+ end
123
+
124
+ @markup = get_default_from_config(key: :markup)
125
+ @sample_file_path = get_default_from_config(key: :sample_file_path)
126
+ @bootstrap_column_width ||= get_default_from_config(key: :bootstrap_column_width) || 2
127
+
128
+ if options['layout']
129
+ layout = options['layout']
130
+ else
131
+ layout = get_default_from_config(key: :layout)
154
132
 
155
- begin
156
- @the_object = eval(class_name)
157
- rescue StandardError => e
158
- message = "*** Oops: It looks like there is no object for #{class_name}. Please define the object + database table first."
159
- puts message
160
- raise(HotGlue::Error, message)
133
+ if !['hotglue', 'bootstrap', 'tailwind'].include? layout
134
+ raise "Invalid option #{layout} in Hot glue config (config/hot_glue.yml). You must either use --layout= when generating or have a file config/hotglue.yml; specify layout as either 'hotglue' or 'bootstrap'"
161
135
  end
136
+ end
162
137
 
163
- @meta_args = meta_args
138
+ @button_icons = get_default_from_config(key: :button_icons) || 'none'
164
139
 
165
- if options['specs_only'] && options['no_specs']
166
- raise(HotGlue::Error, "*** Oops: You seem to have specified both the --specs-only flag and --no-specs flags. this doesn't make any sense, so I am aborting. Aborting.")
140
+ @layout_strategy =
141
+ case layout
142
+ when 'bootstrap'
143
+ LayoutStrategy::Bootstrap.new(self)
144
+ when 'tailwind'
145
+ LayoutStrategy::Tailwind.new(self)
146
+ when 'hotglue'
147
+ LayoutStrategy::HotGlue.new(self)
167
148
  end
168
149
 
169
- if !options['exclude'].empty? && !options['include'].empty?
170
- exit_message = "*** Oops: You seem to have specified both --include and --exclude. Please use one or the other. Aborting."
171
- puts exit_message
150
+ args = meta_args[0]
151
+ @singular = args.first.tableize.singularize # should be in form hello_world
172
152
 
173
- raise(HotGlue::Error, exit_message)
174
- end
153
+ if @singular.include?("/")
154
+ @singular = @singular.split("/").last
155
+ end
175
156
 
157
+ @plural = options['plural'] || @singular.pluralize # respects what you set in inflections.rb, to override, use plural option
158
+ @namespace = options['namespace'] || nil
159
+ use_controller_name = plural.titleize.gsub(" ", "")
160
+ @controller_build_name = (( @namespace.titleize.gsub(" ","") + "::" if @namespace) || "") + use_controller_name + "Controller"
161
+ @controller_build_folder = use_controller_name.underscore
162
+ @controller_build_folder_singular = singular
176
163
 
177
- if @stimulus_syntax.nil?
178
- @stimulus_syntax = true
179
- end
164
+ @auth = options['auth'] || "current_user"
165
+ @auth_identifier = options['auth_identifier'] || (! @god && @auth.gsub("current_", "")) || nil
180
166
 
181
- if !options['markup'].nil?
182
- message = "Using --markup flag in the generator is deprecated; instead, use a file at config/hot_glue.yml with a key markup set to `erb` or `haml`"
183
- raise(HotGlue::Error, message)
184
- end
167
+ if options['nest']
168
+ raise HotGlue::Error, "STOP: the flag --nest has been replaced with --nested; please re-run using the --nested flag"
169
+ end
170
+ @nested = (!options['nested'].empty? && options['nested']) || nil
171
+ @singular_class = args.first # note this is the full class name with a model namespace
185
172
 
186
- yaml_from_config = YAML.load(File.read("config/hot_glue.yml"))
187
- @markup = yaml_from_config[:markup]
188
- @sample_file_path = yaml_from_config[:sample_file_path]
173
+ setup_attachments
189
174
 
190
- if options['layout']
191
- layout = options['layout']
192
- else
193
- layout = yaml_from_config[:layout]
175
+ @exclude_fields = []
176
+ @exclude_fields += options['exclude'].split(",").collect(&:to_sym)
194
177
 
195
- if !['hotglue', 'bootstrap', 'tailwind'].include? layout
196
- raise "Invalid option #{layout} in Hot glue config (config/hot_glue.yml). You must either use --layout= when generating or have a file config/hotglue.yml; specify layout as either 'hotglue' or 'bootstrap'"
197
- end
198
- end
178
+ if !options['include'].empty?
179
+ @include_fields = []
199
180
 
200
- @layout_strategy =
201
- case layout
202
- when 'bootstrap'
203
- LayoutStrategy::Bootstrap.new(self)
204
- when 'tailwind'
205
- LayoutStrategy::Tailwind.new(self)
206
- when 'hotglue'
207
- LayoutStrategy::HotGlue.new(self)
208
- end
181
+ # semicolon to denote layout columns; commas separate fields
182
+ @include_fields += options['include'].split(":").collect{|x|x.split(",")}.flatten.collect(&:to_sym)
183
+ end
209
184
 
210
- args = meta_args[0]
211
- @singular = args.first.tableize.singularize # should be in form hello_world
185
+ @show_only = []
186
+ if !options['show_only'].empty?
187
+ @show_only += options['show_only'].split(",").collect(&:to_sym)
188
+ end
212
189
 
213
- if @singular.include?("/")
214
- @singular = @singular.split("/").last
215
- end
190
+ @update_show_only = []
191
+ if !options['update_show_only'].empty?
192
+ @update_show_only += options['update_show_only'].split(",").collect(&:to_sym)
193
+ end
216
194
 
217
- @plural = options['plural'] || @singular.pluralize # respects what you set in inflections.rb, to override, use plural option
218
- @namespace = options['namespace'] || nil
219
- use_controller_name = plural.titleize.gsub(" ", "")
220
- @controller_build_name = (( @namespace.titleize.gsub(" ","") + "::" if @namespace) || "") + use_controller_name + "Controller"
221
- @controller_build_folder = use_controller_name.underscore
222
- @controller_build_folder_singular = singular
223
195
 
224
- @auth = options['auth'] || "current_user"
225
- @auth_identifier = options['auth_identifier'] || (! @god && @auth.gsub("current_", "")) || nil
196
+ # syntax should be xyz_id{xyz_email},abc_id{abc_email}
197
+ # instead of a drop-down for the foreign entity, a text field will be presented
198
+ # You must ALSO use a factory that contains a parameter of the same name as the 'value' (for example, `xyz_email`)
226
199
 
227
- if options['nest']
228
- raise HotGlue::Error, "STOP: the flag --nest has been replaced with --nested; please re-run using the --nested flag"
229
- end
230
- @nested = (!options['nested'].empty? && options['nested']) || nil
231
- @singular_class = args.first # note this is the full class name with a model namespace
200
+ alt_lookups_entry = options['alt_foreign_key_lookup'].split(",")
201
+ @alt_lookups = {}
202
+ @alt_foreign_key_lookup = alt_lookups_entry.each do |setting|
203
+ setting =~ /(.*){(.*)}/
204
+ key, lookup_as = $1, $2
205
+ assoc = eval("#{class_name}.reflect_on_association(:#{key.to_s.gsub("_id","")}).class_name")
232
206
 
233
- setup_attachments
207
+ data = {lookup_as: lookup_as.gsub("+",""),
208
+ assoc: assoc,
209
+ with_create: lookup_as.include?("+")}
210
+ @alt_lookups[key] = data
211
+ end
234
212
 
235
- @exclude_fields = []
236
- @exclude_fields += options['exclude'].split(",").collect(&:to_sym)
213
+ puts "------ ALT LOOKUPS for #{@alt_lookups}"
237
214
 
238
- if !options['include'].empty?
239
- @include_fields = []
215
+ @update_alt_lookups = @alt_lookups.collect{|key, value|
216
+ @update_show_only.include?(key) ?
217
+ { key: value }
218
+ : nil}.compact
240
219
 
241
- # semicolon to denote layout columns; commas separate fields
242
- @include_fields += options['include'].split(":").collect{|x|x.split(",")}.flatten.collect(&:to_sym)
243
- end
220
+ @label = options['label'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_singular)") ? eval("#{class_name}.class_variable_get(:@@table_label_singular)") : singular.gsub("_", " ").titleize )
221
+ @list_label_heading = options['list_label_heading'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_plural)") ? eval("#{class_name}.class_variable_get(:@@table_label_plural)") : plural.gsub("_", " ").upcase )
244
222
 
245
- @show_only = []
246
- if !options['show_only'].empty?
247
- @show_only += options['show_only'].split(",").collect(&:to_sym)
248
- end
223
+ @new_button_label = options['new_button_label'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_singular)") ? "New " + eval("#{class_name}.class_variable_get(:@@table_label_singular)") : "New " + singular.gsub("_", " ").titleize )
224
+ @new_form_heading = options['new_form_heading'] || "New #{@label}"
249
225
 
250
- @update_show_only = []
251
- if !options['update_show_only'].empty?
252
- @update_show_only += options['update_show_only'].split(",").collect(&:to_sym)
253
- end
254
226
 
255
227
 
256
- # syntax should be xyz_id{xyz_email},abc_id{abc_email}
257
- # instead of a drop-down for the foreign entity, a text field will be presented
258
- # You must ALSO use a factory that contains a parameter of the same name as the 'value' (for example, `xyz_email`)
228
+ setup_hawk_keys
229
+ @form_placeholder_labels = options['form_placeholder_labels'] # true or false
230
+ @inline_list_labels = options['inline_list_labels'] || 'omit' # 'before','after','omit'
259
231
 
260
- alt_lookups_entry = options['alt_foreign_key_lookup'].split(",")
261
- @alt_lookups = {}
262
- @alt_foreign_key_lookup = alt_lookups_entry.each do |setting|
263
- setting =~ /(.*){(.*)}/
264
- key, lookup_as = $1, $2
265
- assoc = eval("#{class_name}.reflect_on_association(:#{key.to_s.gsub("_id","")}).class_name")
266
232
 
267
- data = {lookup_as: lookup_as.gsub("+",""),
268
- assoc: assoc,
269
- with_create: lookup_as.include?("+")}
270
- @alt_lookups[key] = data
271
- end
233
+ @form_labels_position = options['form_labels_position']
234
+ if !['before','after','omit'].include?(@form_labels_position)
235
+ raise HotGlue::Error, "You passed '#{@form_labels_position}' as the setting for --form-labels-position but the only allowed options are before, after (default), and omit"
236
+ end
272
237
 
273
- puts "------ ALT LOOKUPS for #{@alt_lookups}"
238
+ if !['before','after','omit'].include?(@inline_list_labels)
239
+ raise HotGlue::Error, "You passed '#{@inline_list_labels}' as the setting for --inline-list-labels but the only allowed options are before, after, and omit (default)"
240
+ end
274
241
 
275
- @update_alt_lookups = @alt_lookups.collect{|key, value|
276
- @update_show_only.include?(key) ?
277
- { key: value }
278
- : nil}.compact
279
242
 
280
- @label = options['label'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_singular)") ? eval("#{class_name}.class_variable_get(:@@table_label_singular)") : singular.gsub("_", " ").titleize )
281
- @list_label_heading = options['list_label_heading'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_plural)") ? eval("#{class_name}.class_variable_get(:@@table_label_plural)") : plural.gsub("_", " ").upcase )
282
243
 
283
- @new_button_label = options['new_button_label'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_singular)") ? "New " + eval("#{class_name}.class_variable_get(:@@table_label_singular)") : "New " + singular.gsub("_", " ").titleize )
284
- @new_form_heading = options['new_form_heading'] || "New #{@label}"
285
244
 
286
245
 
287
246
 
288
- setup_hawk_keys
289
- @form_placeholder_labels = options['form_placeholder_labels'] # true or false
290
- @inline_list_labels = options['inline_list_labels'] || 'omit' # 'before','after','omit'
247
+ @god = options['god'] || options['gd'] || false
248
+ @specs_only = options['specs_only'] || false
291
249
 
250
+ @no_specs = options['no_specs'] || false
251
+ @no_delete = options['no_delete'] || false
292
252
 
293
- @form_labels_position = options['form_labels_position']
294
- if !['before','after','omit'].include?(@form_labels_position)
295
- raise HotGlue::Error, "You passed '#{@form_labels_position}' as the setting for --form-labels-position but the only allowed options are before, after (default), and omit"
296
- end
253
+ @no_create = options['no_create'] || false
254
+ @no_paginate = options['no_paginate'] || false
255
+ @big_edit = options['big_edit']
297
256
 
298
- if !['before','after','omit'].include?(@inline_list_labels)
299
- raise HotGlue::Error, "You passed '#{@inline_list_labels}' as the setting for --inline-list-labels but the only allowed options are before, after, and omit (default)"
300
- end
257
+ @no_edit = options['no_edit'] || false
258
+ @no_list = options['no_list'] || false
259
+ @no_list_label = options['no_list_label'] || false
260
+ @no_list_heading = options['no_list_heading'] || false
261
+ @stacked_downnesting = options['stacked_downnesting']
301
262
 
302
263
 
303
264
 
304
- if @markup == "erb"
305
- @template_builder = HotGlue::ErbTemplate.new(
306
- layout_strategy: @layout_strategy,
307
- magic_buttons: @magic_buttons,
308
- small_buttons: @small_buttons,
309
- inline_list_labels: @inline_list_labels,
310
- show_only: @show_only,
311
- update_show_only: @update_show_only,
312
- singular_class: singular_class,
313
- singular: singular,
314
- hawk_keys: @hawk_keys,
315
- ownership_field: @ownership_field,
316
- form_labels_position: @form_labels_position,
317
- form_placeholder_labels: @form_placeholder_labels,
318
- alt_lookups: @alt_lookups,
319
- attachments: @attachments,
320
- )
321
- elsif @markup == "slim"
322
- raise(HotGlue::Error, "SLIM IS NOT IMPLEMENTED")
323
- elsif @markup == "haml"
324
- raise(HotGlue::Error, "HAML IS NOT IMPLEMENTED")
325
- end
326
265
 
327
- @god = options['god'] || options['gd'] || false
328
- @specs_only = options['specs_only'] || false
266
+ @display_list_after_update = options['display_list_after_update'] || false
267
+ @smart_layout = options['smart_layout']
329
268
 
330
- @no_specs = options['no_specs'] || false
331
- @no_delete = options['no_delete'] || false
269
+ if options['include'].include?(":") && @smart_layout
270
+ raise HotGlue::Error, "You specified both --smart-layout and also specified grouping mode (there is a : character in your field include list); you must remove the colon(s) from your --include tag or remove the --smart-layout option"
271
+ end
332
272
 
333
- @no_create = options['no_create'] || false
334
- @no_paginate = options['no_paginate'] || false
335
- @big_edit = options['big_edit']
273
+ @container_name = @layout_strategy.container_name
274
+ @downnest = options['downnest'] || false
336
275
 
337
- @no_edit = options['no_edit'] || false
338
- @no_list = options['no_list'] || false
339
- @no_list_label = options['no_list_label'] || false
340
- @no_list_heading = options['no_list_heading'] || false
341
- @stacked_downnesting = options['stacked_downnesting']
276
+ @downnest_children = [] # TODO: defactor @downnest_children in favor of downnest_object
277
+ @downnest_object = {}
278
+ if @downnest
279
+ @downnest_children = @downnest.split(",").map{|child| child.gsub("+","")}
280
+ @downnest_object = HotGlue.construct_downnest_object(@downnest)
281
+ end
342
282
 
283
+ if @god
284
+ @auth = nil
285
+ end
343
286
 
287
+ # when in self auth, the object is the same as the authenticated object
344
288
 
289
+ if @auth && auth_identifier == @singular
290
+ @self_auth = true
291
+ end
345
292
 
346
- @display_list_after_update = options['display_list_after_update'] || false
347
- @smart_layout = options['smart_layout']
293
+ if @self_auth && !@no_create
294
+ raise "This controller appears to be the same as the authentication object but in this context you cannot build a new/create action; please re-run with --no-create flag"
295
+ end
348
296
 
349
- if options['include'].include?(":") && @smart_layout
350
- raise HotGlue::Error, "You specified both --smart-layout and also specified grouping mode (there is a : character in your field include list); you must remove the colon(s) from your --include tag or remove the --smart-layout option"
351
- end
297
+ @magic_buttons = []
298
+ if options['magic_buttons']
299
+ @magic_buttons = options['magic_buttons'].split(',')
300
+ end
352
301
 
353
- @container_name = @layout_strategy.container_name
354
- @downnest = options['downnest'] || false
355
302
 
356
- @downnest_children = [] # TODO: defactor @downnest_children in favor of downnest_object
357
- @downnest_object = {}
358
- if @downnest
359
- @downnest_children = @downnest.split(",").map{|child| child.gsub("+","")}
360
- @downnest_object = HotGlue.construct_downnest_object(@downnest)
361
- end
303
+ @small_buttons = options['small_buttons'] || false
362
304
 
363
- if @god
364
- @auth = nil
365
- end
305
+ @build_update_action = !@no_edit || !@magic_buttons.empty?
306
+ # if the magic buttons are present, build the update action anyway
366
307
 
367
- # when in self auth, the object is the same as the authenticated object
308
+ @ujs_syntax = options['ujs_syntax']
309
+ if !@ujs_syntax
310
+ @ujs_syntax = !defined?(Turbo::Engine)
311
+ end
368
312
 
369
- if @auth && auth_identifier == @singular
370
- @self_auth = true
371
- end
372
313
 
373
- if @self_auth && !@no_create
374
- raise "This controller appears to be the same as the authentication object but in this context you cannot build a new/create action; please re-run with --no-create flag"
375
- end
314
+ # NEST CHAIN
315
+ # new syntax
316
+ # @nested_set = [
317
+ # {
318
+ # singular: ...,
319
+ # plural: ...,
320
+ # optional: false
321
+ # }]
322
+ @nested_set = []
376
323
 
377
- @magic_buttons = []
378
- if options['magic_buttons']
379
- @magic_buttons = options['magic_buttons'].split(',')
380
- end
324
+ if ! @nested.nil?
325
+ @nested_set = @nested.split("/").collect { |arg|
326
+ is_optional = arg.start_with?("~")
327
+ arg.gsub!("~","")
328
+ {
329
+ singular: arg,
330
+ plural: arg.pluralize,
331
+ optional: is_optional
332
+ }
333
+ }
334
+ puts "NESTING: #{@nested_set}"
335
+ end
381
336
 
337
+ # OBJECT OWNERSHIP & NESTING
338
+ @reference_name = HotGlue.derrive_reference_name(singular_class)
339
+ if @auth && @self_auth
340
+ @object_owner_sym = @auth.gsub("current_", "").to_sym
341
+ @object_owner_eval = @auth
342
+ @object_owner_optional = false
343
+ @object_owner_name = @auth.gsub("current_", "").to_s
382
344
 
383
- @small_buttons = options['small_buttons'] || false
384
345
 
385
- @build_update_action = !@no_edit || !@magic_buttons.empty?
386
- # if the magic buttons are present, build the update action anyway
346
+ elsif @auth && ! @self_auth && @nested_set.none? && !@auth.include?(".")
347
+ @object_owner_sym = @auth.gsub("current_", "").to_sym
348
+ @object_owner_eval = @auth
349
+ @object_owner_optional = false
350
+ @object_owner_name = @auth.gsub("current_", "").to_s
387
351
 
388
- @ujs_syntax = options['ujs_syntax']
389
- if !@ujs_syntax
390
- @ujs_syntax = !defined?(Turbo::Engine)
352
+ elsif @auth && @auth.include?(".")
353
+ @object_owner_sym = nil
354
+ @object_owner_eval = @auth
355
+ else
356
+ if @nested_set.any?
357
+ @object_owner_sym = @nested_set.last[:singular].to_sym
358
+ @object_owner_eval = "@#{@nested_set.last[:singular]}"
359
+ @object_owner_name = @nested_set.last[:singular]
360
+ @object_owner_optional = @nested_set.last[:optional]
361
+ else
362
+ @object_owner_sym = nil
363
+ @object_owner_eval = ""
391
364
  end
365
+ end
392
366
 
393
367
 
394
- # NEST CHAIN
395
- # new syntax
396
- # @nested_set = [
397
- # {
398
- # singular: ...,
399
- # plural: ...,
400
- # optional: false
401
- # }]
402
- @nested_set = []
403
-
404
- if ! @nested.nil?
405
- @nested_set = @nested.split("/").collect { |arg|
406
- is_optional = arg.start_with?("~")
407
- arg.gsub!("~","")
408
- {
409
- singular: arg,
410
- plural: arg.pluralize,
411
- optional: is_optional
412
- }
413
- }
414
- puts "NESTING: #{@nested_set}"
415
- end
416
-
417
- # OBJECT OWNERSHIP & NESTING
418
- @reference_name = HotGlue.derrive_reference_name(singular_class)
419
- if @auth && @self_auth
420
- @object_owner_sym = @auth.gsub("current_", "").to_sym
421
- @object_owner_eval = @auth
422
- @object_owner_optional = false
423
- @object_owner_name = @auth.gsub("current_", "").to_s
368
+ @factory_creation = options['factory_creation'].gsub(";", "\n")
369
+ identify_object_owner
370
+ setup_fields
424
371
 
372
+ if (@columns - @show_only - (@ownership_field ? [@ownership_field.to_sym] : [])).empty?
373
+ @no_field_form = true
374
+ end
425
375
 
426
- elsif @auth && ! @self_auth && @nested_set.none? && !@auth.include?(".")
427
- @object_owner_sym = @auth.gsub("current_", "").to_sym
428
- @object_owner_eval = @auth
429
- @object_owner_optional = false
430
- @object_owner_name = @auth.gsub("current_", "").to_s
376
+ buttons_width = ((!@no_edit && 1) || 0) + ((!@no_delete && 1) || 0) + @magic_buttons.count
431
377
 
432
- elsif @auth && @auth.include?(".")
433
- @object_owner_sym = nil
434
- @object_owner_eval = @auth
435
- else
436
- if @nested_set.any?
437
- @object_owner_sym = @nested_set.last[:singular].to_sym
438
- @object_owner_eval = "@#{@nested_set.last[:singular]}"
439
- @object_owner_name = @nested_set.last[:singular]
440
- @object_owner_optional = @nested_set.last[:optional]
441
- else
442
- @object_owner_sym = nil
443
- @object_owner_eval = ""
444
- end
378
+ # build a new polymorphic object
379
+ @associations = []
380
+ @columns_map = {}
381
+ @columns.each do |col|
382
+ if !(@the_object.columns_hash.keys.include?(col.to_s) || @attachments.keys.include?(col))
383
+ raise "couldn't find #{col} in either field list or attachments list"
445
384
  end
446
385
 
447
-
448
- @factory_creation = options['factory_creation'].gsub(";", "\n")
449
- identify_object_owner
450
- setup_fields
451
-
452
- if (@columns - @show_only - (@ownership_field ? [@ownership_field.to_sym] : [])).empty?
453
- @no_field_form = true
386
+ if col.to_s.starts_with?("_")
387
+ @show_only << col
454
388
  end
455
389
 
456
- buttons_width = ((!@no_edit && 1) || 0) + ((!@no_delete && 1) || 0) + @magic_buttons.count
457
-
458
- builder = HotGlue::Layout::Builder.new(include_setting: options['include'],
459
- downnest_object: @downnest_object,
460
- buttons_width: buttons_width,
461
- columns: @columns,
462
- smart_layout: @smart_layout,
463
- stacked_downnesting: @stacked_downnesting)
464
- @layout_object = builder.construct
465
-
390
+ if @the_object.columns_hash.keys.include?(col.to_s)
391
+ type = @the_object.columns_hash[col.to_s].type
392
+ elsif @attachments.keys.include?(col)
393
+ type = :attachment
394
+ end
395
+ this_column_object = FieldFactory.new(name: col.to_s,
396
+ generator: self,
397
+ type: type)
398
+ field = this_column_object.field
399
+ if field.is_a?(AssociationField)
400
+ @associations << field.assoc_name.to_sym
401
+ end
402
+ @columns_map[col] = this_column_object.field
403
+ end
466
404
 
467
405
 
468
- @menu_file_exists = true if @nested_set.none? && File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
469
406
 
470
- @turbo_streams = !!options['with_turbo_streams']
407
+ # create the template object
408
+ if @markup == "erb"
409
+ @template_builder = HotGlue::ErbTemplate.new(
410
+ layout_strategy: @layout_strategy,
411
+ magic_buttons: @magic_buttons,
412
+ small_buttons: @small_buttons,
413
+ inline_list_labels: @inline_list_labels,
414
+ show_only: @show_only,
415
+ update_show_only: @update_show_only,
416
+ singular_class: singular_class,
417
+ singular: singular,
418
+ hawk_keys: @hawk_keys,
419
+ ownership_field: @ownership_field,
420
+ form_labels_position: @form_labels_position,
421
+ form_placeholder_labels: @form_placeholder_labels,
422
+ alt_lookups: @alt_lookups,
423
+ attachments: @attachments,
424
+ columns_map: @columns_map
425
+ )
426
+ elsif @markup == "slim"
427
+ raise(HotGlue::Error, "SLIM IS NOT IMPLEMENTED")
428
+ elsif @markup == "haml"
429
+ raise(HotGlue::Error, "HAML IS NOT IMPLEMENTED")
471
430
  end
472
431
 
432
+ builder = HotGlue::Layout::Builder.new(generator: self,
433
+ include_setting: options['include'],
434
+ buttons_width: buttons_width )
435
+ @layout_object = builder.construct
473
436
 
474
437
 
475
- def setup_hawk_keys
476
- @hawk_keys = {}
477
438
 
478
- if options["hawk"]
479
- options['hawk'].split(",").each do |hawk_entry|
480
- # format is: abc_id[thing]
439
+ @menu_file_exists = true if @nested_set.none? && File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
481
440
 
482
- if hawk_entry.include?("{")
483
- hawk_entry =~ /(.*){(.*)}/
484
- key, hawk_to = $1, $2
485
- else
486
- key = hawk_entry
487
- hawk_to = @auth
488
- end
441
+ @turbo_streams = !!options['with_turbo_streams']
442
+ end
489
443
 
490
- hawk_scope = key.gsub("_id", "").pluralize
491
- optional = eval(singular_class + ".reflect_on_association(:#{key.gsub('_id','')})").options[:optional]
492
444
 
493
- @hawk_keys[key.to_sym] = {bind_to: [hawk_to], optional: optional}
494
- use_shorthand = !options["hawk"].include?("{")
495
445
 
496
- if use_shorthand # only include the hawk scope if using the shorthand
497
- @hawk_keys[key.to_sym][:bind_to] << hawk_scope
498
- end
499
-
500
- end
446
+ def setup_hawk_keys
447
+ @hawk_keys = {}
501
448
 
502
- puts "HAWKING: #{@hawk_keys}"
503
- end
504
- end
449
+ if options["hawk"]
450
+ options['hawk'].split(",").each do |hawk_entry|
451
+ # format is: abc_id[thing]
505
452
 
453
+ if hawk_entry.include?("{")
454
+ hawk_entry =~ /(.*){(.*)}/
455
+ key, hawk_to = $1, $2
456
+ else
457
+ key = hawk_entry
458
+ hawk_to = @auth
459
+ end
506
460
 
507
- def setup_attachments
508
- @attachments = {}
461
+ hawk_scope = key.gsub("_id", "").pluralize
462
+ optional = eval(singular_class + ".reflect_on_association(:#{key.gsub('_id','')})").options[:optional]
509
463
 
510
- if options["attachments"]
464
+ @hawk_keys[key.to_sym] = {bind_to: [hawk_to], optional: optional}
465
+ use_shorthand = !options["hawk"].include?("{")
511
466
 
512
- options['attachments'].split(",").each do |attachment_entry|
513
- # format is: avatar{thumbnail|field_for_original_filename}
467
+ if use_shorthand # only include the hawk scope if using the shorthand
468
+ @hawk_keys[key.to_sym][:bind_to] << hawk_scope
469
+ end
514
470
 
515
- if attachment_entry.include?("{")
516
- num_params = attachment_entry.split("|").count
517
- if num_params == 1
518
- attachment_entry =~ /(.*){(.*)}/
519
- key, thumbnail = $1, $2
520
- elsif num_params == 2
521
- attachment_entry =~ /(.*){(.*)\|(.*)}/
522
- key, thumbnail, field_for_original_filename = $1, $2, $3
523
- elsif num_params > 2
524
- if num_params == 3
525
- attachment_entry =~ /(.*){(.*)\|(.*)\|(.*)}/
526
- key, thumbnail, field_for_original_filename, direct_upload = $1, $2, $3, $4
527
- elsif num_params > 3
528
- attachment_entry =~ /(.*){(.*)\|(.*)\|(.*)\|(.*)}/
529
- key, thumbnail, field_for_original_filename, direct_upload, dropzone = $1, $2, $3, $4, $5
530
- end
471
+ end
531
472
 
532
- field_for_original_filename = nil if field_for_original_filename == ""
473
+ puts "HAWKING: #{@hawk_keys}"
474
+ end
475
+ end
533
476
 
534
- if thumbnail == ''
535
- thumbnail = nil
536
- end
537
477
 
538
- if !direct_upload.nil? && direct_upload != "direct"
539
- raise HotGlue::Error, "received 3rd parameter in attachment long form specification that was not 'direct'; for direct uploads, just use 'direct' or leave off to disable"
540
- end
478
+ def setup_attachments
479
+ @attachments = {}
480
+
481
+ if options["attachments"]
482
+
483
+ options['attachments'].split(",").each do |attachment_entry|
484
+ # format is: avatar{thumbnail|field_for_original_filename}
485
+
486
+ if attachment_entry.include?("{")
487
+ num_params = attachment_entry.split("|").count
488
+ if num_params == 1
489
+ attachment_entry =~ /(.*){(.*)}/
490
+ key, thumbnail = $1, $2
491
+ elsif num_params == 2
492
+ attachment_entry =~ /(.*){(.*)\|(.*)}/
493
+ key, thumbnail, field_for_original_filename = $1, $2, $3
494
+ elsif num_params > 2
495
+ if num_params == 3
496
+ attachment_entry =~ /(.*){(.*)\|(.*)\|(.*)}/
497
+ key, thumbnail, field_for_original_filename, direct_upload = $1, $2, $3, $4
498
+ elsif num_params > 3
499
+ attachment_entry =~ /(.*){(.*)\|(.*)\|(.*)\|(.*)}/
500
+ key, thumbnail, field_for_original_filename, direct_upload, dropzone = $1, $2, $3, $4, $5
501
+ end
541
502
 
542
- if !dropzone.nil? && dropzone != "dropzone"
543
- raise HotGlue::Error, "received 4th parameter in attachme long form specification that was not 'dropzone'; for dropzone, just use 'dropzone' or leave off to disable"
544
- end
503
+ field_for_original_filename = nil if field_for_original_filename == ""
545
504
 
546
- if dropzone && !direct_upload
547
- raise HotGlue::Error, "dropzone requires direct_upload"
548
- end
505
+ if thumbnail == ''
506
+ thumbnail = nil
507
+ end
549
508
 
550
- if field_for_original_filename && direct_upload
551
- raise HotGlue::Error, "Unfortunately orig filename extraction doesn't work with direct upload; please set 2nd parameter to empty string to disable"
552
- end
509
+ if !direct_upload.nil? && direct_upload != "direct"
510
+ raise HotGlue::Error, "received 3rd parameter in attachment long form specification that was not 'direct'; for direct uploads, just use 'direct' or leave off to disable"
511
+ end
553
512
 
554
- direct_upload = !!direct_upload
555
- dropzone = !!dropzone
513
+ if !dropzone.nil? && dropzone != "dropzone"
514
+ raise HotGlue::Error, "received 4th parameter in attachme long form specification that was not 'dropzone'; for dropzone, just use 'dropzone' or leave off to disable"
556
515
  end
557
- else
558
- key = attachment_entry
559
516
 
560
- if !(eval("#{singular_class}.reflect_on_attachment(:#{attachment_entry})"))
561
- raise HotGlue::Error, "Could not find #{attachment_entry} attachment on #{singular_class}"
517
+ if dropzone && !direct_upload
518
+ raise HotGlue::Error, "dropzone requires direct_upload"
562
519
  end
563
- if eval("#{singular_class}.reflect_on_attachment(:#{attachment_entry}).variants.include?(:thumb)")
564
- thumbnail = "thumb"
565
- else
566
- thumbnail = nil
520
+
521
+ if field_for_original_filename && direct_upload
522
+ raise HotGlue::Error, "Unfortunately orig filename extraction doesn't work with direct upload; please set 2nd parameter to empty string to disable"
567
523
  end
568
524
 
569
- direct_upload = nil
570
- field_for_original_filename = nil
571
- dropzone = nil
525
+ direct_upload = !!direct_upload
526
+ dropzone = !!dropzone
527
+ end
528
+ else
529
+ key = attachment_entry
530
+
531
+ if !(eval("#{singular_class}.reflect_on_attachment(:#{attachment_entry})"))
532
+ raise HotGlue::Error, "Could not find #{attachment_entry} attachment on #{singular_class}"
533
+ end
534
+ if eval("#{singular_class}.reflect_on_attachment(:#{attachment_entry}).variants.include?(:thumb)")
535
+ thumbnail = "thumb"
536
+ else
537
+ thumbnail = nil
572
538
  end
573
539
 
574
- if thumbnail && !eval("#{singular_class}.reflect_on_attachment(:#{key}).variants.include?(:#{thumbnail})")
575
- raise HotGlue::Error, "you specified to use #{thumbnail} as the thumbnail but could not find any such variant on the #{key} attachment; add to your #{singular}.rb file:
540
+ direct_upload = nil
541
+ field_for_original_filename = nil
542
+ dropzone = nil
543
+ end
544
+
545
+ if thumbnail && !eval("#{singular_class}.reflect_on_attachment(:#{key}).variants.include?(:#{thumbnail})")
546
+ raise HotGlue::Error, "you specified to use #{thumbnail} as the thumbnail but could not find any such variant on the #{key} attachment; add to your #{singular}.rb file:
576
547
  has_one_attached :#{key} do |attachable|
577
548
  attachable.variant :#{thumbnail}, resize_to_limit: [100, 100]
578
549
  end
579
550
  "
580
- end
581
-
582
-
583
- @attachments[key.to_sym] = {thumbnail: thumbnail,
584
- field_for_original_filename: field_for_original_filename,
585
- direct_upload: direct_upload,
586
- dropzone: dropzone}
587
551
  end
588
552
 
589
- puts "ATTACHMENTS: #{@attachments}"
553
+
554
+ @attachments[key.to_sym] = {thumbnail: thumbnail,
555
+ field_for_original_filename: field_for_original_filename,
556
+ direct_upload: direct_upload,
557
+ dropzone: dropzone}
590
558
  end
559
+
560
+ puts "ATTACHMENTS: #{@attachments}"
591
561
  end
562
+ end
592
563
 
593
- def identify_object_owner
594
- auth_assoc = @auth && @auth.gsub("current_","")
564
+ def identify_object_owner
565
+ auth_assoc = @auth && @auth.gsub("current_","")
595
566
 
596
- if @object_owner_sym && ! @self_auth
597
- auth_assoc_field = auth_assoc + "_id" unless @god
598
- assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
567
+ if @object_owner_sym && ! @self_auth
568
+ auth_assoc_field = auth_assoc + "_id" unless @god
569
+ assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
599
570
 
600
- if assoc
601
- @ownership_field = assoc.name.to_s + "_id"
602
- elsif ! @nested_set.any?
603
- exit_message = "*** Oops: It looks like is no association `#{@object_owner_sym}` from the object #{@singular_class}. If your user is called something else, pass with flag auth=current_X where X is the model for your users as lowercase. Also, be sure to implement current_X as a method on your controller. (If you really don't want to implement a current_X on your controller and want me to check some other method for your current user, see the section in the docs for auth_identifier.) To make a controller that can read all records, specify with --god."
604
- raise(HotGlue::Error, exit_message)
571
+ if assoc
572
+ @ownership_field = assoc.name.to_s + "_id"
573
+ elsif ! @nested_set.any?
574
+ exit_message = "*** Oops: It looks like is no association `#{@object_owner_sym}` from the object #{@singular_class}. If your user is called something else, pass with flag auth=current_X where X is the model for your users as lowercase. Also, be sure to implement current_X as a method on your controller. (If you really don't want to implement a current_X on your controller and want me to check some other method for your current user, see the section in the docs for auth_identifier.) To make a controller that can read all records, specify with --god."
575
+ raise(HotGlue::Error, exit_message)
605
576
 
606
- else
607
- if eval(singular_class + ".reflect_on_association(:#{@object_owner_sym.to_s})").nil? && !eval(singular_class + ".reflect_on_association(:#{@object_owner_sym.to_s.singularize})").nil?
608
- exit_message = "*** Oops: you tried to nest #{singular_class} within a route for `#{@object_owner_sym}` but I can't find an association for this relationship. Did you mean `#{@object_owner_sym.to_s.singularize}` (singular) instead?"
577
+ else
578
+ if eval(singular_class + ".reflect_on_association(:#{@object_owner_sym.to_s})").nil? && !eval(singular_class + ".reflect_on_association(:#{@object_owner_sym.to_s.singularize})").nil?
579
+ exit_message = "*** Oops: you tried to nest #{singular_class} within a route for `#{@object_owner_sym}` but I can't find an association for this relationship. Did you mean `#{@object_owner_sym.to_s.singularize}` (singular) instead?"
609
580
  # else # NOTE: not reachable
610
581
  # exit_message = "*** Oops: Missing relationship from class #{singular_class} to :#{@object_owner_sym} maybe add `belongs_to :#{@object_owner_sym}` to #{singular_class}\n (If your user is called something else, pass with flag auth=current_X where X is the model for your auth object as lowercase. Also, be sure to implement current_X as a method on your controller. If you really don't want to implement a current_X on your controller and want me to check some other method for your current user, see the section in the docs for --auth-identifier flag). To make a controller that can read all records, specify with --god."
611
- end
612
-
613
- raise(HotGlue::Error, exit_message)
614
582
  end
615
- elsif @object_owner_sym && ! @object_owner_eval.include?(".")
616
- @ownership_field = @object_owner_name + "_id"
583
+
584
+ raise(HotGlue::Error, exit_message)
617
585
  end
586
+ elsif @object_owner_sym && ! @object_owner_eval.include?(".")
587
+ @ownership_field = @object_owner_name + "_id"
618
588
  end
589
+ end
619
590
 
620
- def setup_fields
621
- if !@include_fields
622
- @exclude_fields.push :id, :created_at, :updated_at, :encrypted_password,
623
- :reset_password_token,
624
- :reset_password_sent_at, :remember_created_at,
625
- :confirmation_token, :confirmed_at,
626
- :confirmation_sent_at, :unconfirmed_email
627
-
628
- @exclude_fields.push( @ownership_field.to_sym ) if ! @ownership_field.nil?
591
+ def setup_fields
592
+ if !@include_fields
593
+ @exclude_fields.push :id, :created_at, :updated_at, :encrypted_password,
594
+ :reset_password_token,
595
+ :reset_password_sent_at, :remember_created_at,
596
+ :confirmation_token, :confirmed_at,
597
+ :confirmation_sent_at, :unconfirmed_email
629
598
 
599
+ @exclude_fields.push( @ownership_field.to_sym ) if ! @ownership_field.nil?
630
600
 
631
- @columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| @exclude_fields.include?(field) }
632
601
 
602
+ @columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| @exclude_fields.include?(field) }
633
603
 
634
- else
635
- @columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| !@include_fields.include?(field) }
636
- end
637
604
 
638
- if @attachments.any?
639
- puts "adding attachments-as-columns: #{@attachments}"
640
- @attachments.keys.each do |attachment|
641
- @columns << attachment if !@columns.include?(attachment)
642
- end
605
+ else
606
+ @columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| !@include_fields.include?(field) }
607
+ end
643
608
 
644
- check_if_sample_file_is_present
609
+ if @attachments.any?
610
+ puts "adding attachments-as-columns: #{@attachments}"
611
+ @attachments.keys.each do |attachment|
612
+ @columns << attachment if !@columns.include?(attachment)
645
613
  end
646
614
 
615
+ check_if_sample_file_is_present
616
+ end
617
+ end
647
618
 
648
- # build a new polymorphic object
649
- @associations = []
650
- @columns_map = {}
651
- @columns.each do |col|
652
- if !(@the_object.columns_hash.keys.include?(col.to_s) || @attachments.keys.include?(col))
653
- raise "couldn't find #{col} in either field list or attachments list"
654
- end
655
-
656
- if col.to_s.starts_with?("_")
657
- @show_only << col
658
- end
659
-
660
- if @the_object.columns_hash.keys.include?(col.to_s)
661
- type = @the_object.columns_hash[col.to_s].type
662
- elsif @attachments.keys.include?(col)
663
- type = :attachment
664
- end
665
- this_column_object = FieldFactory.new(name: col.to_s,
666
- generator: self,
667
- type: type)
668
- field = this_column_object.field
669
- if field.is_a?(AssociationField)
670
- @associations << field.assoc_name.to_sym
671
- end
672
- @columns_map[col] = this_column_object.field
673
619
 
674
620
 
675
621
 
676
- end
677
- end
678
-
679
622
 
680
- def check_if_sample_file_is_present
681
- if sample_file_path.nil?
682
- puts "you have no sample file path set in config/hot_glue.yml"
683
- settings = File.read("config/hot_glue.yml")
684
- @sample_file_path = "spec/files/computer_code.jpg"
685
- added_setting = ":sample_file_path: #{sample_file_path}"
686
- File.open("config/hot_glue.yml", "w") { |f| f.write settings + "\n" + added_setting }
687
623
 
688
- puts "adding `#{added_setting}` to config/hot_glue.yml"
689
- elsif ! File.exist?(sample_file_path)
690
- puts "NO SAMPLE FILE FOUND: adding sample file at #{sample_file_path}"
691
- template "computer_code.jpg", File.join("#{filepath_prefix}spec/files/", "computer_code.jpg")
692
- end
624
+ def check_if_sample_file_is_present
625
+ if sample_file_path.nil?
626
+ puts "you have no sample file path set in config/hot_glue.yml"
627
+ settings = File.read("config/hot_glue.yml")
628
+ @sample_file_path = "spec/files/computer_code.jpg"
629
+ added_setting = ":sample_file_path: #{sample_file_path}"
630
+ File.open("config/hot_glue.yml", "w") { |f| f.write settings + "\n" + added_setting }
693
631
 
694
- puts ""
632
+ puts "adding `#{added_setting}` to config/hot_glue.yml"
633
+ elsif ! File.exist?(sample_file_path)
634
+ puts "NO SAMPLE FILE FOUND: adding sample file at #{sample_file_path}"
635
+ template "computer_code.jpg", File.join("#{filepath_prefix}spec/files/", "computer_code.jpg")
695
636
  end
696
637
 
697
- def fields_filtered_for_email_lookups
698
- @columns.reject{|c| @alt_lookups.keys.include?(c) } + @alt_lookups.values.map{|v| ("__lookup_#{v[:lookup_as]}").to_sym}
699
- end
638
+ puts ""
639
+ end
700
640
 
701
- def creation_syntax
702
- merge_with = @alt_lookups.collect{ |key, data|
703
- "#{data[:assoc].downcase}: #{data[:assoc].downcase}_factory.#{data[:assoc].downcase}"
704
- }.join(", ")
641
+ def fields_filtered_for_email_lookups
642
+ @columns.reject{|c| @alt_lookups.keys.include?(c) } + @alt_lookups.values.map{|v| ("__lookup_#{v[:lookup_as]}").to_sym}
643
+ end
705
644
 
706
- if @factory_creation == ''
707
- "@#{singular } = #{ class_name }.create(modified_params)"
708
- else
709
- "#{@factory_creation}\n" +
710
- " @#{singular } = #{ class_name }.create(modified_params#{'.merge(' + merge_with + ')' if !merge_with.empty?})"
711
- end
712
- end
645
+ def creation_syntax
646
+ merge_with = @alt_lookups.collect{ |key, data|
647
+ "#{data[:assoc].downcase}: #{data[:assoc].downcase}_factory.#{data[:assoc].downcase}"
648
+ }.join(", ")
713
649
 
714
- def auth_root
715
- "authenticate_" + @auth_identifier.split(".")[0] + "!"
650
+ if @factory_creation == ''
651
+ "@#{singular } = #{ class_name }.create(modified_params)"
652
+ else
653
+ "#{@factory_creation}\n" +
654
+ " @#{singular } = #{ class_name }.create(modified_params#{'.merge(' + merge_with + ')' if !merge_with.empty?})"
716
655
  end
656
+ end
717
657
 
718
- def formats
719
- [format]
720
- end
658
+ def auth_root
659
+ "authenticate_" + @auth_identifier.split(".")[0] + "!"
660
+ end
721
661
 
722
- def format
723
- nil
724
- end
662
+ def formats
663
+ [format]
664
+ end
725
665
 
726
- def filepath_prefix
727
- 'spec/dummy/' if Rails.env.test?
728
- end
666
+ def format
667
+ nil
668
+ end
729
669
 
730
- def copy_controller_and_spec_files
731
- @default_colspan = @columns.size
732
- unless @specs_only
733
- template "controller.rb.erb", File.join("#{filepath_prefix}app/controllers#{namespace_with_dash}", "#{@controller_build_folder}_controller.rb")
734
- if @namespace
735
- begin
736
- eval(controller_descends_from)
737
- rescue NameError => e
738
- template "base_controller.rb.erb", File.join("#{filepath_prefix}app/controllers#{namespace_with_dash}", "base_controller.rb")
739
- end
670
+ def filepath_prefix
671
+ 'spec/dummy/' if Rails.env.test?
672
+ end
673
+
674
+ def copy_controller_and_spec_files
675
+ @default_colspan = @columns.size
676
+ unless @specs_only
677
+ template "controller.rb.erb", File.join("#{filepath_prefix}app/controllers#{namespace_with_dash}", "#{@controller_build_folder}_controller.rb")
678
+ if @namespace
679
+ begin
680
+ eval(controller_descends_from)
681
+ rescue NameError => e
682
+ template "base_controller.rb.erb", File.join("#{filepath_prefix}app/controllers#{namespace_with_dash}", "base_controller.rb")
740
683
  end
741
684
  end
685
+ end
742
686
 
743
- unless @no_specs
744
- dest_file = File.join("#{filepath_prefix}spec/features#{namespace_with_dash}", "#{plural}_behavior_spec.rb")
745
-
746
- if File.exist?(dest_file)
747
- existing_file = File.open(dest_file)
748
- existing_content = existing_file.read
749
- if existing_content =~ /\#HOTGLUE-SAVESTART/
750
- if existing_content !~ /\#HOTGLUE-END/
751
- raise "Your file at #{dest_file} contains a #HOTGLUE-SAVESTART marker without #HOTGLUE-END"
752
- end
753
- @existing_content = existing_content[(existing_content =~ /\#HOTGLUE-SAVESTART/) .. (existing_content =~ /\#HOTGLUE-END/)-1]
754
- @existing_content << "#HOTGLUE-END"
687
+ unless @no_specs
688
+ dest_file = File.join("#{filepath_prefix}spec/features#{namespace_with_dash}", "#{plural}_behavior_spec.rb")
755
689
 
690
+ if File.exist?(dest_file)
691
+ existing_file = File.open(dest_file)
692
+ existing_content = existing_file.read
693
+ if existing_content =~ /\#HOTGLUE-SAVESTART/
694
+ if existing_content !~ /\#HOTGLUE-END/
695
+ raise "Your file at #{dest_file} contains a #HOTGLUE-SAVESTART marker without #HOTGLUE-END"
756
696
  end
757
- existing_file.rewind
758
- else
759
- @existing_content = " #HOTGLUE-SAVESTART\n #HOTGLUE-END"
760
- end
697
+ @existing_content = existing_content[(existing_content =~ /\#HOTGLUE-SAVESTART/) .. (existing_content =~ /\#HOTGLUE-END/)-1]
698
+ @existing_content << "#HOTGLUE-END"
761
699
 
762
-
763
- template "system_spec.rb.erb", dest_file
700
+ end
701
+ existing_file.rewind
702
+ else
703
+ @existing_content = " #HOTGLUE-SAVESTART\n #HOTGLUE-END"
764
704
  end
765
705
 
766
- template "#{@markup}/_errors.#{@markup}", File.join("#{filepath_prefix}app/views#{namespace_with_dash}", "_errors.#{@markup}")
767
- end
768
-
769
- def spec_foreign_association_merge_hash
770
- ", #{testing_name}: #{testing_name}1"
771
- end
772
706
 
773
- def testing_name
774
- singular_class.gsub("::","_").underscore
707
+ template "system_spec.rb.erb", dest_file
775
708
  end
776
709
 
777
- def spec_related_column_lets
778
- @columns_map.collect { |col, col_object|
779
- col_object.spec_related_column_lets
780
- }.join("\n")
781
- end
710
+ template "#{@markup}/_errors.#{@markup}", File.join("#{filepath_prefix}app/views#{namespace_with_dash}", "_errors.#{@markup}")
711
+ end
782
712
 
783
- def list_column_headings
784
- @template_builder.list_column_headings(
785
- layout_object: @layout_object,
786
- col_identifier: @layout_strategy.column_classes_for_column_headings,
787
- column_width: @layout_strategy.column_width,
788
- singular: @singular
789
- )
790
- end
713
+ def spec_foreign_association_merge_hash
714
+ ", #{testing_name}: #{testing_name}1"
715
+ end
791
716
 
792
- def columns_spec_with_sample_data
793
- @columns_map.map { |col, col_object|
794
- unless col_object.is_a?(AssociationField)
795
- random_data = col_object.spec_random_data
796
- col.to_s + ": '" + random_data.to_s + "'"
797
- end
798
- }.join(", ")
799
- end
717
+ def testing_name
718
+ singular_class.gsub("::","_").underscore
719
+ end
800
720
 
801
- def regenerate_me_code
802
- "rails generate hot_glue:scaffold #{ @meta_args[0][0] } #{@meta_args[1].collect{|x| x.gsub(/\s*=\s*([\S\s]+)/, '=\'\1\'')}.join(" ")}"
803
- end
721
+ def spec_related_column_lets
722
+ @columns_map.collect { |col, col_object|
723
+ col_object.spec_related_column_lets
724
+ }.join("\n")
725
+ end
804
726
 
805
- def object_parent_mapping_as_argument_for_specs
727
+ def list_column_headings
728
+ @template_builder.list_column_headings(
729
+ layout_object: @layout_object,
730
+ col_identifier: @layout_strategy.column_classes_for_column_headings,
731
+ column_width: @layout_strategy.column_width,
732
+ singular: @singular
733
+ )
734
+ end
806
735
 
807
- if @self_auth
808
- ""
809
- elsif @nested_set.any? && ! @nested_set.last[:optional]
810
- ", " + @nested_set.last[:singular] + ": " + @nested_set.last[:singular]
811
- elsif @auth && !@god
812
- ", #{@auth_identifier}: #{@auth}"
736
+ def columns_spec_with_sample_data
737
+ @columns_map.map { |col, col_object|
738
+ unless col_object.is_a?(AssociationField)
739
+ random_data = col_object.spec_random_data
740
+ col.to_s + ": '" + random_data.to_s + "'"
813
741
  end
814
- end
742
+ }.join(", ")
743
+ end
815
744
 
816
- def objest_nest_factory_setup
817
- res = ""
818
- if @auth
819
- last_parent = ", #{@auth_identifier}: #{@auth}"
820
- end
745
+ def regenerate_me_code
746
+ "rails generate hot_glue:scaffold #{ @meta_args[0][0] } #{@meta_args[1].collect{|x| x.gsub(/\s*=\s*([\S\s]+)/, '=\'\1\'')}.join(" ")}"
747
+ end
821
748
 
822
- @nested_set.each do |arg|
823
- res << " let(:#{arg[:singular]}) {create(:#{arg[:singular]} #{last_parent} )}\n"
824
- last_parent = ", #{arg[:singular]}: #{arg[:singular]}"
825
- end
826
- res
827
- end
749
+ def object_parent_mapping_as_argument_for_specs
828
750
 
829
- def objest_nest_params_by_id_for_specs
830
- @nested_set.map{|arg|
831
- "#{arg[:singular]}_id: #{arg[:singular]}.id"
832
- }.join(",\n ")
751
+ if @self_auth
752
+ ""
753
+ elsif @nested_set.any? && ! @nested_set.last[:optional]
754
+ ", " + @nested_set.last[:singular] + ": " + @nested_set.last[:singular]
755
+ elsif @auth && !@god
756
+ ", #{@auth_identifier}: #{@auth}"
833
757
  end
758
+ end
834
759
 
835
- def controller_class_name
836
- @controller_build_name
760
+ def objest_nest_factory_setup
761
+ res = ""
762
+ if @auth
763
+ last_parent = ", #{@auth_identifier}: #{@auth}"
837
764
  end
838
765
 
839
- def plural_name
840
- plural
766
+ @nested_set.each do |arg|
767
+ res << " let(:#{arg[:singular]}) {create(:#{arg[:singular]} #{last_parent} )}\n"
768
+ last_parent = ", #{arg[:singular]}: #{arg[:singular]}"
841
769
  end
770
+ res
771
+ end
842
772
 
843
- def auth_identifier
844
- @auth_identifier
845
- end
773
+ def objest_nest_params_by_id_for_specs
774
+ @nested_set.map{|arg|
775
+ "#{arg[:singular]}_id: #{arg[:singular]}.id"
776
+ }.join(",\n ")
777
+ end
846
778
 
847
- def capybara_make_updates(which_partial = :create)
848
- @columns_map.map { | col, col_obj|
849
- show_only_list = which_partial == :create ? @show_only : (@update_show_only+@show_only)
779
+ def controller_class_name
780
+ @controller_build_name
781
+ end
850
782
 
851
- if show_only_list.include?(col)
852
- " page.should have_no_selector(:css, \"[name='#{testing_name}[#{ col.to_s }]'\")"
853
- else
854
- col_obj.spec_setup_and_change_act(which_partial)
855
- end
856
- }.join("\n")
857
- end
783
+ def plural_name
784
+ plural
785
+ end
858
786
 
859
- def path_helper_args
860
- if @nested_set.any? && @nested
861
- [(@nested_set).collect{|a| "#{a[:singular]}"} , singular].join(",")
862
- else
863
- singular
864
- end
865
- end
787
+ def auth_identifier
788
+ @auth_identifier
789
+ end
790
+
791
+ def capybara_make_updates(which_partial = :create)
792
+ @columns_map.map { | col, col_obj|
793
+ show_only_list = which_partial == :create ? @show_only : (@update_show_only+@show_only)
866
794
 
867
- def path_helper_singular
868
- if @nested
869
- "#{@namespace+"_" if @namespace}#{(@nested_set.collect{|x| x[:singular]}.join("_") + "_" if @nested_set.any?)}#{@controller_build_folder_singular}_path"
795
+ if show_only_list.include?(col)
796
+ " page.should have_no_selector(:css, \"[name='#{testing_name}[#{ col.to_s }]'\")"
870
797
  else
871
- "#{@namespace+"_" if @namespace}#{@controller_build_folder_singular}_path"
798
+ col_obj.spec_setup_and_change_act(which_partial)
872
799
  end
873
- end
800
+ }.join("\n")
801
+ end
874
802
 
875
- def path_helper_plural
876
- HotGlue.optionalized_ternary(namespace: @namespace,
877
- target: @controller_build_folder,
878
- nested_set: @nested_set)
803
+ def path_helper_args
804
+ if @nested_set.any? && @nested
805
+ [(@nested_set).collect{|a| "#{a[:singular]}"} , singular].join(",")
806
+ else
807
+ singular
879
808
  end
809
+ end
880
810
 
881
- def form_path_new_helper
882
- HotGlue.optionalized_ternary(namespace: @namespace,
883
- target: @controller_build_folder,
884
- nested_set: @nested_set,
885
- with_params: true,
886
- top_level: false)
811
+ def path_helper_singular
812
+ if @nested
813
+ "#{@namespace+"_" if @namespace}#{(@nested_set.collect{|x| x[:singular]}.join("_") + "_" if @nested_set.any?)}#{@controller_build_folder_singular}_path"
814
+ else
815
+ "#{@namespace+"_" if @namespace}#{@controller_build_folder_singular}_path"
887
816
  end
817
+ end
888
818
 
889
- def form_path_edit_helper
890
- HotGlue.optionalized_ternary(namespace: @namespace,
891
- target: @singular,
892
- nested_set: @nested_set,
893
- with_params: true,
894
- put_form: true,
895
- top_level: true)
896
- end
819
+ def path_helper_plural
820
+ HotGlue.optionalized_ternary(namespace: @namespace,
821
+ target: @controller_build_folder,
822
+ nested_set: @nested_set)
823
+ end
897
824
 
825
+ def form_path_new_helper
826
+ HotGlue.optionalized_ternary(namespace: @namespace,
827
+ target: @controller_build_folder,
828
+ nested_set: @nested_set,
829
+ with_params: true,
830
+ top_level: false)
831
+ end
898
832
 
899
- def delete_path_helper
900
- HotGlue.optionalized_ternary(namespace: @namespace,
901
- target: @singular,
902
- nested_set: @nested_set,
903
- with_params: true,
904
- put_form: true)
905
- end
833
+ def form_path_edit_helper
834
+ HotGlue.optionalized_ternary(namespace: @namespace,
835
+ target: @singular,
836
+ nested_set: @nested_set,
837
+ with_params: true,
838
+ put_form: true,
839
+ top_level: true)
840
+ end
906
841
 
907
- def edit_path_helper
908
- HotGlue.optionalized_ternary(namespace: @namespace,
909
- target: @singular,
910
- nested_set: @nested_set,
911
- modifier: "edit_",
912
- with_params: true,
913
- put_form: true)
914
- end
915
842
 
916
- def path_arity
917
- res = ""
918
- if @nested_set.any? && @nested
919
- res << nested_objects_arity + ", "
920
- end
921
- res << "@" + singular
922
- end
843
+ def delete_path_helper
844
+ HotGlue.optionalized_ternary(namespace: @namespace,
845
+ target: @singular,
846
+ nested_set: @nested_set,
847
+ with_params: true,
848
+ put_form: true)
849
+ end
923
850
 
924
- def line_path_partial
925
- "#{@namespace+"/" if @namespace}#{@controller_build_folder}/line"
926
- end
851
+ def edit_path_helper
852
+ HotGlue.optionalized_ternary(namespace: @namespace,
853
+ target: @singular,
854
+ nested_set: @nested_set,
855
+ modifier: "edit_",
856
+ with_params: true,
857
+ put_form: true)
858
+ end
927
859
 
928
- def show_path_partial
929
- "#{@namespace+"/" if @namespace}#{@controller_build_folder}/show"
860
+ def path_arity
861
+ res = ""
862
+ if @nested_set.any? && @nested
863
+ res << nested_objects_arity + ", "
930
864
  end
865
+ res << "@" + singular
866
+ end
931
867
 
932
- def list_path_partial
933
- "#{@namespace+"/" if @namespace}#{@controller_build_folder}/list"
934
- end
868
+ def line_path_partial
869
+ "#{@namespace+"/" if @namespace}#{@controller_build_folder}/line"
870
+ end
935
871
 
936
- def new_path_name
937
- HotGlue.optionalized_ternary(namespace: @namespace,
938
- target: singular,
939
- nested_set: @nested_set,
940
- modifier: "new_",
941
- with_params: true)
942
- end
872
+ def show_path_partial
873
+ "#{@namespace+"/" if @namespace}#{@controller_build_folder}/show"
874
+ end
943
875
 
944
- def nested_assignments
945
- return "" if @nested_set.none?
946
- @nested_set.map{|a| "#{a}: #{a}"}.join(", ") #metaprgramming into Ruby hash
947
- end
876
+ def list_path_partial
877
+ "#{@namespace+"/" if @namespace}#{@controller_build_folder}/list"
878
+ end
948
879
 
949
- def nested_assignments_top_level # this is by accessing the instance variable-- only use at top level
950
- @nested_set.map{|a| "#{a[:singular]}"}.join(", ") #metaprgramming into Ruby hash
951
- end
880
+ def new_path_name
881
+ HotGlue.optionalized_ternary(namespace: @namespace,
882
+ target: singular,
883
+ nested_set: @nested_set,
884
+ modifier: "new_",
885
+ with_params: true)
886
+ end
952
887
 
953
- def nest_assignments_operator(top_level = false, leading_comma = false)
954
- if @nested_set.any?
955
- "#{", " if leading_comma}#{top_level ? nested_assignments_top_level : nested_assignments }"
956
- else
957
- ""
958
- end
959
- end
888
+ def nested_assignments
889
+ return "" if @nested_set.none?
890
+ @nested_set.map{|a| "#{a}: #{a}"}.join(", ") #metaprgramming into Ruby hash
891
+ end
960
892
 
961
- def nested_assignments_with_leading_comma
962
- nest_assignments_operator(false, true)
963
- end
893
+ def nested_assignments_top_level # this is by accessing the instance variable-- only use at top level
894
+ @nested_set.map{|a| "#{a[:singular]}"}.join(", ") #metaprgramming into Ruby hash
895
+ end
964
896
 
965
- def nested_objects_arity
966
- @nested_set.map{|a| "@#{a[:singular]}"}.join(", ")
897
+ def nest_assignments_operator(top_level = false, leading_comma = false)
898
+ if @nested_set.any?
899
+ "#{", " if leading_comma}#{top_level ? nested_assignments_top_level : nested_assignments }"
900
+ else
901
+ ""
967
902
  end
903
+ end
968
904
 
969
- def nested_arity_for_path
970
- [@nested_set[0..-1].collect{|a| "@#{a[:singular]}"}].join(", ") #metaprgramming into arity for the Rails path helper
971
- end
905
+ def nested_assignments_with_leading_comma
906
+ nest_assignments_operator(false, true)
907
+ end
972
908
 
973
- def object_scope
974
- if @auth
975
- if @nested_set.none?
976
- @auth + ".#{plural}"
977
- else
978
- "@" + @nested_set.last[:singular] + ".#{plural}"
979
- end
909
+ def nested_objects_arity
910
+ @nested_set.map{|a| "@#{a[:singular]}"}.join(", ")
911
+ end
912
+
913
+ def nested_arity_for_path
914
+ [@nested_set[0..-1].collect{|a| "@#{a[:singular]}"}].join(", ") #metaprgramming into arity for the Rails path helper
915
+ end
916
+
917
+ def object_scope
918
+ if @auth
919
+ if @nested_set.none?
920
+ @auth + ".#{plural}"
980
921
  else
981
- if @nested_set.none?
982
- @singular_class
983
- else
984
- "@" + @nested_set.last[:singular] + ".#{plural}"
985
- end
922
+ "@" + @nested_set.last[:singular] + ".#{plural}"
923
+ end
924
+ else
925
+ if @nested_set.none?
926
+ @singular_class
927
+ else
928
+ "@" + @nested_set.last[:singular] + ".#{plural}"
986
929
  end
987
930
  end
931
+ end
988
932
 
989
- def all_objects_root
990
- if @auth
991
- if @self_auth
992
- @singular_class + ".where(id: #{@auth}.id)"
993
- elsif @nested_set.none?
994
- @auth + ".#{plural}"
995
- else
996
- "@" + @nested_set.last[:singular] + ".#{plural}"
997
- end
933
+ def all_objects_root
934
+ if @auth
935
+ if @self_auth
936
+ @singular_class + ".where(id: #{@auth}.id)"
937
+ elsif @nested_set.none?
938
+ @auth + ".#{plural}"
998
939
  else
999
- @singular_class + ".all"
940
+ "@" + @nested_set.last[:singular] + ".#{plural}"
1000
941
  end
942
+ else
943
+ @singular_class + ".all"
1001
944
  end
945
+ end
1002
946
 
1003
- def any_nested?
1004
- @nested_set.any?
1005
- end
947
+ def any_nested?
948
+ @nested_set.any?
949
+ end
1006
950
 
1007
- def all_objects_variable
1008
- all_objects_root + ".page(params[:page])"
1009
- end
951
+ def all_objects_variable
952
+ all_objects_root + ".page(params[:page])"
953
+ end
1010
954
 
1011
- def auth_object
1012
- @auth
1013
- end
955
+ def auth_object
956
+ @auth
957
+ end
1014
958
 
1015
- def no_devise_installed
1016
- !Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.group_by{ |g| g.name }['devise']
1017
- end
959
+ def no_devise_installed
960
+ !Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.group_by{ |g| g.name }['devise']
961
+ end
1018
962
 
1019
- def magic_button_output
1020
- @template_builder.magic_button_output(
1021
- path: HotGlue.optionalized_ternary(namespace: @namespace,
1022
- target: @singular,
1023
- nested_set: @nested_set,
1024
- with_params: true,
1025
- put_form: true),
1026
- singular: singular,
1027
- magic_buttons: @magic_buttons,
1028
- small_buttons: @small_buttons
1029
- )
1030
- end
963
+ def magic_button_output
964
+ @template_builder.magic_button_output(
965
+ path: HotGlue.optionalized_ternary(namespace: @namespace,
966
+ target: @singular,
967
+ nested_set: @nested_set,
968
+ with_params: true,
969
+ put_form: true),
970
+ singular: singular,
971
+ magic_buttons: @magic_buttons,
972
+ small_buttons: @small_buttons
973
+ )
974
+ end
1031
975
 
1032
- def nav_template
1033
- "#{namespace_with_trailing_dash}nav"
1034
- end
976
+ def nav_template
977
+ "#{namespace_with_trailing_dash}nav"
978
+ end
1035
979
 
1036
- def include_nav_template
1037
- File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_nav.html.#{@markup}")
1038
- end
980
+ def include_nav_template
981
+ File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_nav.html.#{@markup}")
982
+ end
1039
983
 
1040
- def copy_view_files
1041
- return if @specs_only
1042
- all_views.each do |view|
1043
- formats.each do |format|
1044
- source_filename = cc_filename_with_extensions("#{@markup}/#{view}", "#{@markup}")
1045
- dest_filename = cc_filename_with_extensions("#{view}", "#{@markup}")
984
+ def copy_view_files
985
+ return if @specs_only
986
+ all_views.each do |view|
987
+ formats.each do |format|
988
+ source_filename = cc_filename_with_extensions("#{@markup}/#{view}", "#{@markup}")
989
+ dest_filename = cc_filename_with_extensions("#{view}", "#{@markup}")
1046
990
 
1047
991
 
1048
- dest_filepath = File.join("#{filepath_prefix}app/views#{namespace_with_dash}",
1049
- @controller_build_folder, dest_filename)
992
+ dest_filepath = File.join("#{filepath_prefix}app/views#{namespace_with_dash}",
993
+ @controller_build_folder, dest_filename)
1050
994
 
1051
995
 
1052
- template source_filename, dest_filepath
1053
- gsub_file dest_filepath, '\%', '%'
996
+ template source_filename, dest_filepath
997
+ gsub_file dest_filepath, '\%', '%'
1054
998
 
1055
- end
1056
999
  end
1000
+ end
1057
1001
 
1058
- turbo_stream_views.each do |view|
1059
- formats.each do |format|
1060
- source_filename = cc_filename_with_extensions( "#{@markup}/#{view}.turbo_stream.#{@markup}")
1061
- dest_filename = cc_filename_with_extensions("#{view}", "turbo_stream.#{@markup}")
1062
- dest_filepath = File.join("#{filepath_prefix}app/views#{namespace_with_dash}",
1063
- @controller_build_folder, dest_filename)
1002
+ turbo_stream_views.each do |view|
1003
+ formats.each do |format|
1004
+ source_filename = cc_filename_with_extensions( "#{@markup}/#{view}.turbo_stream.#{@markup}")
1005
+ dest_filename = cc_filename_with_extensions("#{view}", "turbo_stream.#{@markup}")
1006
+ dest_filepath = File.join("#{filepath_prefix}app/views#{namespace_with_dash}",
1007
+ @controller_build_folder, dest_filename)
1064
1008
 
1065
1009
 
1066
- template source_filename, dest_filepath
1067
- gsub_file dest_filepath, '\%', '%'
1010
+ template source_filename, dest_filepath
1011
+ gsub_file dest_filepath, '\%', '%'
1068
1012
 
1069
- end
1070
1013
  end
1071
1014
  end
1015
+ end
1072
1016
 
1073
- def append_model_callbacks
1074
- # somehow the generator invokes this
1075
-
1076
- if options['with_turbo_streams'] == true
1077
- dest_filename = cc_filename_with_extensions("#{singular_class.underscore}", "rb")
1078
- dest_filepath = File.join("#{filepath_prefix}app/models", dest_filename)
1017
+ def append_model_callbacks
1018
+ # somehow the generator invokes this
1079
1019
 
1020
+ if options['with_turbo_streams'] == true
1021
+ dest_filename = cc_filename_with_extensions("#{singular_class.underscore}", "rb")
1022
+ dest_filepath = File.join("#{filepath_prefix}app/models", dest_filename)
1080
1023
 
1081
- puts "appending turbo callbacks to #{dest_filepath}"
1082
1024
 
1083
- text = File.read(dest_filepath)
1025
+ puts "appending turbo callbacks to #{dest_filepath}"
1084
1026
 
1085
- append_text = "class #{singular_class} < ApplicationRecord\n"
1086
- if !text.include?("include ActionView::RecordIdentifier")
1087
- append_text << " include ActionView::RecordIdentifier\n"
1088
- end
1089
- append_text << " after_update_commit lambda { broadcast_replace_to self, target: \"#{@namespace}__\#{dom_id(self)}\", partial: \"#{@namespace}/#{@plural}/line\" }\n after_destroy_commit lambda { broadcast_remove_to self, target: \"#{@namespace}__\#{dom_id(self)}\"}\n"
1027
+ text = File.read(dest_filepath)
1090
1028
 
1091
- replace = text.gsub(/class #{singular_class} < ApplicationRecord/, append_text)
1092
- File.open(dest_filepath, "w") {|file| file.puts replace}
1029
+ append_text = "class #{singular_class} < ApplicationRecord\n"
1030
+ if !text.include?("include ActionView::RecordIdentifier")
1031
+ append_text << " include ActionView::RecordIdentifier\n"
1093
1032
  end
1094
- end
1033
+ append_text << " after_update_commit lambda { broadcast_replace_to self, target: \"#{@namespace}__\#{dom_id(self)}\", partial: \"#{@namespace}/#{@plural}/line\" }\n after_destroy_commit lambda { broadcast_remove_to self, target: \"#{@namespace}__\#{dom_id(self)}\"}\n"
1095
1034
 
1096
- def namespace_with_dash
1097
- if @namespace
1098
- "/#{@namespace}"
1099
- else
1100
- ""
1101
- end
1035
+ replace = text.gsub(/class #{singular_class} < ApplicationRecord/, append_text)
1036
+ File.open(dest_filepath, "w") {|file| file.puts replace}
1102
1037
  end
1038
+ end
1103
1039
 
1104
- def namespace_with_trailing_dash
1105
- @namespace ? "#{@namespace}/" : ""
1040
+ def namespace_with_dash
1041
+ if @namespace
1042
+ "/#{@namespace}"
1043
+ else
1044
+ ""
1106
1045
  end
1046
+ end
1107
1047
 
1108
- def all_views
1109
- res = %w(index _line _list _show _errors)
1110
-
1111
- unless @no_create
1112
- res += %w(new _new_form _new_button)
1113
- end
1048
+ def namespace_with_trailing_dash
1049
+ @namespace ? "#{@namespace}/" : ""
1050
+ end
1114
1051
 
1115
- unless @no_edit
1116
- res << 'edit'
1117
- end
1052
+ def all_views
1053
+ res = %w(index _line _list _show _errors)
1118
1054
 
1119
- if !( @no_edit && @no_create)
1120
- res << '_form'
1121
- end
1122
- res
1055
+ unless @no_create
1056
+ res += %w(new _new_form _new_button)
1123
1057
  end
1124
1058
 
1125
- def turbo_stream_views
1126
- res = []
1127
- unless @no_delete
1128
- res << 'destroy'
1129
- end
1130
-
1131
- unless @no_create
1132
- res << 'create'
1133
- end
1134
-
1135
- unless @no_edit
1136
- res << 'edit'
1137
- res << 'update'
1138
- end
1139
-
1140
- res
1059
+ unless @no_edit
1060
+ res << 'edit'
1141
1061
  end
1142
1062
 
1143
- def handler
1144
- :erb
1063
+ if !( @no_edit && @no_create)
1064
+ res << '_form'
1145
1065
  end
1066
+ res
1067
+ end
1146
1068
 
1147
- def model_has_strings?
1148
- false
1069
+ def turbo_stream_views
1070
+ res = []
1071
+ unless @no_delete
1072
+ res << 'destroy'
1149
1073
  end
1150
1074
 
1151
- def model_search_fields # an array of fields we can search on
1152
- []
1075
+ unless @no_create
1076
+ res << 'create'
1153
1077
  end
1154
1078
 
1155
- def form_fields_html
1156
- @template_builder.all_form_fields(layout_strategy: @layout_strategy,
1157
- layout_object: @layout_object)
1079
+ unless @no_edit
1080
+ res << 'edit'
1081
+ res << 'update'
1158
1082
  end
1159
1083
 
1160
- def list_label
1161
- @list_label_heading
1162
- end
1084
+ res
1085
+ end
1163
1086
 
1164
- def new_thing_label
1165
- @new_thing_label
1166
- end
1087
+ def handler
1088
+ :erb
1089
+ end
1167
1090
 
1168
- def all_line_fields
1169
- @template_builder.all_line_fields(
1170
- col_identifier: @layout_strategy.column_classes_for_line_fields,
1171
- perc_width: @layout_strategy.each_col, #undefined method `each_col'
1172
- layout_strategy: @layout_strategy,
1173
- layout_object: @layout_object
1174
- )
1091
+ def model_has_strings?
1092
+ false
1093
+ end
1094
+
1095
+ def model_search_fields # an array of fields we can search on
1096
+ []
1097
+ end
1098
+
1099
+ def form_fields_html
1100
+ @template_builder.all_form_fields(layout_strategy: @layout_strategy,
1101
+ layout_object: @layout_object)
1102
+ end
1103
+
1104
+ def list_label
1105
+ @list_label_heading
1106
+ end
1107
+
1108
+ def new_thing_label
1109
+ @new_thing_label
1110
+ end
1111
+
1112
+ def all_line_fields
1113
+ @template_builder.all_line_fields(
1114
+ col_identifier: @layout_strategy.column_classes_for_line_fields,
1115
+ perc_width: @layout_strategy.each_col, #undefined method `each_col'
1116
+ layout_strategy: @layout_strategy,
1117
+ layout_object: @layout_object
1118
+ )
1119
+ end
1120
+
1121
+ def controller_descends_from
1122
+ if defined?(@namespace.titlecase.gsub(" ", "") + "::BaseController")
1123
+ @namespace.titlecase.gsub(" ", "") + "::BaseController"
1124
+ else
1125
+ "ApplicationController"
1175
1126
  end
1127
+ end
1176
1128
 
1177
- def controller_descends_from
1178
- if defined?(@namespace.titlecase.gsub(" ", "") + "::BaseController")
1179
- @namespace.titlecase.gsub(" ", "") + "::BaseController"
1129
+ def display_class
1130
+ me = eval(singular_class)
1131
+
1132
+ @display_class ||=
1133
+ if me.column_names.include?("name") || me.instance_methods(false).include?(:name)
1134
+ # note that all class object respond_to?(:name) with the name of their own class
1135
+ # this one is unique
1136
+ "name"
1137
+ elsif me.column_names.include?("to_label") || me.instance_methods(false).include?(:to_label)
1138
+ "to_label"
1139
+ elsif me.column_names.include?("full_name") || me.instance_methods(false).include?(:full_name)
1140
+ "full_name"
1141
+ elsif me.column_names.include?("display_name") || me.instance_methods(false).include?(:display_name)
1142
+ "display_name"
1143
+ elsif me.column_names.include?("email") || me.instance_methods(false).include?(:email)
1144
+ "email"
1180
1145
  else
1181
- "ApplicationController"
1146
+ exit_message = "*** Oops: Can't find any column to use as the display label on #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, 5) email, or 6) number directly on your #{singular_class} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)"
1147
+ raise(HotGlue::Error, exit_message)
1182
1148
  end
1183
- end
1184
-
1185
- def display_class
1186
- me = eval(singular_class)
1187
-
1188
- @display_class ||=
1189
- if me.column_names.include?("name") || me.instance_methods(false).include?(:name)
1190
- # note that all class object respond_to?(:name) with the name of their own class
1191
- # this one is unique
1192
- "name"
1193
- elsif me.column_names.include?("to_label") || me.instance_methods(false).include?(:to_label)
1194
- "to_label"
1195
- elsif me.column_names.include?("full_name") || me.instance_methods(false).include?(:full_name)
1196
- "full_name"
1197
- elsif me.column_names.include?("display_name") || me.instance_methods(false).include?(:display_name)
1198
- "display_name"
1199
- elsif me.column_names.include?("email") || me.instance_methods(false).include?(:email)
1200
- "email"
1201
- else
1202
- exit_message = "*** Oops: Can't find any column to use as the display label on #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, 5) email, or 6) number directly on your #{singular_class} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)"
1203
- raise(HotGlue::Error, exit_message)
1204
- end
1205
- end
1149
+ end
1206
1150
 
1207
- def destroy_action
1208
- return false if @self_auth
1209
- return !@no_delete
1210
- end
1151
+ def destroy_action
1152
+ return false if @self_auth
1153
+ return !@no_delete
1154
+ end
1211
1155
 
1212
- def create_action
1213
- return false if @self_auth
1214
- return !@no_create
1215
- end
1156
+ def create_action
1157
+ return false if @self_auth
1158
+ return !@no_create
1159
+ end
1216
1160
 
1217
- def namespace_with_slash
1218
- if @namespace
1219
- "#{@namespace}/"
1220
- else
1221
- ""
1222
- end
1161
+ def namespace_with_slash
1162
+ if @namespace
1163
+ "#{@namespace}/"
1164
+ else
1165
+ ""
1223
1166
  end
1167
+ end
1224
1168
 
1225
- def paginate
1226
- @template_builder.paginate(plural: plural)
1227
- end
1169
+ def paginate
1170
+ @template_builder.paginate(plural: plural)
1171
+ end
1228
1172
 
1229
- def controller_magic_button_update_actions
1230
- @magic_buttons.collect{ |magic_button|
1231
- " if #{singular}_params[:#{magic_button}]
1173
+ def controller_magic_button_update_actions
1174
+ @magic_buttons.collect{ |magic_button|
1175
+ " if #{singular}_params[:#{magic_button}]
1232
1176
  begin
1233
1177
  res = @#{singular}.#{magic_button}!
1234
1178
  res = \"#{magic_button.titleize}ed.\" if res === true
@@ -1239,79 +1183,78 @@ module HotGlue
1239
1183
  end
1240
1184
  end"
1241
1185
 
1242
- }.join("\n") + "\n"
1243
- end
1186
+ }.join("\n") + "\n"
1187
+ end
1244
1188
 
1245
1189
 
1246
- def controller_update_params_tap_away_magic_buttons
1247
- @magic_buttons.collect{ |magic_button|
1248
- ".tap{ |ary| ary.delete('__#{magic_button}') }"
1249
- }.join("")
1250
- end
1190
+ def controller_update_params_tap_away_magic_buttons
1191
+ @magic_buttons.collect{ |magic_button|
1192
+ ".tap{ |ary| ary.delete('__#{magic_button}') }"
1193
+ }.join("")
1194
+ end
1251
1195
 
1252
- def controller_update_params_tap_away_alt_lookups
1253
- @alt_lookups.collect{ |key, data|
1254
- ".tap{ |ary| ary.delete('__lookup_#{data[:lookup_as]}') }"
1255
- }.join("")
1256
- end
1196
+ def controller_update_params_tap_away_alt_lookups
1197
+ @alt_lookups.collect{ |key, data|
1198
+ ".tap{ |ary| ary.delete('__lookup_#{data[:lookup_as]}') }"
1199
+ }.join("")
1200
+ end
1257
1201
 
1258
- def nested_for_turbo_id_list_constructor
1259
- if @nested_set.any?
1260
- '+ (((\'__\' + nested_for) if defined?(nested_for)) || "")'
1261
- else
1262
- ""
1263
- end
1202
+ def nested_for_turbo_id_list_constructor
1203
+ if @nested_set.any?
1204
+ '+ (((\'__\' + nested_for) if defined?(nested_for)) || "")'
1205
+ else
1206
+ ""
1264
1207
  end
1208
+ end
1265
1209
 
1266
- def n_plus_one_includes
1267
- if @associations.any? || @attachments.any?
1268
- ".includes(" + (@associations.map{|x| x} + @attachments.collect{|k,v| "#{k}_attachment"}).map{|x| ":#{x.to_s}"}.join(", ") + ")"
1269
- else
1270
- ""
1271
- end
1210
+ def n_plus_one_includes
1211
+ if @associations.any? || @attachments.any?
1212
+ ".includes(" + (@associations.map{|x| x} + @attachments.collect{|k,v| "#{k}_attachment"}).map{|x| ":#{x.to_s}"}.join(", ") + ")"
1213
+ else
1214
+ ""
1272
1215
  end
1216
+ end
1273
1217
 
1274
- def nested_for_turbo_nested_constructor(top_level = true)
1275
- instance_symbol = "@" if top_level
1276
- instance_symbol = "" if !top_level
1277
- if @nested_set.none?
1278
- "\"\""
1279
- else
1280
- @nested_set.collect{|arg|
1281
- "(((\"__#{arg[:singular]}-\#{" + "@" + arg[:singular] + ".id}\") if @" + arg[:singular] + ") || \"\")"
1282
- }.join(" + ")
1283
- end
1218
+ def nested_for_turbo_nested_constructor(top_level = true)
1219
+ instance_symbol = "@" if top_level
1220
+ instance_symbol = "" if !top_level
1221
+ if @nested_set.none?
1222
+ "\"\""
1223
+ else
1224
+ @nested_set.collect{|arg|
1225
+ "(((\"__#{arg[:singular]}-\#{" + "@" + arg[:singular] + ".id}\") if @" + arg[:singular] + ") || \"\")"
1226
+ }.join(" + ")
1284
1227
  end
1228
+ end
1285
1229
 
1286
- def nested_for_assignments_constructor(top_level = true)
1287
- instance_symbol = "@" if top_level
1288
- instance_symbol = "" if !top_level
1289
- if @nested_set.none?
1290
- ""
1291
- else
1292
- ", \n nested_for: \"" + @nested_set.collect{|a| "#{a[:singular]}-" + '#{' + instance_symbol + a[:singular] + ".id}"}.join("__") + "\""
1293
- end
1230
+ def nested_for_assignments_constructor(top_level = true)
1231
+ instance_symbol = "@" if top_level
1232
+ instance_symbol = "" if !top_level
1233
+ if @nested_set.none?
1234
+ ""
1235
+ else
1236
+ ", \n nested_for: \"" + @nested_set.collect{|a| "#{a[:singular]}-" + '#{' + instance_symbol + a[:singular] + ".id}"}.join("__") + "\""
1294
1237
  end
1238
+ end
1295
1239
 
1296
- private # thor does something fancy like sending the class all of its own methods during some strange run sequence
1297
- # does not like public methods
1298
- def cc_filename_with_extensions(name, file_format = format)
1299
- [name, file_format].compact.join(".")
1300
- end
1240
+ private # thor does something fancy like sending the class all of its own methods during some strange run sequence
1241
+ # does not like public methods
1242
+ def cc_filename_with_extensions(name, file_format = format)
1243
+ [name, file_format].compact.join(".")
1244
+ end
1301
1245
 
1302
- def hawk_to_ruby
1303
- res = @hawk_keys.collect{ |k,v|
1304
- "#{k.to_s}: [#{v[:bind_to].join(".")}]"
1305
- }.join(", ")
1306
- res
1307
- end
1246
+ def hawk_to_ruby
1247
+ res = @hawk_keys.collect{ |k,v|
1248
+ "#{k.to_s}: [#{v[:bind_to].join(".")}]"
1249
+ }.join(", ")
1250
+ res
1251
+ end
1308
1252
 
1309
- def controller_attachment_orig_filename_pickup_syntax
1310
- @attachments.collect{ |key, attachment| "\n" + " modified_params[:#{ attachment[:field_for_original_filename] }] = #{singular}_params['#{ key }'].original_filename" if attachment[:field_for_original_filename] }.compact.join("\n")
1311
- end
1253
+ def controller_attachment_orig_filename_pickup_syntax
1254
+ @attachments.collect{ |key, attachment| "\n" + " modified_params[:#{ attachment[:field_for_original_filename] }] = #{singular}_params['#{ key }'].original_filename" if attachment[:field_for_original_filename] }.compact.join("\n")
1255
+ end
1312
1256
 
1313
- def any_datetime_fields?
1314
- (@columns - @attachments.keys.collect(&:to_sym)).collect{|col| eval("#{singular_class}.columns_hash['#{col}']").type}.include?(:datetime)
1315
- end
1257
+ def any_datetime_fields?
1258
+ (@columns - @attachments.keys.collect(&:to_sym)).collect{|col| eval("#{singular_class}.columns_hash['#{col}']").type}.include?(:datetime)
1316
1259
  end
1317
1260
  end