ead 0.1.0 → 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: d6e07db51d8953566d048da05fc0fd512a411027c4294b1bb344342e7a24b5a3
4
- data.tar.gz: 10db1021f0792bb270ac5c27f258a47b9e2124e5b41d95acb24a574bbb2f0c68
3
+ metadata.gz: d3b8b4dac74bd298fe1030da9c00bd04c1badb639de8ae1777f2ca8b98895381
4
+ data.tar.gz: bad574c55817b25d32b11307a7d867e3c503a7b768bf02e8f75ec5d4ec2a15b7
5
5
  SHA512:
6
- metadata.gz: e984c6bebd41d5833ce30b06c89e24168f4d519ef48d5b92bd257b0a6617a377a723c2f8f8be9fa4cfaf614b7bdfd1d46a18ac5b5baac99cec939fe2a69f67da
7
- data.tar.gz: f37f5d29d7007ee72c80fef287bc5d2a144d9a73179d925d6cf1a7011a97fe5f003e5258464387726b394cf41680cbd0ee034c2754453997000aad2d09c8c771
6
+ metadata.gz: a9cbd8d53a5fef880146af795e76efae5505b26649d7138cd846f169f6f4cdfbac6542f053335f87cbeb5bc67e443b859b783f4b7accf9f2d876b7267955bd07
7
+ data.tar.gz: 3156c9c4990b013217e9d365d8f65bc80c6da3923bbab06c345bebcbd6dde5f2afd2841e050be3d6f82caa996ff002aec425e7f3670101a69ba24e6f8787770b
data/bin/ead CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'ead'
3
3
 
4
- EAD.new.start(ARGV)
4
+ EAD.new.start(ARGV)
data/lib/association.rb CHANGED
@@ -5,13 +5,20 @@ class Association
5
5
 
6
6
  def initialize(first_item, association_block)
7
7
  @first_item = first_item
8
- @second_items = add_second_items(association_block)
8
+ @second_items = []
9
+ add_second_items(association_block)
9
10
  @name = association_block.content
10
11
  end
11
12
 
12
13
  def add_second_items(block)
13
- block.sub_blocks.map do |sub_block|
14
- Item.new(sub_block, first_item, self)
14
+ block.sub_blocks.each do |sub_block|
15
+ if sub_block.entity
16
+ second_items << Item.new(sub_block, first_item, self)
17
+ elsif sub_block.entity_clone
18
+ second_items << ItemClone.new(sub_block, first_item, self)
19
+ elsif sub_block.entity_container
20
+ add_second_items(sub_block)
21
+ end
15
22
  end
16
23
  end
17
24
 
@@ -23,6 +30,10 @@ class Association
23
30
  name == 'has_one'
24
31
  end
25
32
 
33
+ def has_any?
34
+ has_one? || has_many?
35
+ end
36
+
26
37
  def through?
27
38
  name == ':through'
28
39
  end
data/lib/block.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  class Block
2
- attr_accessor :id, :content, :category, :attribute_container, :attribute, :type, :association, :sub_blocks
2
+ attr_accessor :id, :content, :category, :attribute_container, :attribute, :type, :association, :sub_blocks,
3
+ :clone_blocks, :cloneable, :entity, :entity_clone, :clone_parent, :entity_container
3
4
 
4
5
  def initialize(id, items)
5
6
  item = items[id]
@@ -7,9 +8,15 @@ class Block
7
8
  @content = item['content']
8
9
  @category = item['category']
9
10
  @attribute_container = item['attributeContainer']
11
+ @entity = item['entity']
12
+ @entity_container = item['entityContainer']
10
13
  @attribute = item['attribute']
11
14
  @type = item['type']
12
15
  @association = item['association']
16
+ @entity_clone = item['entityClone']
17
+ @cloneable = item['cloneable']
18
+ @clone_blocks = item['cloneChildren']
19
+ @clone_parent = item['cloneParent'].to_s
13
20
  @sub_blocks = []
14
21
  item['subItemIds'].each do |sub_item_id|
15
22
  sub_item_id = sub_item_id.to_s
