common_core_js 0.1.0 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.generators +8 -0
  3. data/.gitignore +16 -0
  4. data/.rakeTasks +7 -0
  5. data/Gemfile +15 -0
  6. data/Gemfile.lock +175 -0
  7. data/LICENSE +2 -2
  8. data/README.md +147 -34
  9. data/app/assets/images/common_core_js/.keep +0 -0
  10. data/app/assets/stylesheets/common_core_js/common_core.scss +43 -0
  11. data/app/helpers/common_core_js/application_helper.rb +76 -0
  12. data/app/views/common/_common_create.js.erb +1 -1
  13. data/bin/rails +14 -0
  14. data/common_core_js.gemspec +70 -0
  15. data/lib/common_core_js.rb +20 -0
  16. data/lib/common_core_js/engine.rb +3 -1
  17. data/lib/common_core_js/version.rb +1 -1
  18. data/lib/generators/common_core/USAGE +2 -4
  19. data/lib/generators/common_core/install_generator.rb +22 -0
  20. data/lib/generators/common_core/scaffold_generator.rb +327 -30
  21. data/lib/generators/common_core/templates/_edit.haml +1 -1
  22. data/lib/generators/common_core/templates/_errors.haml +5 -0
  23. data/lib/generators/common_core/templates/_flash_notices.haml +7 -0
  24. data/lib/generators/common_core/templates/_form.haml +1 -0
  25. data/lib/generators/common_core/templates/_line.haml +3 -0
  26. data/lib/generators/common_core/templates/_list.haml +1 -1
  27. data/lib/generators/common_core/templates/_new.haml +1 -1
  28. data/lib/generators/common_core/templates/all.haml +4 -0
  29. data/lib/generators/common_core/templates/common_core.js +52 -0
  30. data/lib/generators/common_core/templates/common_core.scss +0 -0
  31. data/lib/generators/common_core/templates/controller.rb +6 -7
  32. data/lib/generators/common_core/templates/controller_spec.rb +110 -0
  33. data/lib/generators/common_core/templates/edit.js.erb +1 -1
  34. data/lib/generators/common_core/templates/update.js.erb +1 -1
  35. data/lib/tasks/common_core_js_tasks.rake +7 -4
  36. metadata +105 -42
  37. data/lib/version.rb +0 -4
File without changes
@@ -0,0 +1,43 @@
1
+
2
+ [data-role='close-button'] {
3
+ position: absolute;
4
+ top: 0;
5
+ right: 0;
6
+ }
7
+
8
+
9
+ i {
10
+ cursor: pointer;
11
+ }
12
+
13
+
14
+ .show-area{
15
+ span.content {
16
+ background-color: #ddd;
17
+ padding: 0px 6px;
18
+ display: inline-block;
19
+ }
20
+ }
21
+
22
+
23
+ td.paginate{
24
+ position: relative;
25
+ }
26
+
27
+ nav.pagination {
28
+ display: block;
29
+ text-align: right;
30
+ right: 0;
31
+ top: 0;
32
+
33
+ font-size: 1.1em;
34
+
35
+ span {
36
+ margin: 0 2px;
37
+ }
38
+ span.page.current {
39
+ color: black;
40
+ text-decoration: underline;
41
+
42
+ }
43
+ }
@@ -1,4 +1,80 @@
1
1
  module CommonCoreJs
2
2
  module ApplicationHelper
