common_core_js 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }
@@ -0,0 +1,37 @@
1
+
2
+ require("jquery")
3
+ console.log("loading common core...")
4
+ debugger
5
+ $(function(){
6
+ // always pass csrf tokens on ajax calls
7
+ $.ajaxSetup({
8
+ headers: { 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content') }
9
+ });
10
+ });
11
+
12
+ $(document).on('turbolinks:load', function() {
13
+ $(document).ready(() => {
14
+ $("body").on("click", "[data-role='close-button']", (event) => {
15
+ var form_name;
16
+ form_name = $(event.currentTarget).data("name");
17
+ row_id = $(event.currentTarget).data("row-id");
18
+
19
+ if (row_id) {
20
+ $("table." + form_name + "-table tr[data-id=" + row_id + "][data-edit='true']").remove()
21
+ $("table." + form_name + "-table tr[data-id=" + row_id + "]:not([data-edit='true'])").fadeIn()
22
+ $("table." + form_name + "-table tr[data-id=" + row_id + "]:not([data-edit='true']) .show-area").show()
23
+ } else {
24
+ if ($(".new-" + form_name + "-form").length == 0) {
25
+ throw("ERROR: not found" + " .new-" + form_name + "-form")
26
+ }
27
+ var $form = $(event.currentTarget).closest(".new-" + form_name + "-form")
28
+ $form.slideUp()
29
+ $form.siblings(".new-" + form_name + "-button").fadeIn()
30
+ $form.find("i").remove()
31
+ }
32
+ })
33
+ })
34
+ });
35
+
36
+
37
+
@@ -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,69 @@
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
+
51
+ spec.post_install_message = <<~MSG
52
+ ---------------------------------------------
53
+ Welcome to Common Core
54
+
55
+ rails generate common_score:scaffold Thing
56
+
57
+ * Build plug-and-play scaffolding mixing HAML with jQuery-based Javascript
58
+ * Automatically Reads Your Models (make them before building your scaffolding!)
59
+ * Excellent for CRUD, lists with pagination, searching, sorting.
60
+ * Wonderful for prototyping.
61
+ * Plays nicely with Devise, Kaminari, Haml-Rails, Rspec.
62
+ * Create specs autoamatically along with the controllers.
63
+ * Nest your routes model-by-model for built-in poor man's authentication
64
+ * Throw the scaffolding away when your app is ready to graduate to its next phase.
65
+
66
+ see README for complete instructions.
67
+ ---------------------------------------------
68
+ MSG
69
+ end
@@ -1,5 +1,5 @@
1
1
  module CommonCoreJs
2
2
  class Engine < ::Rails::Engine
3
- isolate_namespace CommonCoreJs
3
+ # isolate_namespace CommonCoreJs
4
4
  end
5
5
  end
@@ -1,3 +1,3 @@
1
1
  module CommonCoreJs
2
- VERSION = '0.1.1'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -2,8 +2,6 @@ require 'rails/generators/erb/scaffold/scaffold_generator'
2
2
 
3
3
  module CommonCore
4
4
  class ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
5
-
6
-
7
5
  hook_for :form_builder, :as => :scaffold
8
6
 
9
7
  source_root File.expand_path('templates', __dir__)
@@ -31,10 +29,6 @@ module CommonCore
31
29
  @singular = args[0].tableize.singularize # should be in form hello_world
32
30
 
33
31
 
34
-
35
-
36
-
37
-
38
32
  @plural = @singular + "s" # supply to override; leave blank to use default
39
33
  @singular_class = @singular.titleize.gsub(" ", "")
40
34
  @nest = nil
@@ -61,8 +55,6 @@ module CommonCore
61
55
  end
62
56
  end
63
57
 
64
-
65
-
66
58
  flags = meta_args[1]
67
59
  flags.each do |f|
68
60
  case (f)
@@ -70,10 +62,17 @@ module CommonCore
70
62
  @auth = nil
71
63
  when "--with-index"
72
64
  @with_index = true
65
+ when "--specs-only"
66
+ @specs_only = true
67
+ when "--no-specs"
68
+ @no_specs = true
73
69
  end
74
70
  end
75
71
 
76
-
72
+ if @specs_only && @no_specs
73
+ 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."
74
+ exit
75
+ end
77
76
 
78
77
  if @auth_identifier.nil? && !@auth.nil?
79
78
  @auth_identifier = @auth.gsub("current_", "")
@@ -86,7 +85,6 @@ module CommonCore
86
85
  @nested_args.each do |a|
87
86
  @nested_args_plural[a] = a + "s"
88
87
  end
89
-
90
88
  end
91
89
  end
92
90
 
@@ -99,20 +97,75 @@ module CommonCore
99
97
  end
100
98
 
101
99
  def copy_controller_and_spec_files
102
-
103
100
  @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
101
 
107
- end
102
+ unless @specs_only
103
+ template "controller.rb", File.join("app/controllers#{namespace_with_dash}", "#{plural}_controller.rb")
104
+ end
108
105
 
106
+ unless @no_specs
107
+ template "controller_spec.rb", File.join("spec/controllers#{namespace_with_dash}", "#{plural}_controller_spec.rb")
108
+ end
109
+ end
109
110
 
110
111
  def list_column_headings
111
112
  @columns.map(&:to_s).map{|col_name| ' %th{:scope => "col"} ' + col_name.humanize}.join("\r")
112
113
  end
113
114
 
115
+ def columns_spec_with_sample_data
116
+ @columns.map { |c|
117
+ if eval("#{singular_class}.columns_hash['#{c}']").nil?
118
+ byebug
119
+ end
120
+ type = eval("#{singular_class}.columns_hash['#{c}']").type
121
+ random_data = case type
122
+ when :integer
123
+ rand(1...1000)
124
+ when :string
125
+ FFaker::AnimalUS.common_name
126
+ when :text
127
+ FFaker::AnimalUS.common_name
128
+ when :datetime
129
+ Time.now + rand(1..5).days
130
+ end
131
+ c.to_s + ": '" + random_data.to_s + "'"
132
+ }.join(", ")
133
+ end
134
+
135
+ def object_parent_mapping_as_argument_for_specs
136
+ if @nested_args.any?
137
+ ", " + @nested_args.last + ": " + @nested_args.last
138
+ elsif @auth
139
+ ", #{@auth_identifier}: #{@auth}"
140
+ end
141
+ end
142
+
143
+ def objest_nest_factory_setup
144
+ res = ""
145
+ if @auth
146
+ last_parent = ", #{@auth_identifier}: #{@auth}"
147
+ end
148
+
149
+ @nested_args.each do |arg|
150
+ res << " let(:#{arg}) {create(:#{arg} #{last_parent} )}\n"
151
+ last_parent = ", #{arg}: #{arg}"
152
+ end
153
+ res
154
+ end
155
+
156
+
157
+ def objest_nest_params_by_id_for_specs
158
+ @nested_args.map{|arg|
159
+ "#{arg}_id: #{arg}.id"
160
+ }.join(",\n ")
161
+ end
162
+
163
+
114
164
  def controller_class_name
115
- plural.titleize.gsub(" ", "") + "Controller"
165
+ res = ""
166
+ res << @namespace.titleize + "::" if @namespace
167
+ res << plural.titleize.gsub(" ", "") + "Controller"
168
+ res
116
169
  end
117
170
 
118
171
  def singular_name
@@ -128,20 +181,26 @@ module CommonCore
128
181
  end
129
182
 
130
183
 
131
- def path_helper
184
+ def path_helper_singular
132
185
  "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{singular}_path"
133
186
  end
134
187
 
188
+ def path_helper_plural
189
+ "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{plural}_path"
190
+ end
135
191
 
136
192
  def path_arity
137
- (nested_objects_arity + ", " if @nested_args) + "@" + singular
193
+ res = ""
194
+ if @nested_args.any?
195
+ res << nested_objects_arity + ", "
196
+ end
197
+ res << "@" + singular
138
198
  end
139
199
 
140
200
  def line_path_partial
141
- "#{@namespace+"/" if @namespace}#{singular}/line"
201
+ "#{@namespace+"/" if @namespace}#{plural}/line"
142
202
  end
143
203
 
144
-
145
204
  def nested_assignments
146
205
  @nested_args.map{|a| "#{a}: @#{a}"}.join(", ") #metaprgramming into Ruby hash
147
206
  end
@@ -166,13 +225,26 @@ module CommonCore
166
225
  end
167
226
  end
168
227
 
228
+
229
+ def all_objects_root
230
+ if @auth
231
+ if @nested_args.none?
232
+ @auth + ".#{plural}"
233
+ else
234
+ "@" + @nested_args.last + ".#{plural}"
235
+ end
236
+ else
237
+ @singular_class + ".all"
238
+ end
239
+ end
240
+
169
241
  def any_nested?
170
242
  @nested_args.any?
171
243
  end
172
244
 
173
245
  def all_objects_variable
174
246
  # needs the authenticated root user
175
- "#{@auth}#{'.' + @nested_args.map{|a| "#{@nested_args_plural[a]}.find(@#{a})"}.join('.') + "." if @nested_args}#{plural}"
247
+ "#{@auth}.#{ @nested_args.map{|a| "#{@nested_args_plural[a]}.find(@#{a})"}.join('.') + "." if @nested_args.any?}#{plural}"
176
248
  end
177
249
 
178
250
  def auth_object
@@ -180,29 +252,49 @@ module CommonCore
180
252
  end
181
253
 
182
254
  def copy_view_files
255
+ return if @specs_only
183
256
  js_views.each do |view|
184
257
  formats.each do |format|
185
-
186
258
  filename = cc_filename_with_extensions(view, ["js","erb"])
187
- template filename, File.join("app/views", controller_file_path, filename)
259
+ template filename, File.join("app/views#{namespace_with_dash}", controller_file_path, filename)
188
260
  end
189
261
  end
190
262
 
263
+
191
264
  haml_views.each do |view|
192
265
  formats.each do |format|
193
-
194
266
  filename = cc_filename_with_extensions(view, "haml")
195
- template filename, File.join("app/views", controller_file_path, filename)
267
+ template filename, File.join("app/views#{namespace_with_dash}", controller_file_path, filename)
196
268
  end
197
269
  end
198
270
  end
199
271
 
272
+ def namespace_with_dash
273
+ if @namespace
274
+ "/#{@namespace}"
275
+ else
276
+ ""
277
+ end
278
+ end
279
+
280
+ def namespace_with_trailing_dash
281
+ if @namespace
282
+ "#{@namespace}/"
283
+ else
284
+ ""
285
+ end
286
+ end
287
+
200
288
  def js_views
201
289
  %w(index create destroy edit new update)
202
290
  end
203
291
 
204
292
  def haml_views
205
- %w(_edit _form _line _list _new)
293
+ res = %w(_edit _form _line _list _new)
294
+ if @with_index
295
+ res << 'all'
296
+ end
297
+ res
206
298
  end
207
299
 
208
300
 
@@ -214,11 +306,11 @@ module CommonCore
214
306
  def create_merge_params
215
307
  if @auth
216
308
  "#{@auth_identifier}: #{@auth}"
309
+ else
310
+ ""
217
311
  end
218
312
  end
219
313
 
220
-
221
-
222
314
  def model_has_strings?
223
315
  false
224
316
  end
@@ -228,6 +320,106 @@ module CommonCore
228
320
  []
229
321
  end
230
322
 
323
+ def all_form_fields
324
+ res = @columns.map { |col|
325
+ # if eval("#{singular_class}.columns_hash['#{col}']").nil?
326
+ # byebug
327
+ # end
328
+
329
+ type = eval("#{singular_class}.columns_hash['#{col}']").type
330
+ limit = eval("#{singular_class}.columns_hash['#{col}']").limit
331
+ sql_type = eval("#{singular_class}.columns_hash['#{col}']").sql_type
332
+
333
+ case type
334
+ when :integer
335
+ # look for a belongs_to on this object
336
+ if col.to_s.ends_with?("_id")
337
+
338
+ assoc_name = col.to_s.gsub("_id","")
339
+ assoc = eval("#{singular_class}.reflect_on_association(':#{assoc_name}')")
340
+ ".row
341
+ .form-group.col-md-4
342
+ = f.collection_select(:#{col.to_s}, #{assoc_name.titleize}.all, :id, :to_label, {:prompt => true}, class: 'form-control')
343
+ %label.small.form-text.text-muted
344
+ #{col.to_s.humanize}"
345
+
346
+ else
347
+ ".row
348
+ .form-group.col-md-4
349
+ = f.text_field :#{col.to_s}, class: 'form-control', size: 4, type: 'number'
350
+ %label.form-text
351
+ #{col.to_s.humanize}\n"
352
+ end
353
+ when :string
354
+ width = (limit && limit < 40) ? limit : (40)
355
+ ".row
356
+ .form-group.col-md-4
357
+ = f.text_field :#{col.to_s}, size: #{width}, class: 'form-control'
358
+ %label.form-text
359
+ #{col.to_s.humanize}\n"
360
+ when :text
361
+ # width = (limit && limit < 40) ? limit : (40)
362
+ ".row
363
+ .form-group.col-md-4
364
+ = f.text_area :#{col.to_s}, rows: 4, cols: 40, class: 'form-control'
365
+ %label.form-text
366
+ #{col.humanize}\n"
367
+ when :datetime
368
+ ".row
369
+ .form-group.col-md-4
370
+ = f.text_field :#{col.to_s}, class: 'form-control', type: 'datetime-local'
371
+ %label.form-text
372
+ #{col.to_s.humanize}\n"
373
+ end
374
+ }.join("\n")
375
+ return res
376
+ end
377
+
378
+ def all_line_fields
379
+ res = "%tr{'data-id': #{singular}.id, 'data-edit': 'false'}\n"
380
+
381
+ res << @columns.map { |col|
382
+ type = eval("#{singular_class}.columns_hash['#{col}']").type
383
+ limit = eval("#{singular_class}.columns_hash['#{col}']").limit
384
+ sql_type = eval("#{singular_class}.columns_hash['#{col}']").sql_type
385
+
386
+ case type
387
+ when :integer
388
+ # look for a belongs_to on this object
389
+ if col.to_s.ends_with?("_id")
390
+
391
+ assoc_name = col.to_s.gsub("_id","")
392
+
393
+
394
+ assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
395
+
396
+ if assoc.nil?
397
+ raise "can't find assocation for #{assoc_name}"
398
+ end
399
+
400
+ " %td
401
+ = #{singular}.#{assoc.name.to_s}.to_label"
402
+
403
+ else
404
+ " %td
405
+ = #{singular}.#{col}"
406
+ end
407
+ when :string
408
+ width = (limit && limit < 40) ? limit : (40)
409
+ " %td
410
+ = #{singular}.#{col}"
411
+ when :text
412
+ " %td
413
+ = #{singular}.#{col}"
414
+ when :datetime
415
+ " %td
416
+ = #{singular}.#{col}"
417
+ end
418
+ }.join("\n")
419
+ return res
420
+ end
421
+
422
+
231
423
 
232
424
  private # thor does something fancy like sending the class all of its own methods during some strange run sequence
233
425
  # does not like public methods