@@ -22,6 +29,6 @@ class Block
22
29
  end
23
30
 
24
31
  def self.find(id)
25
- all.each { |block| return block if block.id == id }
32
+ all.find { |block| block.id == id }
26
33
  end
27
34
  end
data/lib/ead.rb CHANGED
@@ -1,27 +1,56 @@
1
1
  require 'json'
2
- require 'fileutils'
3
2
  require 'item'
3
+ require 'item_clone'
4
4
  require 'block'
5
- require 'byebug'
6
5
 
7
6
  class EAD
8
7
  def import_JSON(user_arguments)
9
8
  file = File.read(user_arguments[0] || './EAD.json')
10
9
  items = JSON.parse(file)
11
- ead_id = '8'
10
+ ead_id = '9'
12
11
  Block.new(ead_id, items)
12
+ Block.all.each do |block|
13
+ next unless block.cloneable
14
+
15
+ block.clone_blocks.map! do |id|
16
+ Block.find(id.to_s)
17
+ end
18
+ end
19
+ end
20
+
21
+ def create_items(block)
22
+ block.sub_blocks.each do |sub_block|
23
+ if sub_block.entity
24
+ Item.new(sub_block)
25
+ elsif sub_block.entity_clone
26
+ ItemClone.new(sub_block)
27
+ elsif sub_block.entity_container
28
+ create_items(sub_block)
29
+ end
30
+ end
13
31
  end
14
32
 
15
33
  def check_implement_items
16
- ead_id = '8'
34
+ ead_id = '9'
17
35
  block = Block.find(ead_id)
18
- block.sub_blocks.each do |sub_block|
19
- Item.new(sub_block)
36
+ create_items(block)
37
+
38
+ ItemClone.all.each do |item_clone|
39
+ parent = Item.find(item_clone.clone_parent)
40
+ item_clone.clone_parent = Item.find(item_clone.clone_parent)
41
+ parent.clones << item_clone
20
42
  end
21
43
 
22
44
  Item.all.reverse.each do |item|
23
45
  item.create_migration
24
- item.add_associations_to_model
46
+ end
47
+
48
+ Item.all.reverse.each do |item|
49
+ item.add_associations
50
+ end
51
+
52
+ ItemClone.all.reverse.each do |item_clone|
53
+ item_clone.add_associations
25
54
  end
26
55
  end
27
56
 
data/lib/item.rb CHANGED
@@ -1,166 +1,70 @@
1
+ require 'item_base'
1
2
  require 'attribute'
2
3
  require 'association'
3
- require 'fileutils'
4
4
  require 'active_support/core_ext/string'
5
5
 
6
- class Item
7
- attr_accessor :name, :parent, :parent_association, :associations, :attributes
6
+ class Item < ItemBase
7
+ attr_accessor :clones, :polymorphic, :polymorphic_names
8
8
 
9
9
  def initialize(block, parent = nil, parent_association = nil)
10
- @name = block.content.downcase.singularize
11
- @parent = parent
12
- @parent_association = parent_association
13
- @attributes = []
14
- @associations = []
15
-
16
- block.sub_blocks.each do |sub_block|
17
- if sub_block.attribute
18
- add_to_attributes(sub_block)
19
- elsif sub_block.attribute_container
20
- add_attribute_container(sub_block)
21
- elsif sub_block.association
22
- add_to_associations(sub_block)
23
- end
24
- end
25
- end
26
-
27
- def grand_parent
28
- parent.parent
29
- end
30
-
31
- def add_attribute_container(block)
32
- block.sub_blocks.each do |attribute|
33
- add_to_attributes(attribute)
34
- end
35
- end
36
-
37
- def add_to_attributes(block)
38
- @attributes << Attribute.new(block.content, block.type)
39
- end
40
-
41
- def add_to_associations(block)
42
- @associations << Association.new(self, block)
10
+ super(block, parent, parent_association)
11
+ @clones = []
12
+ @polymorphic = false
13
+ @polymorphic_names = []
43
14
  end
44
15
 