3
+
4
+ def datetime_field_localized(form_object, field_name, value, label, timezone = nil )
5
+ res = form_object.label(label,
6
+ field_name,
7
+ class: 'small form-text text-muted')
8
+
9
+ res << form_object.text_field(field_name, class: 'form-control',
10
+ type: 'datetime-local',
11
+ value: date_to_current_timezone(value, timezone))
12
+
13
+ res << human_timezone(Time.now, timezone)
14
+ res
15
+ end
16
+
17
+
18
+ def date_field_localized(form_object, field_name, value, label, timezone = nil )
19
+ res = form_object.label(label,
20
+ field_name,
21
+ class: 'small form-text text-muted')
22
+
23
+ res << form_object.text_field(field_name, class: 'form-control',
24
+ type: 'date',
25
+ value: date_to_current_timezone(value, timezone))
26
+
27
+ res
28
+ end
29
+
30
+ def time_field_localized(form_object, field_name, value, label, timezone = nil )
31
+ res = form_object.label(label,
32
+ field_name,
33
+ class: 'small form-text text-muted')
34
+
35
+ res << form_object.text_field(field_name, class: 'form-control',
36
+ type: 'time',
37
+ value: date_to_current_timezone(value, timezone))
38
+
39
+ res << human_timezone(Time.now, timezone)
40
+ res
41
+ end
42
+
43
+ def current_timezone
44
+ if method(:current_user)
45
+ if current_user.try(:timezone)
46
+ Time.now.in_time_zone(current_user.timezone).strftime("%z").to_i/100
47
+ else
48
+ Time.now.strftime("%z").to_i/100
49
+ end
50
+ else
51
+ raise "no method current_user is available or it does not implement timezone; please implement/override the method current_timezone"
52
+ end
53
+ end
54
+
55
+ def human_timezone(time_string, timezone)
56
+ time = time_string.in_time_zone(timezone)
57
+
58
+ if time.zone.match?(/^\w/)
59
+ time.zone
60
+ else
61
+ time.formatted_offset
62
+ end
63
+ end
64
+
65
+ def date_to_current_timezone(date, timezone = nil)
66
+ # if the timezone is nil, use the server date'
67
+ if timezone.nil?
68
+ timezone = Time.now.strftime("%z").to_i/100
69
+ end
70
+
71
+ return nil if date.nil?
72
+
73
+ begin
74
+ return date.in_time_zone(timezone).strftime("%Y-%m-%dT%H:%M")
75
+ rescue
76
+ return nil
77
+ end
78
+ end
3
79
  end
4
80
  end
@@ -8,7 +8,7 @@
8
8
 
9
9
  <% if object.errors.any? %>
10
10
  $(".flash-notices").html("<%= j render 'layouts/flash_notices' %>");
11
- $("<%= (scope + " ") if controller.common_scope %> .new-<%=singular%>-form").html("<%= j render(partial: '#{controller.namespace}errors', locals: {resource: object}) %>")
11
+ $("<%= (scope + " ") if controller.common_scope %> .new-<%=singular%>-form").html('<%= j render(partial: "#{controller.namespace}errors", locals: {resource: object}) %>')
12
12
  $("<%= (scope + " ") if controller.common_scope %> .new-<%=singular%>-form").append("<%= j render(partial: "new", locals: { singular.to_sym => object}) %><i class='fa fa-times-circle fa-2x' data-name='<%=singular%>' data-role='close-button' />").slideDown();
13
13
  <% else %>
14
14
  $("<%= (scope + " ") if controller.common_scope %> .new-<%=singular%>-form").slideUp();
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path('..', __dir__)
6
+ ENGINE_PATH = File.expand_path('../lib/common_core_js/engine', __dir__)
7
+ APP_PATH = File.expand_path('../test/dummy/config/application', __dir__)
8
+
9
+ # Set up gems listed in the Gemfile.
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
11
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
12
+
13
+ require 'rails/all'
14
+ require 'rails/engine/commands'
@@ -0,0 +1,70 @@
1
+ $:.push File.expand_path("lib", __dir__)
2
+
3
+ # Maintain your gem's version:
4
+ require "common_core_js/version"
5
+ require 'byebug'
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "common_core_js"
9
+ spec.version = CommonCoreJs::VERSION
10
+ spec.license = 'MIT'
11
+ spec.date = '2020-06-28'
12
+ spec.summary = "A gem build scaffolding."
13
+ spec.description = "Simple, plug & play Rails scaffolding with really simple Javascript"
14
+ spec.authors = ["Jason Fleetwood-Boldt"]
15
+ spec.email = 'jason.fb@datatravels.com'
16
+
17
+
18
+
19
+
20
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
21
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
22
+ if spec.respond_to?(:metadata)
23
+ spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
24
+ else
25
+ raise "RubyGems 2.0 or newer is required to protect against " \
26
+ "public gem pushes."
27
+ end
28
+
29
+ # spec.files = Dir["{app,config,db,lib,vendor}/**/*", "LICENSE", "Rakefile", "README.md"]
30
+
31
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
32
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
33
+ end
34
+
35
+ spec.add_dependency "rails"
36
+ spec.homepage = 'https://blog.jasonfleetwoodboldt.com/common-core-js/'
37
+ spec.metadata = { "source_code_uri" => "https://github.com/jasonfb/common_core_js",
38
+ "documentation_uri" => "https://github.com/jasonfb/common_core_js",
39
+ "homepage_uri" => 'https://blog.jasonfleetwoodboldt.com/common-core-js/',
40
+ "mailing_list_uri" => 'https://blog.jasonfleetwoodboldt.com/#sfba-form2-container'
41
+ }
42
+
43
+ spec.add_runtime_dependency('kaminari')
44
+ spec.add_runtime_dependency('haml-rails')
45
+ spec.add_runtime_dependency "sass-rails"
46
+
47
+ spec.add_runtime_dependency 'bootsnap'
48
+ spec.add_runtime_dependency 'bootstrap'
49
+ spec.add_runtime_dependency 'font-awesome-rails'
50
+ spec.add_dependency 'ffaker'
51
+
52
+ spec.post_install_message = <<~MSG
53
+ ---------------------------------------------
54
+ Welcome to Common Core
55
+
56
+ rails generate common_score:scaffold Thing
57
+
58
+ * Build plug-and-play scaffolding mixing HAML with jQuery-based Javascript
59
+ * Automatically Reads Your Models (make them before building your scaffolding!)
60
+ * Excellent for CRUD, lists with pagination, searching, sorting.
61
+ * Wonderful for prototyping.
62
+ * Plays nicely with Devise, Kaminari, Haml-Rails, Rspec.
63
+ * Create specs autoamatically along with the controllers.
64
+ * Nest your routes model-by-model for built-in poor man's authentication
65
+ * Throw the scaffolding away when your app is ready to graduate to its next phase.
66
+
67
+ see README for complete instructions.
68
+ ---------------------------------------------
69
+ MSG
70
+ end
@@ -6,4 +6,24 @@ require 'haml-rails'
6
6
 
