bullet_train-super_scaffolding 1.0.28 → 1.0.29

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f442627a03e1aea9a33fd4d046a378d0177649eaffc3c1fef2d77cf6dc738b5b
4
- data.tar.gz: 67a9b22aa08ffe3f99ccd1ff88d1568b2d2d3ff247e53a3e96c96eb80b1a09a0
3
+ metadata.gz: 05b68451045068aa2ec97bb4198826333c702d2af995005b9cf0090e58254ed4
4
+ data.tar.gz: 1ea761bfa6ec36306bedae27ecbb51176fb03ff35581b0c5f66dbcf722f4f69e
5
5
  SHA512:
6
- metadata.gz: ef3e5a25df02bce626e7762b482d019852d3c61ba79096c34d8dbd5bfa63e5e939c8aed3755153d0b926086617b11804868609ac5195cda9d5438c988093707f
7
- data.tar.gz: b618a50a54582ca322650947f3b00b0d9fabc1c0383c17c8c6d265c5ee7eba3a7cab200b963935429c63c2e7c49c9fe78badce0233eb1c50aa76b92f313b1d2d
6
+ metadata.gz: '09dbb3f20dcb25d5f1abab3d5a009686f415799b43575e31738695809a882e3a26e8aa5cdb29951b882c66bd75af3f26abddf8006b053404eb8fafe3038ff5db'
7
+ data.tar.gz: f3b55698e2feb4425bf56d855b82570ec59c7ce51a867b7c447e7386a4c88245534bb54513f638b5b3fd60e2a390d374fd53c6199d0bf761ce5c91ff6186e600
@@ -1,5 +1,5 @@
1
1
  module BulletTrain
2
2
  module SuperScaffolding
3
- VERSION = "1.0.28"
3
+ VERSION = "1.0.29"
4
4
  end
5
5
  end
@@ -137,4 +137,8 @@ class Scaffolding::BlockManipulator
137
137
  end
138
138
  current_line
139
139
  end
140
+
141
+ def block_indentation_size(line_number)
142
+ lines[line_number].scan(/^\s+/).first.size
143
+ end
140
144
  end
@@ -1,5 +1,5 @@
1
1
  class Scaffolding::RoutesFileManipulator
2
- attr_accessor :child, :parent, :lines, :transformer_options
2
+ attr_accessor :child, :parent, :lines, :transformer_options, :block_manipulator
3
3
 
4
4
  def initialize(filename, child, parent, transformer_options = {})
5
5
  self.child = child
@@ -7,6 +7,7 @@ class Scaffolding::RoutesFileManipulator
7
7
  @filename = filename
8
8
  self.lines = File.readlines(@filename)
9
9
  self.transformer_options = transformer_options
10
+ self.block_manipulator = Scaffolding::BlockManipulator.new(@filename)
10
11
  end
11
12
 
12
13
  def child_parts
@@ -141,7 +142,12 @@ class Scaffolding::RoutesFileManipulator
141
142
  current_namespace = nil
142
143
  while namespaces.any?
143
144
  current_namespace = namespaces.shift
144
- namespace_lines = find_namespaces(created_namespaces + [current_namespace], within)
145
+ namespace_lines = if within.nil?
146
+ find_namespaces(created_namespaces + [current_namespace], within)
147
+ else
148
+ scope_namespace_to_parent(current_namespace, within)
149
+ end
150
+
145
151
  unless namespace_lines[current_namespace]
146
152
  lines_to_add = ["namespace :#{current_namespace} do", "end"]
147
153
  if created_namespaces.any?
@@ -156,6 +162,35 @@ class Scaffolding::RoutesFileManipulator
156
162
  namespace_lines ? namespace_lines[current_namespace] : nil
157
163
  end
158
164
 