45
- def grand_parent_association
46
- parent.parent_association
47
- end
48
-
49
- def grand_parent_has_many?
50
- grand_parent_association&.has_many?
51
- end
52
-
53
- def grand_parent_has_one?
54
- grand_parent_association&.has_one?
16
+ def model_name
17
+ name.camelize
55
18
  end
56
19
 
57
- def parent_through?
58
- parent_association&.through?
59
- end
20
+ def add_references(command, item)
21
+ return if command.include? " #{item.name}:references"
60
22
 
61
- def parent_has_many?
62
- parent_association&.has_many?
23
+ command << " #{item.name}:references"
63
24
  end
64
25
 
65
- def parent_has_one?
66
- parent_association&.has_one?
26
+ def add_polymorphic(command, poly_name)
27
+ command << " #{poly_name}:references{polymorphic}"
67
28
  end
68
29
 
69
- def self.all
70
- ObjectSpace.each_object(self).to_a
30
+ def update_polymorphic_names
31
+ all_parents_name = [self, *clones].map do |item|
32
+ [item.parent&.name, item.through_association && item.through_child.name]
33
+ end
34
+ all_parents_name.flatten!.compact!
35
+ @polymorphic_names = all_parents_name.find_all { |name| all_parents_name.count(name) > 1 }.uniq
71
36
  end
72
37
 
73
- def through_association
74
- associations.find { |association| association.through? }
75
- end
38
+ def check_polymorphic(command)
39
+ update_polymorphic_names
40
+ @polymorphic_names.each do |poly_name|
41
+ add_polymorphic(command, poly_name)
42
+ end
76
43
 
77
- def through_child
78
- through_association.second_items.first
79
- end
80
-
81
- def model_name
82
- name.capitalize
44
+ @polymorphic = true if @polymorphic_names.size.positive?
83
45
  end
84
46
 
85
47
  def create_migration
86
- def add_references(command, item)
87
- command << " #{item.name}:references"
88
- end
89
-
90
48
  return if File.exist?("./app/models/#{name}.rb")
91
49
 
92
50
  command = 'bundle exec rails generate model '
93
51
  command << model_name
94
52
  attributes.each { |attribute| attribute.add_to(command) }
95
53
 
96
- if parent_has_many? || parent_has_one?
97
- add_references(command, parent)
98
- elsif parent_through? && grand_parent_has_one?
99
- add_references(command, parent)
100
- end
101
-
102
- if parent_has_many? && through_association
103
- through_child.create_migration
104
- add_references(command, through_child)
105
- end
106
-
107
- system(command)
108
- end
109
-
110
- def add_associations_to_model
111
- def through?(item)
112
- item.present?
113
- end
114
-
115
- def update_model(start_item, end_item, association, intermediate_item = nil)
116
- return unless association.has_one? || association.has_many?
117
-
118
- start_model = start_item.name
119
- end_model = end_item.name
120
- intermediate_model = intermediate_item.name if intermediate_item
121
-
122
- if association.has_many?
123
- end_model = end_model.pluralize
124
- intermediate_model = intermediate_model.pluralize if intermediate_model
125
- end
54
+ check_polymorphic(command)
126
55
 
127
- tempfile = File.open('./app/models/model_update.rb', 'w')
128
- f = File.new("./app/models/#{start_model}.rb")
129
- f.each do |line|
130
- if line.include? 'end'
131
- line_association = " #{association.name} :#{end_model}"
132
- line_association << ", through: :#{intermediate_model}" if through?(intermediate_item)
133
- line_association << "\n"
134
- tempfile << line_association
135
- end
136
- tempfile << line
56
+ [self, *clones].each do |item|
57
+ if item.parent_has_many? && item.through_association
58
+ item.through_child.create_migration if item.through_child.not_clone?
59
+ add_references(command, item.through_child)
137
60
  end
138
- f.close
139
- tempfile.close
140
61
 