7
7
  module CommonCoreJs
8
8
  # Your code goes here...
9
+ #
10
+ module ControllerHelpers
11
+ def modify_date_inputs_on_params(modified_params, authenticated_user = nil)
12
+ use_timezone = authenticated_user.timezone || Time.now.strftime("%z")
13
+
14
+ modified_params = modified_params.tap do |params|
15
+ params.keys.each{|k|
16
+ if k.ends_with?("_at") || k.ends_with?("_date")
17
+
18
+ begin
19
+ params[k] = DateTime.strptime("#{params[k]} #{use_timezone}", '%Y-%m-%dT%H:%M %z')
20
+ rescue StandardError
21
+
22
+ end
23
+ end
24
+ }
25
+ end
26
+ modified_params
27
+ end
28
+ end
9
29
  end
@@ -1,5 +1,7 @@
1
1
  module CommonCoreJs
2
2
  class Engine < ::Rails::Engine
3
- isolate_namespace CommonCoreJs
3
+ # isolate_namespace CommonCoreJs
4
+
5
+
4
6
  end
5
7
  end
@@ -1,3 +1,3 @@
1
1
  module CommonCoreJs
2
- VERSION = '0.1.0'
2
+ VERSION = '0.3.3'
3
3
  end
@@ -1,8 +1,6 @@
1
1
  Description:
2
- Explain the generator
2
+ Generate a controller, view files, and spec
3
3
 
4
4
  Example:
5
- rails generate common_core_scaffold Thing
5
+ rails generate common_core:scaffold Thing
6
6
 
7
- This will create:
8
- what/will/it/create
@@ -0,0 +1,22 @@
1
+ require 'rails/generators/erb/scaffold/scaffold_generator'
2
+ require 'ffaker'
3
+
4
+ module CommonCore
5
+ class InstallGenerator < Rails::Generators::Base
6
+ hook_for :form_builder, :as => :scaffold
7
+
8
+ source_root File.expand_path('templates', __dir__)
9
+
10
+
11
+ def initialize(*args) #:nodoc:
12
+ super
13
+ copy_file "common_core.js", "app/javascript/common_core.js"
14
+ copy_file "common_core.scss", "app/assets/stylesheets/common_core.scss"
15
+ copy_file "_flash_notices.haml", "app/views/layouts/_flash_notices.haml"
16
+
17
+ end
18
+ end
19
+ end
20
+
21
+
22
+
@@ -1,15 +1,46 @@
1
1
  require 'rails/generators/erb/scaffold/scaffold_generator'