165
+ # Since it's possible for multiple namespaces to exist on different levels,
166
+ # We scope the namespace we're trying to scaffold to its proper parent before processing it.
167
+ #
168
+ # i.e:
169
+ # Parent: Insight => Child: Personality::CharacterTrait
170
+ # Parent: Team => Child: Personality::Disposition
171
+ # In this case, the :personality namespace under :insights should be
172
+ # ignored when Super Scaffolding Personality::Dispositon.
173
+ #
174
+ # resources do :insights do
175
+ # namespace :personality do
176
+ # resources :character_traits
177
+ # end
178
+ # end
179
+ #
180
+ # namespace :personality do
181
+ # resources :dispositions
182
+ # end
183
+ #
184
+ # In this case, Personality::CharacterTrait is under Team just like Personality::Disposition,
185
+ # but Personality::CharacterTrait's DIRECT parent is Insight so we shouldn't scaffold its routes there.
186
+ def scope_namespace_to_parent(namespace, within)
187
+ namespace_block_start = namespace_blocks_directly_under_parent(within).map do |namespace_block|
188
+ namespace_line_number = namespace_block.begin
189
+ namespace_line_number if lines[namespace_line_number].match?(/ +namespace :#{namespace}/)
190
+ end.compact
191
+ namespace_block_start.present? ? {namespace => namespace_block_start} : {}
192
+ end
193
+
159
194
  def find(needle, within = nil)
160
195
  lines_within(within).each_with_index do |line, line_number|
161
196
  return (within + (within ? 1 : 0) + line_number) if line.match?(needle)
@@ -220,6 +255,8 @@ class Scaffolding::RoutesFileManipulator
220
255
  result
221
256
  end
222
257
 
258
+ # Finds namespace blocks no matter how many levels deep they are nested in resource blocks, etc.
259
+ # However, will not find namespace blocks inside namespace blocks.
223
260
  def top_level_namespace_block_lines(within)
224
261
  local_namespace_blocks = []
225
262
  lines_within(within).each do |line|
@@ -253,6 +290,24 @@ class Scaffolding::RoutesFileManipulator
253
290
  local_namespace_blocks
254
291
  end
255
292
 
293
+ # Whereas top_level_namespace_block_lines grabs all namespace blocks that
294
+ # appear first no matter how many resource blocks they're nested in,
295
+ # this method grabs namespace blocks that are only indented one level deep.
296
+ def namespace_blocks_directly_under_parent(within)
297
+ blocks = []
298
+ if lines[within].match?(/do$/)
299
+ parent_indentation_size = block_manipulator.block_indentation_size(within)
300
+ within_block_end = find_block_end(within)
301
+ within.upto(within_block_end) do |line_number|
302
+ if lines[line_number].match?(/^#{" " * (parent_indentation_size + 2)}namespace/)
303
+ namespace_block_lines = line_number..find_block_end(line_number)
304
+ blocks << namespace_block_lines
305
+ end
306
+ end
307
+ end
308
+ blocks
309
+ end
310
+
256
311
  def find_or_create_resource_block(parts, options = {})
257
312
  find_or_create_resource(parts, options)
258
313
  find_or_convert_resource_block(parts.last, options)
@@ -300,7 +355,6 @@ class Scaffolding::RoutesFileManipulator
300
355
  child_namespaces, child_resource, parent_namespaces, parent_resource = divergent_parts
301
356
 
302
357
  within = find_or_create_namespaces(base_namespaces)
303
- within = find_or_create_namespaces(common_namespaces, within) if common_namespaces.any?
304
358
 
305
359
  # e.g. Project and Projects::Deliverable
306
360
  if parent_namespaces.empty? && child_namespaces.one? && parent_resource == child_namespaces.first
@@ -326,33 +380,31 @@ class Scaffolding::RoutesFileManipulator
326
380
  # resources :deliverables, except: collection_actions
327
381
  # end
328
382
 
383
+ # We want to see if there are any namespaces one level above the parent itself,
384
+ # because namespaces with the same name as the resource can exist on the same level.
385
+ parent_block_start = find_block_parent(parent_within)
386
+ namespace_line_within = find_or_create_namespaces(child_namespaces, parent_block_start)
387
+ find_or_create_resource([child_resource], options: "except: collection_actions", within: namespace_line_within)
329
388
  unless find_namespaces(child_namespaces, within)[child_namespaces.last]
330
- insert_after(["", "namespace :#{child_namespaces.last} do", "end"], find_block_end(scope_within))
331
- unless find_namespaces(child_namespaces, within)[child_namespaces.last]
332
- raise "tried to insert `namespace :#{child_namespaces.last}` but it seems we failed"
333
- end
389
+ raise "tried to insert `namespace :#{child_namespaces.last}` but it seems we failed"
334
390
  end
335
391
 
336
- find_or_create_resource(child_namespaces + [child_resource], options: "except: collection_actions", within: within)
337
-
338
392
  # e.g. Projects::Deliverable and Objective Under It, Abstract::Concept and Concrete::Thing
339
393
  elsif parent_namespaces.any?
340
394
 
341
395
  # namespace :projects do
342
396
  # resources :deliverables
343
397
  # end
344
- #
398
+ top_parent_namespace = find_namespaces(parent_namespaces, within)[parent_namespaces.first]
399
+ find_or_create_resource(child_namespaces + [child_resource], within: top_parent_namespace)
400
+
345
401
  # resources :projects_deliverables, path: 'projects/deliverables' do
346
402
  # resources :objectives
347
403
  # end
348
-
349
- find_resource(parent_namespaces + [parent_resource], within: within)
350
- top_parent_namespace = find_namespaces(parent_namespaces, within)[parent_namespaces.first]
351
404
  block_parent_within = find_block_parent(top_parent_namespace)
352
405
  parent_namespaces_and_resource = (parent_namespaces + [parent_resource]).join("_")
353
406
  parent_within = find_or_create_resource_block([parent_namespaces_and_resource], options: "path: '#{parent_namespaces_and_resource.tr("_", "/")}'", within: block_parent_within)
354
407
  find_or_create_resource(child_namespaces + [child_resource], within: parent_within)
355
-
356
408
  else
357
409
 
358
410
  begin
@@ -37,6 +37,12 @@ def check_required_options_for_attributes(scaffolding_type, attributes, child, p
37
37
  name = parts.shift
38
38
  type = parts.join(":")
39
39
 
40
+ unless Scaffolding.valid_attribute_type?(type)
41
+ raise "You have entered an invalid attribute type: #{type}. General data types are used when creating new models, but Bullet Train " +
42
+ "uses field partials when Super Scaffolding, i.e. - `name:text_field` as opposed to `name:string`. " +
43
+ "Please refer to the Field Partial documentation to view which attribute types are available."
44
+ end
45
+
40
46
  # extract any options they passed in with the field.
41
47
  type, attribute_options = type.scan(/^(.*){(.*)}/).first || type
42
48
 
@@ -655,8 +655,14 @@ class Scaffolding::Transformer
655
655
  "email"
656
656
  when "color_picker"
657
657
  "code"
658
- else
658
+ when "text_field"
659
+ "text"
660
+ when "text_area"
661
+ "text"
662
+ when "file_field"
659
663
  "text"
664
+ else
665
+ raise "Invalid attribute type: #{type}."
660
666
  end
661
667
 
662
668
  cell_attributes = if boolean_buttons
@@ -1030,10 +1036,14 @@ class Scaffolding::Transformer
1030
1036
  scaffold_add_line_to_file("./app/views/account/scaffolding/completely_concrete/tangible_things/_tangible_thing.json.jbuilder", ":#{name},", RUBY_NEW_FIELDS_HOOK, prepend: true, suppress_could_not_find: true)
1031
1037
  scaffold_add_line_to_file("./app/serializers/api/v1/scaffolding/completely_concrete/tangible_thing_serializer.rb", ":#{name},", RUBY_NEW_FIELDS_HOOK, prepend: true)
1032
1038
 
1033
- assertion = if type == "date_field"
1039
+ assertion = case type
1040
+ when "date_field"
1034
1041
  "assert_equal Date.parse(tangible_thing_data['#{name}']), tangible_thing.#{name}"
1035
- elsif type == "date_and_time_field"
1042
+ when "date_and_time_field"
1036
1043
  "assert_equal DateTime.parse(tangible_thing_data['#{name}']), tangible_thing.#{name}"
1044
+ when "file_field"
1045
+ # TODO: If we want to use Cloudinary to handle our files, we should make sure we're getting a URL.
1046
+ "assert_equal tangible_thing_data['#{name}']['record']['id'], tangible_thing.#{name}.record.id"
1037
1047
  else
1038
1048
  "assert_equal tangible_thing_data['#{name}'], tangible_thing.#{name}"
1039
1049
  end
@@ -1276,10 +1286,20 @@ class Scaffolding::Transformer
1276
1286
  else
1277
1287
  transform_string("association :absolutely_abstract_creative_concept, factory: :scaffolding_absolutely_abstract_creative_concept")
1278
1288
  end
1289
+
1279
1290
  scaffold_replace_line_in_file("./test/factories/scaffolding/completely_concrete/tangible_things.rb", content, "absolutely_abstract_creative_concept { nil }")
1280
1291
 
1281
1292
  add_has_many_association
1282
1293
 
1294
+ # Adds file attachment to factory
1295
+ attributes.each do |attribute|
1296
+ attribute_name, partial_type = attribute.split(":")
1297
+ if partial_type == "file_field"
1298
+ content = "#{attribute_name} { Rack::Test::UploadedFile.new(\"test/support/foo.txt\") }"
1299
+ scaffold_replace_line_in_file("./test/factories/scaffolding/completely_concrete/tangible_things.rb", content, "#{attribute_name} { nil }")
1300
+ end
1301
+ end
1302
+
1283
1303
  if class_names_transformer.belongs_to_needs_class_definition?
1284
1304
  scaffold_replace_line_in_file("./app/models/scaffolding/completely_concrete/tangible_thing.rb", transform_string("belongs_to :absolutely_abstract_creative_concept, class_name: \"Scaffolding::AbsolutelyAbstract::CreativeConcept\"\n"), transform_string("belongs_to :absolutely_abstract_creative_concept\n"))
1285
1305
  end
data/lib/scaffolding.rb CHANGED
@@ -1,2 +1,21 @@
1
1
  module Scaffolding
2
+ def self.valid_attribute_type?(type)
3
+ [
4
+ "boolean",
5
+ "button",
6
+ "cloudinary_image",
7
+ "color_picker",
8
+ "date_and_time_field",
9
+ "date_field",
10
+ "email_field",
11
+ "file_field",
12
+ "options",
13
+ "password_field",
14
+ "phone_field",
15
+ "super_select",
16
+ "text_area",
17
+ "text_field",
18
+ "trix_editor"
19
+ ].include?(type.gsub(/{.*}/, "")) # Pop off curly brackets such as `super_select{class_name=Membership}`
20
+ end
2
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet_train-super_scaffolding
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.28
4
+ version: 1.0.29
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-22 00:00:00.000000000 Z
11
+ date: 2022-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: standard
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: spring
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: indefinite_article
57
71
  requirement: !ruby/object:Gem::Requirement