class_from_son 0.1.8 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64442ffab338e5be82ed2a8dd9da60904777f17c6aa397a1c41f3a03617823cb
4
- data.tar.gz: 9f6145f03094e312ed5efd05c23cd93e67a5112ddd920b177a4dd91383e2ba6f
3
+ metadata.gz: 7fe5463050c5bf5076026c3035dd5bf5e470659327ea19f6d8306042d96660bf
4
+ data.tar.gz: ea0270609324bd424d40ab09fa3b4da93d02689356e89d80b43c5a67cf5c6200
5
5
  SHA512:
6
- metadata.gz: a8e7f6a45207f44a91043bda76f45c367d116c8498466d51e6946b14057de66e39ced63717304abcb0bf86623d19510a4b32023e5f3822c950ff419e4b0c97a4
7
- data.tar.gz: 49894af656eb32ac4ce2d68637bc4998d737a3b2d7d2ab2f2afaf335dfa1153c09b1e62d136bf43318da898a330f34be30a28b9b195d3deb61183034a4b72b62
6
+ metadata.gz: 43cdeb8b35bd888eb0a21516e815e961d84d6714a522f49e16c628752954e67e4159afcd8552ba0741d204d26d824fd4b1b38b68dab8329ecf6ebdf34a1c642f
7
+ data.tar.gz: 549407b5e6149da0da5a826658591fdb76cc672b01bb157f81189fe66fe9fb37ab8de1424b80834f0758997045307133e44dbe2dfef3525b3a000574e18d411a
data/README.md CHANGED
@@ -31,6 +31,12 @@ or
31
31
  ruby -e "require 'class_from_son'; ClassFromSON.generate :ruby, my_json_string, :json"
32
32
  ```
33
33
 
34
+ Advanced use :
35
+
36
+ ```
37
+ ruby -e "require 'class_from_son'; ClassFromSON.generate :ruby, my_json_string, :json, true, false, true, '../write/files/somewhere/else'"
38
+ ```
39
+
34
40
  Method parameter explanations :
35
41
 
36
42
  ```
@@ -42,7 +48,10 @@ Method parameter explanations :
42
48
  # source_lang is symbol or nil (if nil, source language will be determined from the file extension)
43
49
  # make_file flag defaults to true; set to false if you do not want files to be created by this method
44
50
  # force_file flag is false; set to true if you wish to overwrite matching destination files (use with caution!)
45
- def ClassFromSON.generate_from_file(dest_lang, file, source_lang, make_file = true, force_file = false)
51
+ # lenient_mode flag is true; if the SON contains different objects with the same name (e.g. "data") then these will be treated
52
+ # as different objects with a _1, _2, etc. suffix. If this flag is false and these different objects are present, then errors will occur
53
+ # custom_file_path is nil; set to an absoulte or relative path to have the new files be written to that location
54
+ def ClassFromSON.generate_from_file(dest_lang, file, source_lang = nil, make_file = true, force_file = false, lenient_mode = true, custom_file_path = nil)
46
55
  ```
47
56
 
48
57
  ```