2
+ require 'ffaker'
3
+
4
+
2
5
 
3
6
  module CommonCore
4
- class ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
7
+
8
+ module GeneratorHelper
9
+ def text_area_output(col, field_length)
10
+ lines = field_length % 40
11
+ if lines > 5
12
+ lines = 5
13
+ end
14
+
15
+ ".row
16
+ .form-group.col-md-4
17
+ = f.text_area :#{col.to_s}, class: 'form-control', cols: 40, rows: '#{lines}'
18
+ %label.form-text
19
+ #{col.to_s.humanize}\n"
20
+ end
5
21
 
6
22
 
23
+
24
+ def field_output(col, type = nil, width)
25
+ ".row
26
+ .form-group.col-md-4
27
+ = f.text_field :#{col.to_s}, value: @#{singular}.#{col.to_s}, size: #{width}, class: 'form-control', type: '#{type}'
28
+ %label.form-text
29
+ #{col.to_s.humanize}\n"
30
+ end
31
+ end
32
+
33
+
34
+ class ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
7
35
  hook_for :form_builder, :as => :scaffold
8
36
 
9
37
  source_root File.expand_path('templates', __dir__)
10
38
  attr_accessor :path, :singular, :plural, :singular_class, :nest_with
11
39
 
12
40
 
41
+ include GeneratorHelper
42
+
43
+
13
44
  def initialize(*meta_args) #:nodoc:
14
45
  super
15
46
 
@@ -20,21 +51,12 @@ module CommonCore
20
51
  exit
21
52
  end
22
53
 
23
- begin
24
- @columns = object.columns.map(&:name).map(&:to_sym).reject{|x| x==:updated_at || x==:created_at || x==:id}
25
- rescue StandardError => e
26
- puts "Ooops... it looks like is an object for #{class_name}. Please create the database table with fields first. "
27
- exit
28
- end
54
+
29
55
 
30
56
  args = meta_args[0]
31
57
  @singular = args[0].tableize.singularize # should be in form hello_world
32
58
 
33
59
 
34
-
35
-
36
-
37
-
38
60
  @plural = @singular + "s" # supply to override; leave blank to use default
39
61
  @singular_class = @singular.titleize.gsub(" ", "")
40
62
  @nest = nil
@@ -61,8 +83,18 @@ module CommonCore
61
83
  end
62
84
  end
63
85
 
86
+ auth_assoc = @auth.gsub("current_","")
87
+ auth_assoc_field = auth_assoc + "_id"
64
88
 
65
89
 
90
+ begin
91
+ @columns = object.columns.map(&:name).map(&:to_sym).reject{|field| field==:updated_at ||
92
+ field==:created_at || field==:id || field == auth_assoc_field.to_sym }
93
+ rescue StandardError => e
94
+ puts "Ooops... it looks like is an object for #{class_name}. Please create the database table with fields first. "
95
+ exit
96
+ end
97
+
66
98
  flags = meta_args[1]
67
99
  flags.each do |f|
68
100
  case (f)
@@ -70,10 +102,17 @@ module CommonCore
70
102
  @auth = nil
71
103
  when "--with-index"
72
104
  @with_index = true
105
+ when "--specs-only"
106
+ @specs_only = true
107
+ when "--no-specs"
108
+ @no_specs = true
73
109
  end
74
110
  end
75
111
 
76
-
112
+ if @specs_only && @no_specs
113
+ puts "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. sorry."
114
+ exit
115
+ end
77
116
 
78
117
  if @auth_identifier.nil? && !@auth.nil?
79
118
  @auth_identifier = @auth.gsub("current_", "")
@@ -86,7 +125,6 @@ module CommonCore
86
125
  @nested_args.each do |a|
87
126
  @nested_args_plural[a] = a + "s"
88
127
  end
89
-
90
128
  end
91
129
  end
92
130
 
@@ -99,20 +137,77 @@ module CommonCore
99
137
  end
100
138
 
101
139
  def copy_controller_and_spec_files
102
-
103
140
  @default_colspan = @columns.size
104
- template "controller.rb", File.join("app/controllers", "#{plural}_controller.rb")
105
- # template "index", File.join("app/views", "app/views/#{self.name.downcase}/index")
106
141
 