141
- FileUtils.mv(
142
- './app/models/model_update.rb',
143
- "./app/models/#{start_model}.rb"
62
+ next unless item.parent && !item.one_polymorphic_names?(item.parent) && (
63
+ item.parent_has_any? || item.parent_through_has_one?
144
64
  )
145
- end
146
-
147
- if parent_through?
148
- if grand_parent_has_many?
149
- update_model(self, parent, grand_parent_association)
150
- update_model(grand_parent, self, grand_parent_association, parent)
151
- update_model(self, grand_parent, grand_parent_association, parent)
152
65
 
153
- elsif grand_parent_has_one?
154
- update_model(parent, self, grand_parent_association)
155
- update_model(grand_parent, self, grand_parent_association, parent)
156
- end
157
- end
158
- associations.each do |association|
159
- next unless association.has_many? || association.has_one?
160
-
161
- association.second_items.each do |second_item|
162
- update_model(self, second_item, association)
163
- end
66
+ add_references(command, item.parent)
164
67
  end
68
+ system(command)
165
69
  end
166
70
  end
data/lib/item_base.rb ADDED
@@ -0,0 +1,239 @@
1
+ require 'project_file'
2
+
3
+ class ItemBase
4
+ attr_accessor :name, :parent, :parent_association, :associations, :attributes, :id, :twin_name
5
+
6
+ def initialize(block, parent = nil, parent_association = nil)
7
+ @id = block.id
8
+ @name = block.content.split(' || ')[0].underscore.singularize
9
+ @twin_name = block.content.split(' || ')[1]&.underscore&.singularize
10
+ @parent = parent
11
+ @parent_association = parent_association
12
+ @attributes = []
13
+ @associations = []
14
+ block.sub_blocks.each do |sub_block|
15
+ if sub_block.attribute
16
+ add_to_attributes(sub_block)
17
+ elsif sub_block.attribute_container
18
+ add_attribute_container(sub_block)
19
+ elsif sub_block.association
20
+ add_to_associations(sub_block)
21
+ end
22
+ end
23
+ end
24
+
25
+ def add_attribute_container(block)
26
+ block.sub_blocks.each do |attribute|
27
+ add_to_attributes(attribute)
28
+ end
29
+ end
30
+
31
+ def add_to_attributes(block)
32
+ @attributes << Attribute.new(block.content, block.type)
33
+ end
34
+
35
+ def add_to_associations(block)
36
+ @associations << Association.new(self, block)
37
+ end
38
+
39
+ def grand
40
+ parent.parent
41
+ end
42
+
43
+ def grand_association
44
+ parent.parent_association
45
+ end
46
+
47
+ def grand_has_many?
48
+ grand_association&.has_many?
49
+ end
50
+
51
+ def grand_has_one?
52
+ grand_association&.has_one?
53
+ end
54
+
55
+ def grand_real_self_real?
56
+ reals_same? grand
57
+ end
58
+
59
+ def reals_same?(item)
60
+ real_item == item.real_item
61
+ end
62
+
63
+ def parent_through?
64
+ parent_association&.through?
65
+ end
66
+
67
+ def parent_has_many?
68
+ parent_association&.has_many?
69
+ end
70
+
71
+ def parent_has_one?
72
+ parent_association&.has_one?
73
+ end
74
+
75
+ def parent_has_any?
76
+ parent_has_one? || parent_has_many?
77
+ end
78
+
79
+ def parent_through_has_one?
80
+ parent_through? && grand_has_one?
81
+ end
82
+
83
+ def parent_through_has_many?
84
+ parent_through? && grand_has_many?
85
+ end
86
+
87
+ def through_association
88
+ associations.find(&:through?)
89
+ end
90
+
91
+ def through_child
92
+ through_association&.second_items&.first
93
+ end
94
+
95
+ def through?(item)
96
+ item.present?
97
+ end
98
+
99
+ def clone_name_different?
100
+ clone? && (clone_parent.name != name)
101
+ end
102
+
103
+ def one_polymorphic_names?(item)
104
+ real_item.polymorphic && real_item.polymorphic_names.include?(item.name)
105
+ end
106
+
107
+ def clone?
108
+ instance_of?(ItemClone)
109
+ end
110
+
111
+ def not_clone?
112
+ !clone?
113
+ end
114
+
115
+ def real_item
116
+ clone? ? clone_parent : self
117
+ end
118
+
119
+ def grand_many_through_reals_same?(item)
120
+ parent_through_has_many? && (grand == item) && reals_same?(item)
121
+ end
122
+
123
+ def parent_has_many_reals_same_through_child?(item)
124
+ item.parent_through_has_many? && (through_child == item) && item.reals_same?(parent)
125
+ end
126
+
127
+ def update_end_model_migration_files(start_item, association)
128
+ polymorphic_end = one_polymorphic_names?(start_item)
129
+
130
+ end_model_line = {}
131
+ end_migration_line = {}
132
+ if association.has_one? && start_item.parent&.reals_same?(self)
133
+ end_model_line['optional'] = 'true'
134
+ end_migration_line['null'] = 'true'
135
+ end
136
+
137
+ if association.has_any?
138
+ if reals_same?(start_item)
139
+ end_model_line['optional'] = 'true'
140
+ end_migration_line['null'] = 'true'
141
+ end
142
+
143
+ if start_item.clone? && !polymorphic_end && start_item.clone_name_different?
144
+ end_model_line['class_name'] = "\"#{start_item.clone_parent.name.camelize}\""
145
+ end_migration_line['foreign_key'] = "{ to_table: :#{start_item.clone_parent.name.pluralize} }"
146
+ end
147
+ end
148
+
149
+ ProjectFile.update_line(real_item.name, 'model', /belongs_to :#{start_item.name}/, end_model_line)
150
+
151
+ migration_name = real_item.name
152
+ ProjectFile.update_line(migration_name, 'migration', /t.references :#{start_item.name}/, end_migration_line)
153
+ end
154
+
155
+ def update_start_model_file(end_item, association, intermediate_item = nil)
156
+ start_model = real_item.name
157
+
158
+ end_model = if end_item.parent_has_many_reals_same_through_child?(self)
159
+ end_item.twin_name
160
+ else
161
+ end_item.name
162
+ end
163
+
164
+ intermediate_model = if grand_many_through_reals_same?(end_item)
165
+ intermediate_item.twin_name
166
+ elsif intermediate_item
167
+ intermediate_item.name
168
+ end
169
+
170
+ if association.has_many?
171
+ end_model = end_model.pluralize
172
+ intermediate_model = intermediate_model.pluralize if intermediate_model
173
+ end
174
+
175
+ line_content = {}
176
+ line_content[association.name] = if intermediate_item&.one_polymorphic_names?(end_item) && association.has_many?
177
+ ":#{end_item.real_item.name.pluralize}"
178
+ else
179
+ ":#{end_model}"
180
+ end
181
+
182
+ if intermediate_item
183
+ line_content['through'] = ":#{intermediate_model}"
184
+ if intermediate_item.one_polymorphic_names?(end_item)
185
+ line_content['source'] = ":#{end_item.name}"
186
+ line_content['source_type'] = "\"#{end_item.real_item.name.camelize}\" "
187
+ end
188
+ elsif !intermediate_item
189
+ line_content['class_name'] = "\"#{end_item.real_item.name.camelize}\"" if end_item.clone_name_different?
190
+
191
+ if end_item.one_polymorphic_names?(self)
192
+ line_content['as'] = ":#{name}"
193
+ elsif clone_name_different?
194
+ line_content['foreign_key'] = "\"#{name.singularize}_id\""
195
+ end
196
+ end
197
+
198
+ ProjectFile.add_line(start_model, end_model, line_content)
199
+ end
200
+
201
+ def update_model(end_item, association, intermediate_item = nil)
202
+ return unless association.has_one? || association.has_many?
203
+
204
+ end_item.update_end_model_migration_files(self, association) unless intermediate_item
205
+ update_start_model_file(end_item, association, intermediate_item)
206
+ end
207
+
208
+ def parent_through_add_associations
209
+ if parent_through_has_many?
210
+ update_model(parent, grand_association)
211
+ update_model(grand, grand_association, parent)
212
+
213
+ elsif parent_through_has_one?
214
+ parent.update_model(self, grand_association)
215
+ end
216
+
217
+ grand.update_model(self, grand_association, parent)
218
+ end
219
+
220
+ def add_associations
221
+ parent_through_add_associations if parent_through?
222
+
223
+ associations.each do |association|
224
+ next unless association.has_any?
225
+
226
+ association.second_items.each do |second_item|
227
+ update_model(second_item, association)
228
+ end
229
+ end
230
+ end
231
+
232
+ def self.all
233
+ ObjectSpace.each_object(self).to_a
234
+ end
235
+
236
+ def self.find(id)
237
+ all.find { |item| item.id == id }
238
+ end
239
+ end
data/lib/item_clone.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'item_base'
2
+
3
+ class ItemClone < ItemBase
4
+ attr_accessor :clone_parent
5
+
6
+ def initialize(block, parent = nil, parent_association = nil)
7
+ super(block, parent, parent_association)
8
+ @clone_parent = block.clone_parent
9
+ end
10
+
11
+ def model_name
12
+ clone_parent.name.camelize
13
+ end
14
+ end
@@ -0,0 +1,68 @@
1
+ class ProjectFile
2
+ def self.open_close(name, type, &block)
3
+ case type
4
+ when 'migration'
5
+ tempfile_name = './db/migrate/migration_update.rb'
6
+ file_name = Dir.glob("./db/migrate/*_#{name.pluralize}.rb").first
7
+ when 'model'
8
+ tempfile_name = './app/models/model_update.rb'
9
+ file_name = "./app/models/#{name}.rb"
10
+ end
11
+
12
+ tempfile = File.open(tempfile_name, 'w')
13
+ file = File.new(file_name)
14
+
15
+ block.call(file, tempfile)
16
+
17
+ file.close
18
+ tempfile.close
19
+
20
+ FileUtils.mv(
21
+ tempfile_name,
22
+ file_name
23
+ )
24
+ end
25
+
26
+ def self.update_line(name, type, keywords, line_content)
27
+ open_close(name, type) do |file, tempfile|
28
+ file.each do |line|
29
+ if line.match(keywords)
30
+ line.gsub!("\n", ' ')
31
+ line_content.each do |key, value|
32
+ if line.include? key
33
+ line.gsub!(/#{key}: .*([, ])/, "#{key}: #{value}#{Regexp.last_match(1)}")
34
+ else
35
+ line << ", #{key}: #{value}"
36
+ end
37
+ end
38
+ line << "\n"
39
+
40
+ end
41
+ tempfile << line
42
+ end
43
+ end
44
+ end
45
+
46
+ def self.add_line(name, end_model, line_content)
47
+ open_close(name, 'model') do |file, tempfile|
48
+ line_found = false
49
+ file.each do |line|
50
+ if (line.include?('end') || line.include?("through: :#{end_model}")) && !line_found
51
+ line_found = true
52
+ line_association = ''
53
+ line_content.each do |key, value|
54
+ line_association << if %w[has_many has_one].include?(key)
55
+ " #{key} #{value}"
56
+ else
57
+ ", #{key}: #{value}"
58
+ end
59
+ end
60
+
61
+ line_association << "\n"
62
+ tempfile << line_association
63
+ end
64
+ tempfile << line
65
+ end
66
+ end
67
+ end
68
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ead
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hasan Ozovali
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-09 00:00:00.000000000 Z
11
+ date: 2021-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -80,6 +80,9 @@ files:
80
80
  - lib/block.rb
81
81
  - lib/ead.rb
82
82
  - lib/item.rb
83
+ - lib/item_base.rb
84
+ - lib/item_clone.rb
85
+ - lib/project_file.rb
83
86
  homepage: https://rubygems.org/gems/ead
84
87
  licenses:
85
88
  - MIT
@@ -92,7 +95,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
92
95
  requirements:
93
96
  - - ">="
94
97
  - !ruby/object:Gem::Version
95
- version: 2.5.1
98
+ version: 2.7.2
96
99
  required_rubygems_version: !ruby/object:Gem::Requirement
97
100
  requirements:
98
101
  - - ">="