@@ -54,5 +63,8 @@ def ClassFromSON.generate_from_file(dest_lang, file, source_lang, make_file = tr
54
63
  # source_lang is symbol
55
64
  # make_file flag defaults to true; set to false if you do not want files to be created by this method
56
65
  # force_file flag is false; set to true if you wish to overwrite matching destination files (use with caution!)
57
- def ClassFromSON.generate(dest_lang, source, source_lang, make_file = true, force_file = false)
66
+ # lenient_mode flag is true; if the SON contains different objects with the same name (e.g. "data") then these will be treated
67
+ # as different objects with a _1, _2, etc. suffix. If this flag is false and these different objects are present, then errors will occur
68
+ # custom_file_path is nil; set to an absoulte or relative path to have the new files be written to that location
69
+ def ClassFromSON.generate(dest_lang, source, source_lang, make_file = true, force_file = false, lenient_mode = true, custom_file_path = nil)
58
70
  ```
@@ -172,6 +172,7 @@ class ClassFromSON
172
172
 
173
173
  # Returns code representing the start of the class
174
174
  def generate_class_start(name)
175
+ # TODO make this more readable
175
176
  case @language
176
177
  when :java
177
178
  start = <<-START
@@ -199,7 +200,16 @@ import lombok.Setter;
199
200
  public class #{convert_custom_class_type(name)} {
200
201
  START
201
202
  when :ruby
202
- start = "class #{convert_custom_class_type(name)}"
203
+ case @mode
204
+ when :json
205
+ start = <<-START
206
+ require 'json'
207
+
208
+ class #{convert_custom_class_type(name)}
209
+ START
210
+ else
211
+ error_and_exit "Cannot parse mode #{@mode}"
212
+ end
203
213
  else
204
214
  error_and_exit "Could not convert to output language #{@language}"
205
215
  end
@@ -285,7 +295,7 @@ START
285
295
  def generate_ruby_code_from_attributes(attributes)
286
296
  code = []
287
297
  names = []
288
- attributes.each {|att| names << att[:name]}
298
+ attributes.each {|att| names << att[:name].snakecase}
289
299
 
290
300
  # Instance variables
291
301
  names.each do |name|
@@ -294,12 +304,74 @@ START
294
304
  code << "" # An empty string is enough to trigger a newline
295
305
 
296
306
  # Constructor
297
- code << "\tdef initialize(#{names.join(", ")})"
307
+ # This is deliberately commented out, in favour of self.from_hash
308
+ code << "\t# Using self.from_hash(hash) is usually better, but this code is here in case you prefer this style of constructor"
309
+ code << "\t# def initialize(#{names.join(", ")})"
298
310
  names.each do |name|
299
- code << "\t\t@#{name} = #{name}"
311
+ code << "\t\t# @#{name} = #{name}"
300
312
  end
313
+ code << "\t# end"
314
+ code
315
+ end
316
+
317
+ # Returns code for a from_SON and to_SON method
318
+ def generate_from_and_to_methods(classname, attributes)
319
+ case @language
320
+ when :java, :java_lombok
321
+ return generate_java_from_and_to_methods(classname, attributes)
322
+ when :ruby
323
+ return generate_ruby_from_and_to_methods(classname, attributes)
324
+ else
325
+ error_and_exit "Could not convert to output language #{@language}"
326
+ end
327
+ end
328
+
329
+ # Returns Java code for a from_SON and to_SON method
330
+ def generate_java_from_and_to_methods(classname, attributes)
331
+ code = []
332
+ # TODO
333
+ code
334
+ end
335
+
336
+ # Returns Ruby code for a from_SON and to_SON method
337
+ def generate_ruby_from_and_to_methods(classname, attributes)
338
+ code = []
339
+ names = []
340
+ attributes.each {|att| names << att[:name].snakecase}
341
+
342
+ # from_hash method
343
+ code << ""
344
+ code << "\tdef self.from_hash(h)"
345
+ code << "\t\to = self.new"
346
+ names.each do |name|
347
+ code << "\t\to.#{name} = h[:#{name}]"
348
+ end
349
+ code << "\t\to"
301
350
  code << "\tend"
302
351
 
352
+ # from_SON method
353
+ code << ""
354
+ code << "\tdef self.from_#{@mode}(#{@mode})"
355
+ case @mode
356
+ when :json
357
+ code << "\t\tself.from_hash(JSON.parse(#{@mode}))"
358
+ # TODO other input languages, e.g. XML, YAML
359
+ end
360
+ code << "\tend"
361
+
362
+ # to_SON method
363
+ code << ""
364
+ code << "\tdef to_#{@mode}"
365
+ code << "\t\th = {}"
366
+ names.each do |name|
367
+ code << "\t\th[:#{name}] = @#{name}"
368
+ end
369
+ case @mode
370
+ when :json
371
+ code << "\t\tJSON.generate(h)"
372
+ # TODO other input languages, e.g. XML, YAML
373
+ end
374
+ code << "\tend"
303
375
  code
304
376
  end
305
377
 
@@ -337,6 +409,7 @@ START
337
409
  end
338
410
 
339
411
  lines << generate_code_from_attributes(attributes)
412
+ lines << generate_from_and_to_methods(classname, attributes)
340
413
  lines << generate_class_end
341
414
  lines.flatten!
342
415
  this_file[:contents] = lines.join("\n")
@@ -356,13 +429,16 @@ START
356
429
  # source_lang is symbol or nil (if nil, source language will be determined from the file extension)
357
430
  # make_file flag defaults to true; set to false if you do not want files to be created by this method
358
431
  # force_file flag is false; set to true if you wish to overwrite matching destination files (use with caution!)
359
- def ClassFromSON.generate_from_file(dest_lang, file, source_lang = nil, make_file = true, force_file = false)
432
+ # lenient_mode flag is true; if the SON contains different objects with the same name (e.g. "data") then these will be treated
433
+ # as different objects with a _1, _2, etc. suffix. If this flag is false and these different objects are present, then errors will occur
434
+ # custom_file_path is nil; set to an absoulte or relative path to have the new files be written to that location
435
+ def ClassFromSON.generate_from_file(dest_lang, file, source_lang = nil, make_file = true, force_file = false, lenient_mode = true, custom_file_path = nil)
360
436
 
361
437
  error_and_exit "Could not locate file #{file}" unless File.exists?(file)
362
438
 
363
439
  source_lang ||= File.extname(file).gsub(".", "")
364
440
  source = File.readlines(file).join
365
- ClassFromSON.generate(dest_lang, source, source_lang, make_file, force_file)
441
+ ClassFromSON.generate(dest_lang, source, source_lang, make_file, force_file, lenient_mode, custom_file_path)
366
442
 
367
443
  # o = ClassFromSON.new
368
444
  # o.generate(dest_lang, source, source_lang, make_file)
@@ -376,9 +452,12 @@ START
376
452
  # source_lang is symbol
377
453
  # make_file flag defaults to true; set to false if you do not want files to be created by this method
378
454
  # force_file flag is false; set to true if you wish to overwrite matching destination files (use with caution!)
379
- def ClassFromSON.generate(dest_lang, source, source_lang, make_file = true, force_file = false)
455
+ # lenient_mode flag is true; if the SON contains different objects with the same name (e.g. "data") then these will be treated
456
+ # as different objects with a _1, _2, etc. suffix. If this flag is false and these different objects are present, then errors will occur
457
+ # custom_file_path is nil; set to an absoulte or relative path to have the new files be written to that location
458
+ def ClassFromSON.generate(dest_lang, source, source_lang, make_file = true, force_file = false, lenient_mode = true, custom_file_path = nil)
380
459
  o = ClassFromSON.new
381
- o.generate(dest_lang, source, source_lang, make_file, force_file)
460
+ o.generate(dest_lang, source, source_lang, make_file, force_file, lenient_mode, custom_file_path)
382
461
  end
383
462
 
384
463
  # Will generate classes from a SON string.
@@ -389,7 +468,10 @@ START
389
468
  # source_lang is symbol
390
469
  # make_file flag defaults to true; set to false if you do not want files to be created by this method
391
470
  # force_file flag is false; set to true if you wish to overwrite matching destination files (use with caution!)
392
- def generate(dest_lang, source, source_lang, make_file = true, force_file = false)
471
+ # lenient_mode flag is true; if the SON contains different objects with the same name (e.g. "data") then these will be treated
472
+ # as different objects with a _1, _2, etc. suffix. If this flag is false and these different objects are present, then errors will occur
473
+ # custom_file_path is nil; set to an absoulte or relative path to have the new files be written to that location
474
+ def generate(dest_lang, source, source_lang, make_file = true, force_file = false, lenient_mode = true, custom_file_path = nil)
393
475
 
394
476
  error_and_exit "Please supply first argument as a Symbol" unless dest_lang.class == Symbol
395
477
 
@@ -434,16 +516,46 @@ START
434
516
  top_level_classname = generate_top_level_name
435
517
  output_classes = generate_output_classes(hash, top_level_classname).flatten # returns an array
436
518
 
519
+ # Set the directory that the files will be written into
520
+ if custom_file_path
521
+ # This caters for both absolute & relative file paths
522
+ file_path = File.absolute_path(custom_file_path)
523
+ else
524
+ file_path = Dir.getwd
525
+ end
526
+
527
+ # Track the names of the classes/files we have written so far
528
+ written_file_names = []
529
+
437
530
  if make_file
438
531
  output_classes.each do |out|
439
532
  name = out[:name_with_ext]
533
+ # Check the name against the files we have already written
534
+ if written_file_names.include?(name)
535
+ if lenient_mode
536
+ # Let us increment the name, e.g. "data.rb" -> "data_1.rb", "data_2.rb", etc.
537
+ increment = 1
538
+ new_name = name.gsub(@extension, "_#{increment}#{@extension}")
539
+ while written_file_names.include?(new_name)
540
+ increment += 1
541
+ new_name = name.gsub(@extension, "_#{increment}#{@extension}")
542
+ end
543
+ name = new_name
544
+ else
545
+ message = "Want to generate output file #{name}, but a file with that name has already been written by this process. Your SON structure contains 2+ different classes with the same name"
546
+ error_and_exit(message)
547
+ end
548
+ end
549
+
550
+ filename = file_path + File::SEPARATOR + name
440
551
  contents = out[:contents]
441
552
  unless force_file
442
553
  error_and_exit "Want to generate output file #{name}, but that file already exists" if File.exists?(name)
443
554
  end
444
- File.open(name, "w+") do |f|
555
+ File.open(filename, "w+") do |f|
445
556
  f.puts contents
446
557
  end
558
+ written_file_names << name
447
559
  puts "Wrote out file #{name}"
448
560
  end
449
561
 
@@ -19,7 +19,7 @@ class TestEx < Test::Unit::TestCase
19
19
 
20
20
  address_filename = "address.rb"
21
21
  top_level_filename = "generated_from_json.rb"
22
- phonenumbers_filename = "phonenumbers.rb"
22
+ phonenumbers_filename = "phone_numbers.rb"
23
23
 
24
24
  expected_address = File.readlines(address_filename).join.chomp # trim off any trailing whitespace (irrelevent for this test)
25
25
  expected_example = File.readlines(top_level_filename).join.chomp # trim off any trailing whitespace (irrelevent for this test)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: class_from_son
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Morrisby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-03 00:00:00.000000000 Z
11
+ date: 2021-07-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: This gem will attempt to generate code of a class of an object representing
14
14
  the contents of a Serialised-Object-Notation (SON) string (or file). E.g. it will