hot-glue 0.5.11 → 0.5.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +17 -2
- data/README.md +78 -7
- data/lib/generators/hot_glue/default_config_loader.rb +12 -0
- data/lib/generators/hot_glue/field_factory.rb +2 -0
- data/lib/generators/hot_glue/fields/association_field.rb +1 -1
- data/lib/generators/hot_glue/fields/attachment_field.rb +27 -0
- data/lib/generators/hot_glue/fields/date_time_field.rb +3 -2
- data/lib/generators/hot_glue/fields/enum_field.rb +2 -2
- data/lib/generators/hot_glue/fields/field.rb +2 -2
- data/lib/generators/hot_glue/fields/integer_field.rb +1 -1
- data/lib/generators/hot_glue/fields/uuid_field.rb +1 -2
- data/lib/generators/hot_glue/flash_notices_install_generator.rb +20 -0
- data/lib/generators/hot_glue/hot_glue.rb +5 -0
- data/lib/generators/hot_glue/install_generator.rb +2 -7
- data/lib/generators/hot_glue/layout/builder.rb +38 -55
- data/lib/generators/hot_glue/markup_templates/erb.rb +9 -15
- data/lib/generators/hot_glue/scaffold_generator.rb +971 -1008
- data/lib/generators/hot_glue/templates/controller.rb.erb +5 -4
- data/lib/generators/hot_glue/templates/erb/_edit.erb +12 -0
- data/lib/generators/hot_glue/templates/erb/_flash_notices.erb +12 -8
- data/lib/generators/hot_glue/templates/erb/_list.erb +1 -2
- data/lib/generators/hot_glue/templates/erb/_show.erb +2 -2
- data/lib/generators/hot_glue/templates/erb/create.turbo_stream.erb +3 -4
- data/lib/generators/hot_glue/templates/erb/destroy.turbo_stream.erb +7 -1
- data/lib/generators/hot_glue/templates/erb/edit.erb +34 -16
- data/lib/generators/hot_glue/templates/erb/update.turbo_stream.erb +3 -6
- data/lib/generators/hot_glue/templates/system_spec.rb.erb +1 -1
- data/lib/hot-glue.rb +81 -0
- data/lib/hotglue/version.rb +1 -1
- data/script/test +2 -4
- metadata +6 -18
- data/lib/generators/hot_glue/templates/erb/_errors.erb +0 -11
- data/lib/generators/hot_glue/templates/haml/_errors.haml +0 -6
- data/lib/generators/hot_glue/templates/haml/_flash_notices.haml +0 -8
- data/lib/generators/hot_glue/templates/haml/_form.haml +0 -5
- data/lib/generators/hot_glue/templates/haml/_line.haml +0 -6
- data/lib/generators/hot_glue/templates/haml/_list.haml +0 -15
- data/lib/generators/hot_glue/templates/haml/_new_button.haml +0 -2
- data/lib/generators/hot_glue/templates/haml/_new_form.haml +0 -7
- data/lib/generators/hot_glue/templates/haml/_show.haml +0 -7
- data/lib/generators/hot_glue/templates/haml/create.turbo_stream.haml +0 -14
- data/lib/generators/hot_glue/templates/haml/destroy.turbo_stream.haml +0 -2
- data/lib/generators/hot_glue/templates/haml/edit.haml +0 -19
- data/lib/generators/hot_glue/templates/haml/edit.turbo_stream.haml +0 -4
- data/lib/generators/hot_glue/templates/haml/index.haml +0 -8
- data/lib/generators/hot_glue/templates/haml/new.haml +0 -1
- data/lib/generators/hot_glue/templates/haml/update.turbo_stream.haml +0 -9
@@ -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,1169 @@ 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
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
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
|
-
|
156
|
-
|
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
|
-
|
138
|
+
@button_icons = get_default_from_config(key: :button_icons) || 'none'
|
164
139
|
|
165
|
-
|
166
|
-
|
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
|
-
|
170
|
-
|
171
|
-
puts exit_message
|
150
|
+
args = meta_args[0]
|
151
|
+
@singular = args.first.tableize.singularize # should be in form hello_world
|
172
152
|
|
173
|
-
|
174
|
-
|
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
|
-
|
178
|
-
|
179
|
-
end
|
164
|
+
@auth = options['auth'] || "current_user"
|
165
|
+
@auth_identifier = options['auth_identifier'] || (! @god && @auth.gsub("current_", "")) || nil
|
180
166
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
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
|
-
|
187
|
-
@markup = yaml_from_config[:markup]
|
188
|
-
@sample_file_path = yaml_from_config[:sample_file_path]
|
173
|
+
setup_attachments
|
189
174
|
|
190
|
-
|
191
|
-
|
192
|
-
else
|
193
|
-
layout = yaml_from_config[:layout]
|
175
|
+
@exclude_fields = []
|
176
|
+
@exclude_fields += options['exclude'].split(",").collect(&:to_sym)
|
194
177
|
|
195
|
-
|
196
|
-
|
197
|
-
end
|
198
|
-
end
|
178
|
+
if !options['include'].empty?
|
179
|
+
@include_fields = []
|
199
180
|
|
200
|
-
|
201
|
-
|
202
|
-
|
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
|
-
|
211
|
-
|
185
|
+
@show_only = []
|
186
|
+
if !options['show_only'].empty?
|
187
|
+
@show_only += options['show_only'].split(",").collect(&:to_sym)
|
188
|
+
end
|
212
189
|
|
213
|
-
|
214
|
-
|
215
|
-
|
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
|
-
|
225
|
-
|
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
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
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
|
-
|
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
|
-
|
236
|
-
@exclude_fields += options['exclude'].split(",").collect(&:to_sym)
|
213
|
+
puts "------ ALT LOOKUPS for #{@alt_lookups}"
|
237
214
|
|
238
|
-
|
239
|
-
|
215
|
+
@update_alt_lookups = @alt_lookups.collect{|key, value|
|
216
|
+
@update_show_only.include?(key) ?
|
217
|
+
{ key: value }
|
218
|
+
: nil}.compact
|
240
219
|
|
241
|
-
|
242
|
-
|
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
|
-
|
246
|
-
|
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
|
-
|
257
|
-
|
258
|
-
|
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
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
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
|
-
|
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
|
-
|
289
|
-
|
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
|
-
|
294
|
-
|
295
|
-
|
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
|
-
|
299
|
-
|
300
|
-
|
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
|
-
|
328
|
-
|
266
|
+
@display_list_after_update = options['display_list_after_update'] || false
|
267
|
+
@smart_layout = options['smart_layout']
|
329
268
|
|
330
|
-
|
331
|
-
|
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
|
-
|
334
|
-
|
335
|
-
@big_edit = options['big_edit']
|
273
|
+
@container_name = @layout_strategy.container_name
|
274
|
+
@downnest = options['downnest'] || false
|
336
275
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
@
|
341
|
-
@
|
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
|
-
|
347
|
-
|
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
|
-
|
350
|
-
|
351
|
-
|
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
|
-
|
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
|
-
|
364
|
-
|
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
|
-
|
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
|
-
|
374
|
-
|
375
|
-
|
314
|
+
# NEST CHAIN
|
315
|
+
# new syntax
|
316
|
+
# @nested_set = [
|
317
|
+
# {
|
318
|
+
# singular: ...,
|
319
|
+
# plural: ...,
|
320
|
+
# optional: false
|
321
|
+
# }]
|
322
|
+
@nested_set = []
|
376
323
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
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
|
-
|
386
|
-
|
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
|
-
|
389
|
-
|
390
|
-
|
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
|
-
|
395
|
-
|
396
|
-
|
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
|
-
|
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
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
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
|
-
|
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
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
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
|
-
|
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
|
-
|
478
|
-
if options["hawk"]
|
479
|
-
options['hawk'].split(",").each do |hawk_entry|
|
480
|
-
# format is: abc_id[thing]
|
481
438
|
|
482
|
-
|
483
|
-
hawk_entry =~ /(.*){(.*)}/
|
484
|
-
key, hawk_to = $1, $2
|
485
|
-
else
|
486
|
-
key = hawk_entry
|
487
|
-
hawk_to = @auth
|
488
|
-
end
|
439
|
+
@menu_file_exists = true if @nested_set.none? && File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
|
489
440
|
|
490
|
-
|
491
|
-
|
441
|
+
@turbo_streams = !!options['with_turbo_streams']
|
442
|
+
end
|
492
443
|
|
493
|
-
@hawk_keys[key.to_sym] = {bind_to: [hawk_to], optional: optional}
|
494
|
-
use_shorthand = !options["hawk"].include?("{")
|
495
444
|
|
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
445
|
|
500
|
-
|
446
|
+
def setup_hawk_keys
|
447
|
+
@hawk_keys = {}
|
501
448
|
|
502
|
-
|
503
|
-
|
504
|
-
|
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
|
-
|
508
|
-
|
461
|
+
hawk_scope = key.gsub("_id", "").pluralize
|
462
|
+
optional = eval(singular_class + ".reflect_on_association(:#{key.gsub('_id','')})").options[:optional]
|
509
463
|
|
510
|
-
|
464
|
+
@hawk_keys[key.to_sym] = {bind_to: [hawk_to], optional: optional}
|
465
|
+
use_shorthand = !options["hawk"].include?("{")
|
511
466
|
|
512
|
-
|
513
|
-
|
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
|
-
|
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
|
-
|
473
|
+
puts "HAWKING: #{@hawk_keys}"
|
474
|
+
end
|
475
|
+
end
|
533
476
|
|
534
|
-
if thumbnail == ''
|
535
|
-
thumbnail = nil
|
536
|
-
end
|
537
477
|
|
538
|
-
|
539
|
-
|
540
|
-
|
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
|
-
|
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
|
-
|
547
|
-
|
548
|
-
|
505
|
+
if thumbnail == ''
|
506
|
+
thumbnail = nil
|
507
|
+
end
|
549
508
|
|
550
|
-
|
551
|
-
|
552
|
-
|
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
|
-
|
555
|
-
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 !
|
561
|
-
raise HotGlue::Error, "
|
517
|
+
if dropzone && !direct_upload
|
518
|
+
raise HotGlue::Error, "dropzone requires direct_upload"
|
562
519
|
end
|
563
|
-
|
564
|
-
|
565
|
-
|
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 =
|
570
|
-
|
571
|
-
|
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
|
-
|
575
|
-
|
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
|
-
|
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
|
-
|
594
|
-
|
564
|
+
def identify_object_owner
|
565
|
+
auth_assoc = @auth && @auth.gsub("current_","")
|
595
566
|
|
596
|
-
|
597
|
-
|
598
|
-
|
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
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
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
|
-
|
607
|
-
|
608
|
-
|
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
|
-
|
616
|
-
|
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
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
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
|
-
|
639
|
-
|
640
|
-
|
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
|
-
|
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
|
|
647
|
-
|
648
|
-
|
649
|
-
|
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
|
615
|
+
check_if_sample_file_is_present
|
616
|
+
end
|
617
|
+
end
|
673
618
|
|
674
619
|
|
675
620
|
|
676
|
-
end
|
677
|
-
end
|
678
621
|
|
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
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
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
|
-
|
698
|
-
|
699
|
-
end
|
638
|
+
puts ""
|
639
|
+
end
|
700
640
|
|
701
|
-
|
702
|
-
|
703
|
-
|
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
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
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
|
-
|
715
|
-
"
|
650
|
+
if @factory_creation == ''
|
651
|
+
"@#{singular } = #{ class_name }.create(modified_params#{'.merge(' + merge_with + ')' if !merge_with.empty?})"
|
652
|
+
else
|
653
|
+
"#{@factory_creation}\n" +
|
654
|
+
" @#{singular } = factory.#{singular}"
|
716
655
|
end
|
656
|
+
end
|
717
657
|
|
718
|
-
|
719
|
-
|
720
|
-
|
658
|
+
def auth_root
|
659
|
+
"authenticate_" + @auth_identifier.split(".")[0] + "!"
|
660
|
+
end
|
721
661
|
|
722
|
-
|
723
|
-
|
724
|
-
|
662
|
+
def formats
|
663
|
+
[format]
|
664
|
+
end
|
725
665
|
|
726
|
-
|
727
|
-
|
728
|
-
|
666
|
+
def format
|
667
|
+
nil
|
668
|
+
end
|
729
669
|
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
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
|
-
|
744
|
-
|
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
|
-
|
758
|
-
|
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
|
-
|
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
706
|
|
769
|
-
|
770
|
-
", #{testing_name}: #{testing_name}1"
|
707
|
+
template "system_spec.rb.erb", dest_file
|
771
708
|
end
|
772
709
|
|
773
|
-
|
774
|
-
|
775
|
-
end
|
776
|
-
|
777
|
-
def spec_related_column_lets
|
778
|
-
@columns_map.collect { |col, col_object|
|
779
|
-
col_object.spec_related_column_lets
|
780
|
-
}.join("\n")
|
710
|
+
if File.exist?("#{filepath_prefix}app/views#{namespace_with_dash}/_errors.#{@markup}")
|
711
|
+
File.delete("#{filepath_prefix}app/views#{namespace_with_dash}/_errors.#{@markup}")
|
781
712
|
end
|
713
|
+
end
|
782
714
|
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
col_identifier: @layout_strategy.column_classes_for_column_headings,
|
787
|
-
column_width: @layout_strategy.column_width,
|
788
|
-
singular: @singular
|
789
|
-
)
|
790
|
-
end
|
715
|
+
def spec_foreign_association_merge_hash
|
716
|
+
", #{testing_name}: #{testing_name}1"
|
717
|
+
end
|
791
718
|
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
random_data = col_object.spec_random_data
|
796
|
-
col.to_s + ": '" + random_data.to_s + "'"
|
797
|
-
end
|
798
|
-
}.join(", ")
|
799
|
-
end
|
719
|
+
def testing_name
|
720
|
+
singular_class.gsub("::","_").underscore
|
721
|
+
end
|
800
722
|
|
801
|
-
|
802
|
-
|
803
|
-
|
723
|
+
def spec_related_column_lets
|
724
|
+
@columns_map.collect { |col, col_object|
|
725
|
+
col_object.spec_related_column_lets
|
726
|
+
}.join("\n")
|
727
|
+
end
|
804
728
|
|
805
|
-
|
729
|
+
def list_column_headings
|
730
|
+
@template_builder.list_column_headings(
|
731
|
+
layout_object: @layout_object,
|
732
|
+
col_identifier: @layout_strategy.column_classes_for_column_headings,
|
733
|
+
column_width: @layout_strategy.column_width,
|
734
|
+
singular: @singular
|
735
|
+
)
|
736
|
+
end
|
806
737
|
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
", #{@auth_identifier}: #{@auth}"
|
738
|
+
def columns_spec_with_sample_data
|
739
|
+
@columns_map.map { |col, col_object|
|
740
|
+
unless col_object.is_a?(AssociationField)
|
741
|
+
random_data = col_object.spec_random_data
|
742
|
+
col.to_s + ": '" + random_data.to_s + "'"
|
813
743
|
end
|
814
|
-
|
744
|
+
}.join(", ")
|
745
|
+
end
|
815
746
|
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
last_parent = ", #{@auth_identifier}: #{@auth}"
|
820
|
-
end
|
747
|
+
def regenerate_me_code
|
748
|
+
"rails generate hot_glue:scaffold #{ @meta_args[0][0] } #{@meta_args[1].collect{|x| x.gsub(/\s*=\s*([\S\s]+)/, '=\'\1\'')}.join(" ")}"
|
749
|
+
end
|
821
750
|
|
822
|
-
|
823
|
-
res << " let(:#{arg[:singular]}) {create(:#{arg[:singular]} #{last_parent} )}\n"
|
824
|
-
last_parent = ", #{arg[:singular]}: #{arg[:singular]}"
|
825
|
-
end
|
826
|
-
res
|
827
|
-
end
|
751
|
+
def object_parent_mapping_as_argument_for_specs
|
828
752
|
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
753
|
+
if @self_auth
|
754
|
+
""
|
755
|
+
elsif @nested_set.any? && ! @nested_set.last[:optional]
|
756
|
+
", " + @nested_set.last[:singular] + ": " + @nested_set.last[:singular]
|
757
|
+
elsif @auth && !@god
|
758
|
+
", #{@auth_identifier}: #{@auth}"
|
833
759
|
end
|
760
|
+
end
|
834
761
|
|
835
|
-
|
836
|
-
|
762
|
+
def objest_nest_factory_setup
|
763
|
+
res = ""
|
764
|
+
if @auth
|
765
|
+
last_parent = ", #{@auth_identifier}: #{@auth}"
|
837
766
|
end
|
838
767
|
|
839
|
-
|
840
|
-
|
768
|
+
@nested_set.each do |arg|
|
769
|
+
res << " let(:#{arg[:singular]}) {create(:#{arg[:singular]} #{last_parent} )}\n"
|
770
|
+
last_parent = ", #{arg[:singular]}: #{arg[:singular]}"
|
841
771
|
end
|
772
|
+
res
|
773
|
+
end
|
842
774
|
|
843
|
-
|
844
|
-
|
845
|
-
|
775
|
+
def objest_nest_params_by_id_for_specs
|
776
|
+
@nested_set.map{|arg|
|
777
|
+
"#{arg[:singular]}_id: #{arg[:singular]}.id"
|
778
|
+
}.join(",\n ")
|
779
|
+
end
|
846
780
|
|
847
|
-
|
848
|
-
|
849
|
-
|
781
|
+
def controller_class_name
|
782
|
+
@controller_build_name
|
783
|
+
end
|
850
784
|
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
col_obj.spec_setup_and_change_act(which_partial)
|
855
|
-
end
|
856
|
-
}.join("\n")
|
857
|
-
end
|
785
|
+
def plural_name
|
786
|
+
plural
|
787
|
+
end
|
858
788
|
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
789
|
+
def auth_identifier
|
790
|
+
@auth_identifier
|
791
|
+
end
|
792
|
+
|
793
|
+
def capybara_make_updates(which_partial = :create)
|
794
|
+
@columns_map.map { | col, col_obj|
|
795
|
+
show_only_list = which_partial == :create ? @show_only : (@update_show_only+@show_only)
|
866
796
|
|
867
|
-
|
868
|
-
|
869
|
-
"#{@namespace+"_" if @namespace}#{(@nested_set.collect{|x| x[:singular]}.join("_") + "_" if @nested_set.any?)}#{@controller_build_folder_singular}_path"
|
797
|
+
if show_only_list.include?(col)
|
798
|
+
" page.should have_no_selector(:css, \"[name='#{testing_name}[#{ col.to_s }]'\")"
|
870
799
|
else
|
871
|
-
|
800
|
+
col_obj.spec_setup_and_change_act(which_partial)
|
872
801
|
end
|
873
|
-
|
802
|
+
}.join("\n")
|
803
|
+
end
|
874
804
|
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
805
|
+
def path_helper_args
|
806
|
+
if @nested_set.any? && @nested
|
807
|
+
[(@nested_set).collect{|a| "#{a[:singular]}"} , singular].join(",")
|
808
|
+
else
|
809
|
+
singular
|
879
810
|
end
|
811
|
+
end
|
880
812
|
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
top_level: false)
|
813
|
+
def path_helper_singular
|
814
|
+
if @nested
|
815
|
+
"#{@namespace+"_" if @namespace}#{(@nested_set.collect{|x| x[:singular]}.join("_") + "_" if @nested_set.any?)}#{@controller_build_folder_singular}_path"
|
816
|
+
else
|
817
|
+
"#{@namespace+"_" if @namespace}#{@controller_build_folder_singular}_path"
|
887
818
|
end
|
819
|
+
end
|
888
820
|
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
put_form: true,
|
895
|
-
top_level: true)
|
896
|
-
end
|
821
|
+
def path_helper_plural
|
822
|
+
HotGlue.optionalized_ternary(namespace: @namespace,
|
823
|
+
target: @controller_build_folder,
|
824
|
+
nested_set: @nested_set)
|
825
|
+
end
|
897
826
|
|
827
|
+
def form_path_new_helper
|
828
|
+
HotGlue.optionalized_ternary(namespace: @namespace,
|
829
|
+
target: @controller_build_folder,
|
830
|
+
nested_set: @nested_set,
|
831
|
+
with_params: true,
|
832
|
+
top_level: false)
|
833
|
+
end
|
898
834
|
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
835
|
+
def form_path_edit_helper
|
836
|
+
HotGlue.optionalized_ternary(namespace: @namespace,
|
837
|
+
target: @singular,
|
838
|
+
nested_set: @nested_set,
|
839
|
+
with_params: true,
|
840
|
+
put_form: true,
|
841
|
+
top_level: true)
|
842
|
+
end
|
906
843
|
|
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
844
|
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
845
|
+
def delete_path_helper
|
846
|
+
HotGlue.optionalized_ternary(namespace: @namespace,
|
847
|
+
target: @singular,
|
848
|
+
nested_set: @nested_set,
|
849
|
+
with_params: true,
|
850
|
+
put_form: true)
|
851
|
+
end
|
923
852
|
|
924
|
-
|
925
|
-
|
926
|
-
|
853
|
+
def edit_path_helper
|
854
|
+
HotGlue.optionalized_ternary(namespace: @namespace,
|
855
|
+
target: @singular,
|
856
|
+
nested_set: @nested_set,
|
857
|
+
modifier: "edit_",
|
858
|
+
with_params: true,
|
859
|
+
put_form: true)
|
860
|
+
end
|
927
861
|
|
928
|
-
|
929
|
-
|
862
|
+
def path_arity
|
863
|
+
res = ""
|
864
|
+
if @nested_set.any? && @nested
|
865
|
+
res << nested_objects_arity + ", "
|
930
866
|
end
|
867
|
+
res << "@" + singular
|
868
|
+
end
|
931
869
|
|
932
|
-
|
933
|
-
|
934
|
-
|
870
|
+
def line_path_partial
|
871
|
+
"#{@namespace+"/" if @namespace}#{@controller_build_folder}/line"
|
872
|
+
end
|
935
873
|
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
nested_set: @nested_set,
|
940
|
-
modifier: "new_",
|
941
|
-
with_params: true)
|
942
|
-
end
|
874
|
+
def show_path_partial
|
875
|
+
"#{@namespace+"/" if @namespace}#{@controller_build_folder}/show"
|
876
|
+
end
|
943
877
|
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
end
|
878
|
+
def list_path_partial
|
879
|
+
"#{@namespace+"/" if @namespace}#{@controller_build_folder}/list"
|
880
|
+
end
|
948
881
|
|
949
|
-
|
950
|
-
|
951
|
-
|
882
|
+
def new_path_name
|
883
|
+
HotGlue.optionalized_ternary(namespace: @namespace,
|
884
|
+
target: singular,
|
885
|
+
nested_set: @nested_set,
|
886
|
+
modifier: "new_",
|
887
|
+
with_params: true)
|
888
|
+
end
|
952
889
|
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
""
|
958
|
-
end
|
959
|
-
end
|
890
|
+
def nested_assignments
|
891
|
+
return "" if @nested_set.none?
|
892
|
+
@nested_set.map{|a| "#{a}: #{a}"}.join(", ") #metaprgramming into Ruby hash
|
893
|
+
end
|
960
894
|
|
961
|
-
|
962
|
-
|
963
|
-
|
895
|
+
def nested_assignments_top_level # this is by accessing the instance variable-- only use at top level
|
896
|
+
@nested_set.map{|a| "#{a[:singular]}"}.join(", ") #metaprgramming into Ruby hash
|
897
|
+
end
|
964
898
|
|
965
|
-
|
966
|
-
|
899
|
+
def nest_assignments_operator(top_level = false, leading_comma = false)
|
900
|
+
if @nested_set.any?
|
901
|
+
"#{", " if leading_comma}#{top_level ? nested_assignments_top_level : nested_assignments }"
|
902
|
+
else
|
903
|
+
""
|
967
904
|
end
|
905
|
+
end
|
968
906
|
|
969
|
-
|
970
|
-
|
971
|
-
|
907
|
+
def nested_assignments_with_leading_comma
|
908
|
+
nest_assignments_operator(false, true)
|
909
|
+
end
|
972
910
|
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
911
|
+
def nested_objects_arity
|
912
|
+
@nested_set.map{|a| "@#{a[:singular]}"}.join(", ")
|
913
|
+
end
|
914
|
+
|
915
|
+
def nested_arity_for_path
|
916
|
+
[@nested_set[0..-1].collect{|a| "@#{a[:singular]}"}].join(", ") #metaprgramming into arity for the Rails path helper
|
917
|
+
end
|
918
|
+
|
919
|
+
def object_scope
|
920
|
+
if @auth
|
921
|
+
if @nested_set.none?
|
922
|
+
@auth + ".#{plural}"
|
980
923
|
else
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
924
|
+
"@" + @nested_set.last[:singular] + ".#{plural}"
|
925
|
+
end
|
926
|
+
else
|
927
|
+
if @nested_set.none?
|
928
|
+
@singular_class
|
929
|
+
else
|
930
|
+
"@" + @nested_set.last[:singular] + ".#{plural}"
|
986
931
|
end
|
987
932
|
end
|
933
|
+
end
|
988
934
|
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
else
|
996
|
-
"@" + @nested_set.last[:singular] + ".#{plural}"
|
997
|
-
end
|
935
|
+
def all_objects_root
|
936
|
+
if @auth
|
937
|
+
if @self_auth
|
938
|
+
@singular_class + ".where(id: #{@auth}.id)"
|
939
|
+
elsif @nested_set.none?
|
940
|
+
@auth + ".#{plural}"
|
998
941
|
else
|
999
|
-
@
|
942
|
+
"@" + @nested_set.last[:singular] + ".#{plural}"
|
1000
943
|
end
|
944
|
+
else
|
945
|
+
@singular_class + ".all"
|
1001
946
|
end
|
947
|
+
end
|
1002
948
|
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
949
|
+
def any_nested?
|
950
|
+
@nested_set.any?
|
951
|
+
end
|
1006
952
|
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
953
|
+
def all_objects_variable
|
954
|
+
all_objects_root + ".page(params[:page])"
|
955
|
+
end
|
1010
956
|
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
957
|
+
def auth_object
|
958
|
+
@auth
|
959
|
+
end
|
1014
960
|
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
961
|
+
def no_devise_installed
|
962
|
+
!Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.group_by{ |g| g.name }['devise']
|
963
|
+
end
|
1018
964
|
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
965
|
+
def magic_button_output
|
966
|
+
@template_builder.magic_button_output(
|
967
|
+
path: HotGlue.optionalized_ternary(namespace: @namespace,
|
968
|
+
target: @singular,
|
969
|
+
nested_set: @nested_set,
|
970
|
+
with_params: true,
|
971
|
+
put_form: true),
|
972
|
+
singular: singular,
|
973
|
+
magic_buttons: @magic_buttons,
|
974
|
+
small_buttons: @small_buttons
|
975
|
+
)
|
976
|
+
end
|
1031
977
|
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
978
|
+
def nav_template
|
979
|
+
"#{namespace_with_trailing_dash}nav"
|
980
|
+
end
|
1035
981
|
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
982
|
+
def include_nav_template
|
983
|
+
File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_nav.html.#{@markup}")
|
984
|
+
end
|
1039
985
|
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
986
|
+
def copy_view_files
|
987
|
+
return if @specs_only
|
988
|
+
all_views.each do |view|
|
989
|
+
formats.each do |format|
|
990
|
+
source_filename = cc_filename_with_extensions("#{@markup}/#{view}", "#{@markup}")
|
991
|
+
dest_filename = cc_filename_with_extensions("#{view}", "#{@markup}")
|
1046
992
|
|
1047
993
|
|
1048
|
-
|
1049
|
-
|
994
|
+
dest_filepath = File.join("#{filepath_prefix}app/views#{namespace_with_dash}",
|
995
|
+
@controller_build_folder, dest_filename)
|
1050
996
|
|
1051
997
|
|
1052
|
-
|
1053
|
-
|
998
|
+
template source_filename, dest_filepath
|
999
|
+
gsub_file dest_filepath, '\%', '%'
|
1054
1000
|
|
1055
|
-
end
|
1056
1001
|
end
|
1002
|
+
end
|
1057
1003
|
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1004
|
+
turbo_stream_views.each do |view|
|
1005
|
+
formats.each do |format|
|
1006
|
+
source_filename = cc_filename_with_extensions( "#{@markup}/#{view}.turbo_stream.#{@markup}")
|
1007
|
+
dest_filename = cc_filename_with_extensions("#{view}", "turbo_stream.#{@markup}")
|
1008
|
+
dest_filepath = File.join("#{filepath_prefix}app/views#{namespace_with_dash}",
|
1009
|
+
@controller_build_folder, dest_filename)
|
1064
1010
|
|
1065
1011
|
|
1066
|
-
|
1067
|
-
|
1012
|
+
template source_filename, dest_filepath
|
1013
|
+
gsub_file dest_filepath, '\%', '%'
|
1068
1014
|
|
1069
|
-
end
|
1070
1015
|
end
|
1071
1016
|
end
|
1017
|
+
end
|
1072
1018
|
|
1073
|
-
|
1074
|
-
|
1019
|
+
def append_model_callbacks
|
1020
|
+
# somehow the generator invokes this
|
1075
1021
|
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1022
|
+
if options['with_turbo_streams'] == true
|
1023
|
+
dest_filename = cc_filename_with_extensions("#{singular_class.underscore}", "rb")
|
1024
|
+
dest_filepath = File.join("#{filepath_prefix}app/models", dest_filename)
|
1079
1025
|
|
1080
1026
|
|
1081
|
-
|
1027
|
+
puts "appending turbo callbacks to #{dest_filepath}"
|
1082
1028
|
|
1083
|
-
|
1029
|
+
text = File.read(dest_filepath)
|
1084
1030
|
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
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"
|
1090
|
-
|
1091
|
-
replace = text.gsub(/class #{singular_class} < ApplicationRecord/, append_text)
|
1092
|
-
File.open(dest_filepath, "w") {|file| file.puts replace}
|
1031
|
+
append_text = "class #{singular_class} < ApplicationRecord\n"
|
1032
|
+
if !text.include?("include ActionView::RecordIdentifier")
|
1033
|
+
append_text << " include ActionView::RecordIdentifier\n"
|
1093
1034
|
end
|
1094
|
-
|
1035
|
+
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
1036
|
|
1096
|
-
|
1097
|
-
|
1098
|
-
"/#{@namespace}"
|
1099
|
-
else
|
1100
|
-
""
|
1101
|
-
end
|
1037
|
+
replace = text.gsub(/class #{singular_class} < ApplicationRecord/, append_text)
|
1038
|
+
File.open(dest_filepath, "w") {|file| file.puts replace}
|
1102
1039
|
end
|
1040
|
+
end
|
1103
1041
|
|
1104
|
-
|
1105
|
-
|
1042
|
+
def namespace_with_dash
|
1043
|
+
if @namespace
|
1044
|
+
"/#{@namespace}"
|
1045
|
+
else
|
1046
|
+
""
|
1106
1047
|
end
|
1048
|
+
end
|
1107
1049
|
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
unless @no_create
|
1112
|
-
res += %w(new _new_form _new_button)
|
1113
|
-
end
|
1050
|
+
def namespace_with_trailing_dash
|
1051
|
+
@namespace ? "#{@namespace}/" : ""
|
1052
|
+
end
|
1114
1053
|
|
1115
|
-
|
1116
|
-
|
1117
|
-
end
|
1054
|
+
def all_views
|
1055
|
+
res = %w(index _line _list _show)
|
1118
1056
|
|
1119
|
-
|
1120
|
-
|
1121
|
-
end
|
1122
|
-
res
|
1057
|
+
unless @no_create
|
1058
|
+
res += %w(new _new_form _new_button)
|
1123
1059
|
end
|
1124
1060
|
|
1125
|
-
|
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
|
1061
|
+
unless @no_edit
|
1062
|
+
res += %w{edit _edit}
|
1141
1063
|
end
|
1142
1064
|
|
1143
|
-
|
1144
|
-
|
1065
|
+
if !( @no_edit && @no_create)
|
1066
|
+
res << '_form'
|
1145
1067
|
end
|
1068
|
+
res
|
1069
|
+
end
|
1146
1070
|
|
1147
|
-
|
1148
|
-
|
1071
|
+
def turbo_stream_views
|
1072
|
+
res = []
|
1073
|
+
unless @no_delete
|
1074
|
+
res << 'destroy'
|
1149
1075
|
end
|
1150
1076
|
|
1151
|
-
|
1152
|
-
|
1077
|
+
unless @no_create
|
1078
|
+
res << 'create'
|
1153
1079
|
end
|
1154
1080
|
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1081
|
+
unless @no_edit
|
1082
|
+
res << 'edit'
|
1083
|
+
res << 'update'
|
1158
1084
|
end
|
1159
1085
|
|
1160
|
-
|
1161
|
-
|
1162
|
-
end
|
1086
|
+
res
|
1087
|
+
end
|
1163
1088
|
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1089
|
+
def handler
|
1090
|
+
:erb
|
1091
|
+
end
|
1167
1092
|
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1093
|
+
def model_has_strings?
|
1094
|
+
false
|
1095
|
+
end
|
1096
|
+
|
1097
|
+
def model_search_fields # an array of fields we can search on
|
1098
|
+
[]
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
def form_fields_html
|
1102
|
+
@template_builder.all_form_fields(layout_strategy: @layout_strategy,
|
1103
|
+
layout_object: @layout_object)
|
1104
|
+
end
|
1105
|
+
|
1106
|
+
def list_label
|
1107
|
+
@list_label_heading
|
1108
|
+
end
|
1109
|
+
|
1110
|
+
def new_thing_label
|
1111
|
+
@new_thing_label
|
1112
|
+
end
|
1113
|
+
|
1114
|
+
def all_line_fields
|
1115
|
+
@template_builder.all_line_fields(
|
1116
|
+
col_identifier: @layout_strategy.column_classes_for_line_fields,
|
1117
|
+
perc_width: @layout_strategy.each_col, #undefined method `each_col'
|
1118
|
+
layout_strategy: @layout_strategy,
|
1119
|
+
layout_object: @layout_object
|
1120
|
+
)
|
1121
|
+
end
|
1122
|
+
|
1123
|
+
def controller_descends_from
|
1124
|
+
if defined?(@namespace.titlecase.gsub(" ", "") + "::BaseController")
|
1125
|
+
@namespace.titlecase.gsub(" ", "") + "::BaseController"
|
1126
|
+
else
|
1127
|
+
"ApplicationController"
|
1175
1128
|
end
|
1129
|
+
end
|
1176
1130
|
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1131
|
+
def display_class
|
1132
|
+
me = eval(singular_class)
|
1133
|
+
|
1134
|
+
@display_class ||=
|
1135
|
+
if me.column_names.include?("name") || me.instance_methods(false).include?(:name)
|
1136
|
+
# note that all class object respond_to?(:name) with the name of their own class
|
1137
|
+
# this one is unique
|
1138
|
+
"name"
|
1139
|
+
elsif me.column_names.include?("to_label") || me.instance_methods(false).include?(:to_label)
|
1140
|
+
"to_label"
|
1141
|
+
elsif me.column_names.include?("full_name") || me.instance_methods(false).include?(:full_name)
|
1142
|
+
"full_name"
|
1143
|
+
elsif me.column_names.include?("display_name") || me.instance_methods(false).include?(:display_name)
|
1144
|
+
"display_name"
|
1145
|
+
elsif me.column_names.include?("email") || me.instance_methods(false).include?(:email)
|
1146
|
+
"email"
|
1180
1147
|
else
|
1181
|
-
"
|
1148
|
+
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)"
|
1149
|
+
raise(HotGlue::Error, exit_message)
|
1182
1150
|
end
|
1183
|
-
|
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
|
1151
|
+
end
|
1206
1152
|
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1153
|
+
def destroy_action
|
1154
|
+
return false if @self_auth
|
1155
|
+
return !@no_delete
|
1156
|
+
end
|
1211
1157
|
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1158
|
+
def create_action
|
1159
|
+
return false if @self_auth
|
1160
|
+
return !@no_create
|
1161
|
+
end
|
1216
1162
|
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
end
|
1163
|
+
def namespace_with_slash
|
1164
|
+
if @namespace
|
1165
|
+
"#{@namespace}/"
|
1166
|
+
else
|
1167
|
+
""
|
1223
1168
|
end
|
1169
|
+
end
|
1224
1170
|
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1171
|
+
def paginate
|
1172
|
+
@template_builder.paginate(plural: plural)
|
1173
|
+
end
|
1228
1174
|
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1175
|
+
def controller_magic_button_update_actions
|
1176
|
+
@magic_buttons.collect{ |magic_button|
|
1177
|
+
" if #{singular}_params[:#{magic_button}]
|
1232
1178
|
begin
|
1233
1179
|
res = @#{singular}.#{magic_button}!
|
1234
1180
|
res = \"#{magic_button.titleize}ed.\" if res === true
|
@@ -1239,79 +1185,96 @@ module HotGlue
|
|
1239
1185
|
end
|
1240
1186
|
end"
|
1241
1187
|
|
1242
|
-
|
1243
|
-
|
1188
|
+
}.join("\n") + "\n"
|
1189
|
+
end
|
1244
1190
|
|
1245
1191
|
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1192
|
+
def controller_update_params_tap_away_magic_buttons
|
1193
|
+
@magic_buttons.collect{ |magic_button|
|
1194
|
+
".tap{ |ary| ary.delete('__#{magic_button}') }"
|
1195
|
+
}.join("")
|
1196
|
+
end
|
1251
1197
|
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1198
|
+
def controller_update_params_tap_away_alt_lookups
|
1199
|
+
@alt_lookups.collect{ |key, data|
|
1200
|
+
".tap{ |ary| ary.delete('__lookup_#{data[:lookup_as]}') }"
|
1201
|
+
}.join("")
|
1202
|
+
end
|
1257
1203
|
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
end
|
1204
|
+
def nested_for_turbo_id_list_constructor
|
1205
|
+
if @nested_set.any?
|
1206
|
+
'+ (((\'__\' + nested_for) if defined?(nested_for)) || "")'
|
1207
|
+
else
|
1208
|
+
""
|
1264
1209
|
end
|
1210
|
+
end
|
1265
1211
|
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
end
|
1212
|
+
def n_plus_one_includes
|
1213
|
+
if @associations.any? || @attachments.any?
|
1214
|
+
".includes(" + (@associations.map{|x| x} + @attachments.collect{|k,v| "#{k}_attachment"}).map{|x| ":#{x.to_s}"}.join(", ") + ")"
|
1215
|
+
else
|
1216
|
+
""
|
1272
1217
|
end
|
1218
|
+
end
|
1273
1219
|
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
end
|
1220
|
+
def nested_for_turbo_nested_constructor(top_level = true)
|
1221
|
+
instance_symbol = "@" if top_level
|
1222
|
+
instance_symbol = "" if !top_level
|
1223
|
+
if @nested_set.none?
|
1224
|
+
"\"\""
|
1225
|
+
else
|
1226
|
+
@nested_set.collect{|arg|
|
1227
|
+
"(((\"__#{arg[:singular]}-\#{" + "@" + arg[:singular] + ".id}\") if @" + arg[:singular] + ") || \"\")"
|
1228
|
+
}.join(" + ")
|
1284
1229
|
end
|
1230
|
+
end
|
1285
1231
|
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
end
|
1232
|
+
def nested_for_assignments_constructor(top_level = true)
|
1233
|
+
instance_symbol = "@" if top_level
|
1234
|
+
instance_symbol = "" if !top_level
|
1235
|
+
if @nested_set.none?
|
1236
|
+
""
|
1237
|
+
else
|
1238
|
+
", \n nested_for: \"" + @nested_set.collect{|a| "#{a[:singular]}-" + '#{' + instance_symbol + a[:singular] + ".id}"}.join("__") + "\""
|
1294
1239
|
end
|
1240
|
+
end
|
1295
1241
|
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1242
|
+
private # thor does something fancy like sending the class all of its own methods during some strange run sequence
|
1243
|
+
# does not like public methods
|
1244
|
+
def cc_filename_with_extensions(name, file_format = format)
|
1245
|
+
[name, file_format].compact.join(".")
|
1246
|
+
end
|
1301
1247
|
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1248
|
+
def hawk_to_ruby
|
1249
|
+
res = @hawk_keys.collect{ |k,v|
|
1250
|
+
"#{k.to_s}: [#{v[:bind_to].join(".")}]"
|
1251
|
+
}.join(", ")
|
1252
|
+
res
|
1253
|
+
end
|
1308
1254
|
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1255
|
+
def controller_attachment_orig_filename_pickup_syntax
|
1256
|
+
@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")
|
1257
|
+
end
|
1312
1258
|
|
1313
|
-
|
1314
|
-
|
1259
|
+
def any_datetime_fields?
|
1260
|
+
(@columns - @attachments.keys.collect(&:to_sym)).collect{|col| eval("#{singular_class}.columns_hash['#{col}']").type}.include?(:datetime)
|
1261
|
+
end
|
1262
|
+
|
1263
|
+
def post_action_parental_updates
|
1264
|
+
if @nested_set.any?
|
1265
|
+
"\n" + @nested_set.collect{ |data|
|
1266
|
+
parent = data[:singular]
|
1267
|
+
"@#{singular}.#{parent}.reload"
|
1268
|
+
}.join("\n")
|
1315
1269
|
end
|
1316
1270
|
end
|
1271
|
+
|
1272
|
+
|
1273
|
+
def turbo_parental_updates
|
1274
|
+
@nested_set.collect{| data|
|
1275
|
+
"<%= turbo_stream.replace \"#{@namespace + '__' if @namespace}\#{dom_id(@#{data[:singular]})}\" do %>
|
1276
|
+
<%= render partial: \"#{@namespace}/#{data[:plural]}/edit\", locals: {#{data[:singular]}: @#{singular}.#{data[:singular]}.reload} %>
|
1277
|
+
<% end %>"
|
1278
|
+
}.join("\n")
|
1279
|
+
end
|
1317
1280
|
end
|