107
- end
142
+ unless @specs_only
143
+ template "controller.rb", File.join("app/controllers#{namespace_with_dash}", "#{plural}_controller.rb")
144
+ end
145
+
146
+ unless @no_specs
147
+ template "controller_spec.rb", File.join("spec/controllers#{namespace_with_dash}", "#{plural}_controller_spec.rb")
148
+ end
108
149
 
150
+ template "_errors.haml", File.join("app/views#{namespace_with_dash}", "_errors.haml")
151
+ end
109
152
 
110
153
  def list_column_headings
111
154
  @columns.map(&:to_s).map{|col_name| ' %th{:scope => "col"} ' + col_name.humanize}.join("\r")
112
155
  end
113
156
 
157
+ def columns_spec_with_sample_data
158
+ @columns.map { |c|
159
+ if eval("#{singular_class}.columns_hash['#{c}']").nil?
160
+ byebug
161
+ end
162
+ type = eval("#{singular_class}.columns_hash['#{c}']").type
163
+ random_data = case type
164
+ when :integer
165
+ rand(1...1000)
166
+ when :string
167
+ FFaker::AnimalUS.common_name
168
+ when :text
169
+ FFaker::AnimalUS.common_name
170
+ when :datetime
171
+ Time.now + rand(1..5).days
172
+ end
173
+ c.to_s + ": '" + random_data.to_s + "'"
174
+ }.join(", ")
175
+ end
176
+
177
+ def object_parent_mapping_as_argument_for_specs
178
+ if @nested_args.any?
179
+ ", " + @nested_args.last + ": " + @nested_args.last
180
+ elsif @auth
181
+ ", #{@auth_identifier}: #{@auth}"
182
+ end
183
+ end
184
+
185
+ def objest_nest_factory_setup
186
+ res = ""
187
+ if @auth
188
+ last_parent = ", #{@auth_identifier}: #{@auth}"
189
+ end
190
+
191
+ @nested_args.each do |arg|
192
+ res << " let(:#{arg}) {create(:#{arg} #{last_parent} )}\n"
193
+ last_parent = ", #{arg}: #{arg}"
194
+ end
195
+ res
196
+ end
197
+
198
+
199
+ def objest_nest_params_by_id_for_specs
200
+ @nested_args.map{|arg|
201
+ "#{arg}_id: #{arg}.id"
202
+ }.join(",\n ")
203
+ end
204
+
205
+
114
206
  def controller_class_name
115
- plural.titleize.gsub(" ", "") + "Controller"
207
+ res = ""
208
+ res << @namespace.titleize + "::" if @namespace
209
+ res << plural.titleize.gsub(" ", "") + "Controller"
210
+ res
116
211
  end
117
212
 
118
213
  def singular_name
@@ -128,20 +223,26 @@ module CommonCore
128
223
  end
129
224
 
130
225
 
131
- def path_helper
226
+ def path_helper_singular
132
227
  "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{singular}_path"
133
228
  end
134
229
 
230
+ def path_helper_plural
231
+ "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{plural}_path"
232
+ end
135
233
 
136
234
  def path_arity
137
- (nested_objects_arity + ", " if @nested_args) + "@" + singular
235
+ res = ""
236
+ if @nested_args.any?
237
+ res << nested_objects_arity + ", "
238
+ end
239
+ res << "@" + singular
138
240
  end
139
241
 
140
242
  def line_path_partial
141
- "#{@namespace+"/" if @namespace}#{singular}/line"
243
+ "#{@namespace+"/" if @namespace}#{plural}/line"
142
244
  end
143
245
 
144
-
145
246
  def nested_assignments
146
247
  @nested_args.map{|a| "#{a}: @#{a}"}.join(", ") #metaprgramming into Ruby hash
147
248
  end
@@ -166,13 +267,26 @@ module CommonCore
166
267
  end
167
268
  end
168
269
 
270
+
271
+ def all_objects_root
272
+ if @auth
273
+ if @nested_args.none?
274
+ @auth + ".#{plural}"
275
+ else
276
+ "@" + @nested_args.last + ".#{plural}"
277
+ end
278
+ else
279
+ @singular_class + ".all"
280
+ end
281
+ end
282
+
169
283
  def any_nested?
170
284
  @nested_args.any?
171
285
  end
172
286
 
173
287
  def all_objects_variable
174
288
  # needs the authenticated root user
175
- "#{@auth}#{'.' + @nested_args.map{|a| "#{@nested_args_plural[a]}.find(@#{a})"}.join('.') + "." if @nested_args}#{plural}"
289
+ "#{@auth}.#{ @nested_args.map{|a| "#{@nested_args_plural[a]}.find(@#{a})"}.join('.') + "." if @nested_args.any?}#{plural}"
176
290
  end
177
291
 
178
292
  def auth_object
@@ -180,29 +294,49 @@ module CommonCore
180
294
  end
181
295
 
182
296
  def copy_view_files
297
+ return if @specs_only
183
298
  js_views.each do |view|
184
299
  formats.each do |format|
185
-
186
300
  filename = cc_filename_with_extensions(view, ["js","erb"])
187
- template filename, File.join("app/views", controller_file_path, filename)
301
+ template filename, File.join("app/views#{namespace_with_dash}", controller_file_path, filename)
188
302
  end
189
303
  end
190
304
 
305
+
191
306
  haml_views.each do |view|
192
307
  formats.each do |format|
193
-
194
308
  filename = cc_filename_with_extensions(view, "haml")
195
- template filename, File.join("app/views", controller_file_path, filename)
309
+ template filename, File.join("app/views#{namespace_with_dash}", controller_file_path, filename)
196
310
  end
197
311
  end
198
312
  end
199
313
 
314
+ def namespace_with_dash
315
+ if @namespace
316
+ "/#{@namespace}"
317
+ else
318
+ ""
319
+ end
320
+ end
321
+
322
+ def namespace_with_trailing_dash
323
+ if @namespace
324
+ "#{@namespace}/"
325
+ else
326
+ ""
327
+ end
328
+ end
329
+
200
330
  def js_views
201
331
  %w(index create destroy edit new update)
202
332
  end
203
333
 
204
334
  def haml_views
205
- %w(_edit _form _line _list _new)
335
+ res = %w(_edit _form _line _list _new)
336
+ if @with_index
337
+ res << 'all'
338
+ end
339
+ res
206
340
  end
207
341
 
208
342
 
@@ -214,11 +348,11 @@ module CommonCore
214
348
  def create_merge_params
215
349
  if @auth
216
350
  "#{@auth_identifier}: #{@auth}"
351
+ else
352
+ ""
217
353
  end
218
354
  end
219
355
 
220
-
221
-
222
356
  def model_has_strings?
223
357
  false
224
358
  end
@@ -228,6 +362,169 @@ module CommonCore
228
362
  []
229
363
  end
230
364
 
365
+ def all_form_fields
366
+ res = @columns.map { |col|
367
+
368
+
369
+ type = eval("#{singular_class}.columns_hash['#{col}']").type
370
+ limit = eval("#{singular_class}.columns_hash['#{col}']").limit
371
+ sql_type = eval("#{singular_class}.columns_hash['#{col}']").sql_type
372
+
373
+ case type
374
+ when :integer
375
+ # look for a belongs_to on this object
376
+ if col.to_s.ends_with?("_id")
377
+ # guess the association name label
378
+
379
+
380
+ assoc_name = col.to_s.gsub("_id","")
381
+ assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
382
+ if assoc.nil?
383
+ puts "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
384
+ exit
385
+ end
386
+
387
+ if assoc.active_record.column_names.include?("name")
388
+ display_column = "name"
389
+ elsif assoc.active_record.column_names.include?("to_label")
390
+ display_column = "to_label"
391
+ elsif assoc.active_record.column_names.include?("full_name")
392
+ display_column = "full_name"
393
+ elsif assoc.active_record.column_names.include?("display_name")
394
+ display_column = "display_name"
395
+ elsif assoc.active_record.column_names.include?("email")
396
+ display_column = "email"
397
+ end
398
+
399
+ ".row
400
+ .form-group.col-md-4
401
+ = f.collection_select(:#{col.to_s}, #{assoc_name.titleize}.all, :id, :#{display_column}, {prompt: true, selected: @#{singular}.#{col.to_s} }, class: 'form-control')
402
+ %label.small.form-text.text-muted
403
+ #{col.to_s.humanize}"
404
+
405
+ else
406
+ ".row
407
+ .form-group.col-md-4
408
+ = f.text_field :#{col.to_s}, value: @#{singular}.#{col.to_s}, class: 'form-control', size: 4, type: 'number'
409
+ %label.form-text
410
+ #{col.to_s.humanize}\n"
411
+ end
412
+ when :string
413
+ limit ||= 40
414
+ if limit < 50
415
+ field_output(col, nil, limit)
416
+ else
417
+ text_area_output(col, limit)
418
+ end
419
+
420
+ when :text
421
+ limit ||= 40
422
+ if limit < 50
423
+ field_output(col, nil, limit)
424
+ else
425
+ text_area_output(col, limit)
426
+ end
427
+
428
+ when :datetime
429
+ ".row
430
+ .form-group.col-md-4
431
+ = datetime_field_localized(f, :#{col.to_s}, @#{singular}.#{col.to_s}, '#{col.to_s.humanize}', #{@auth}.timezone)"
432
+ when :date
433
+ ".row
434
+ .form-group.col-md-4
435
+ = date_field_localized(f, :#{col.to_s}, @#{singular}.#{col.to_s}, '#{col.to_s.humanize}', #{@auth}.timezone)"
436
+ when :time
437
+ ".row
438
+ .form-group.col-md-4
439
+ = time_field_localized(f, :#{col.to_s}, @#{singular}.#{col.to_s}, '#{col.to_s.humanize}', #{@auth}.timezone)"
440
+
441
+ end
442
+
443
+ }.join("\n")
444
+ return res
445
+ end
446
+
447
+
448
+ def all_line_fields
449
+ res = "%tr{'data-id': #{singular}.id, 'data-edit': 'false'}\n"
450
+
451
+ res << @columns.map { |col|
452
+ type = eval("#{singular_class}.columns_hash['#{col}']").type
453
+ limit = eval("#{singular_class}.columns_hash['#{col}']").limit
454
+ sql_type = eval("#{singular_class}.columns_hash['#{col}']").sql_type
455
+
456
+ case type
457
+ when :integer
458
+ # look for a belongs_to on this object
459
+ if col.to_s.ends_with?("_id")
460
+
461
+ assoc_name = col.to_s.gsub("_id","")
462
+
463
+
464
+ assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
465
+
466
+ if assoc.nil?
467
+ puts "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
468
+ exit
469
+ end
470
+
471
+ if assoc.active_record.column_names.include?("name")
472
+ display_column = "name"
473
+ elsif assoc.active_record.column_names.include?("to_label")
474
+ display_column = "to_label"
475
+ elsif assoc.active_record.column_names.include?("full_name")
476
+ display_column = "full_name"
477
+ elsif assoc.active_record.column_names.include?("display_name")
478
+ display_column = "display_name"
479
+ elsif assoc.active_record.column_names.include?("email")
480
+ display_column = "email"
481
+ else
482
+ puts "cant find any column to use as label for #{assoc.name.to_s}; any of name, to_labe, full_name, display_name, or email"
483
+ end
484
+
485
+ " %td
486
+ = #{singular}.#{assoc.name.to_s}.#{display_column}"
487
+
488
+ else
489
+ " %td
490
+ = #{singular}.#{col}"
491
+ end
492
+ when :string
493
+ width = (limit && limit < 40) ? limit : (40)
494
+ " %td
495
+ = #{singular}.#{col}"
496
+ when :text
497
+ " %td
498
+ = #{singular}.#{col}"
499
+ when :datetime
500
+ " %td
501
+ - unless #{singular}.#{col}.nil?
502
+ = #{singular}.#{col}.in_time_zone(current_timezone).strftime('%m/%d/%Y @ %l:%M %p ') + human_timezone(Time.now, current_timezone)
503
+ - else
504
+ %span.alert-danger
505
+ MISSING
506
+ "
507
+ when :date
508
+ " %td
509
+ - unless #{singular}.#{col}.nil?
510
+ = #{singular}.#{col}
511
+ - else
512
+ %span.alert-danger
513
+ "
514
+ when :time
515
+ " %td
516
+ - unless #{singular}.#{col}.nil?
517
+ = #{singular}.#{col}.in_time_zone(current_timezone).strftime('%l:%M %p ') + human_timezone(Time.now, current_timezone)
518
+ - else
519
+ %span.alert-danger
520
+ "
521
+
522
+ end
523
+ }.join("\n")
524
+ return res
525
+ end
526
+
527
+
231
528
 
232
529
  private # thor does something fancy like sending the class all of its own methods during some strange run sequence
233
530
  # does not like public methods