ead 0.3.1 → 0.4.2
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 +4 -4
- data/lib/association.rb +103 -10
- data/lib/attribute.rb +3 -3
- data/lib/ead.rb +39 -47
- data/lib/entity.rb +145 -0
- data/lib/project_file.rb +28 -3
- data/lib/table.rb +88 -0
- data/lib/table_entity_base.rb +9 -0
- metadata +22 -8
- data/lib/block.rb +0 -34
- data/lib/item.rb +0 -92
- data/lib/item_base.rb +0 -17
- data/lib/item_clone.rb +0 -212
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7f4093a77c77ad563d127f8e091fccbb10a4c026402f6981b5019fdb6d0efff
|
4
|
+
data.tar.gz: 01f1f36ba0deb5b8a963d8d853b1a9190b8f749a8338bf363766f21961b854ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91231d696d2a26b2fcee500756374fc48ec3c403bee73f2f3a43e05b09065d7c969453b924598bef287b7ac80ed0357fe3eafd958142650663ab8e6e6c002e6f
|
7
|
+
data.tar.gz: f5b2b67f1917ada516d19cb498ab580ba55bd25698dc3c019db10fc26d4d1d92018c91295950d2f61a41ba8ec965fed96d566f7e771aee0060061eb4ec01b466
|
data/lib/association.rb
CHANGED
@@ -1,21 +1,114 @@
|
|
1
|
-
require '
|
1
|
+
require 'table'
|
2
2
|
|
3
3
|
class Association
|
4
|
-
attr_accessor :
|
4
|
+
attr_accessor :first_entity, :second_entity, :name, :middle_entities_has_one, :middle_entities_has_many,
|
5
|
+
:through_entity
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
@
|
9
|
-
|
10
|
-
@
|
7
|
+
# first_entity, association_block)
|
8
|
+
def initialize(edge)
|
9
|
+
@first_entity = Entity.find(edge['source'])
|
10
|
+
@second_entity = Entity.find(edge['target'])
|
11
|
+
@through_entity = nil
|
12
|
+
|
13
|
+
@middle_entities_has_one = []
|
14
|
+
@middle_entities_has_many = []
|
15
|
+
|
16
|
+
@first_entity.associations << self
|
17
|
+
@second_entity.parent_associations << self
|
18
|
+
|
19
|
+
@name = nil
|
20
|
+
case edge['type']
|
21
|
+
when 'hasMany'
|
22
|
+
@first_entity.children_has_many << @second_entity
|
23
|
+
@second_entity.parents_has_many << @first_entity
|
24
|
+
|
25
|
+
@name = 'has_many'
|
26
|
+
when 'hasOne'
|
27
|
+
@first_entity.children_has_one << @second_entity
|
28
|
+
@second_entity.parents_has_one << @first_entity
|
29
|
+
|
30
|
+
@name = 'has_one'
|
31
|
+
when 'through'
|
32
|
+
@first_entity.children_through << @second_entity
|
33
|
+
@second_entity.parents_through << @first_entity
|
34
|
+
|
35
|
+
@through_entity = Entity.find(edge['data']['throughNodeId'])
|
36
|
+
|
37
|
+
@name = ':through'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.check_middle_entities_include(entity)
|
42
|
+
associations = Association.all.select { |association| association.through_entity == entity }
|
43
|
+
associations.each do |association|
|
44
|
+
unless (association.middle_entities_has_many.include? entity) || (association.middle_entities_has_one.include? entity)
|
45
|
+
association.set_middle_entity
|
46
|
+
end
|
47
|
+
end
|
11
48
|
end
|
12
49
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
50
|
+
def set_middle_entity
|
51
|
+
source = first_entity
|
52
|
+
target = second_entity
|
53
|
+
|
54
|
+
if (
|
55
|
+
source.parents_has_many +
|
56
|
+
source.parents_has_many_through +
|
57
|
+
source.parents_has_one +
|
58
|
+
source.parents_has_one_through +
|
59
|
+
source.children_has_many +
|
60
|
+
source.children_has_many_through +
|
61
|
+
source.children_has_one +
|
62
|
+
source.children_has_one_through
|
63
|
+
).include?(through_entity) &&
|
64
|
+
(
|
65
|
+
(
|
66
|
+
target.parents_has_many +
|
67
|
+
target.parents_has_many_through +
|
68
|
+
target.parents_has_one +
|
69
|
+
target.parents_has_one_through +
|
70
|
+
target.children_has_many +
|
71
|
+
target.children_has_many_through +
|
72
|
+
target.children_has_one +
|
73
|
+
target.children_has_one_through
|
74
|
+
).include?(through_entity) || (
|
75
|
+
through_entity.parents_has_many.map(&:clone_parent).include?(target.clone_parent) ||
|
76
|
+
through_entity.parents_has_one.map(&:clone_parent).include?(target.clone_parent)
|
77
|
+
)
|
78
|
+
)
|
79
|
+
|
80
|
+
if (
|
81
|
+
source.children_has_many.include?(through_entity) ||
|
82
|
+
source.children_has_many_through.include?(through_entity)
|
83
|
+
) || (
|
84
|
+
target.parents_has_many.include?(through_entity) ||
|
85
|
+
target.parents_has_many_through.include?(through_entity)
|
86
|
+
)
|
87
|
+
|
88
|
+
unless middle_entities_has_many.include? through_entity
|
89
|
+
middle_entities_has_many << through_entity
|
90
|
+
source.children_has_many_through << target
|
91
|
+
target.parents_has_many_through << source
|
92
|
+
Association.check_middle_entities_include(target)
|
93
|
+
end
|
94
|
+
else
|
95
|
+
unless middle_entities_has_one.include? through_entity
|
96
|
+
middle_entities_has_one << through_entity
|
97
|
+
source.children_has_one_through << target
|
98
|
+
target.parents_has_one_through << source
|
99
|
+
Association.check_middle_entities_include(target)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
16
103
|
end
|
17
104
|
end
|
18
105
|
|
106
|
+
def self.set_middle_entities
|
107
|
+
associations = all.select(&:through?)
|
108
|
+
|
109
|
+
associations.each(&:set_middle_entity)
|
110
|
+
end
|
111
|
+
|
19
112
|
def has_many?
|
20
113
|
name == 'has_many'
|
21
114
|
end
|
data/lib/attribute.rb
CHANGED
data/lib/ead.rb
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
require 'json'
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
require 'block'
|
2
|
+
require 'table'
|
3
|
+
require 'entity'
|
5
4
|
require 'rest-client'
|
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
|
|
11
|
-
unless ['0.
|
10
|
+
unless ['0.4.0', '0.4.1', '0.4.2'].include? JSON.parse(file)['version']
|
12
11
|
puts "\n\n----------------"
|
13
12
|
puts "\e[31m#{
|
14
13
|
'Versions of your EAD file and the gem are not compatible.'\
|
15
|
-
|
16
|
-
|
14
|
+
' So, you may have some unexpected results.'\
|
15
|
+
'To run your EAD file correctly, please run'
|
17
16
|
}\e[0m"
|
18
17
|
|
19
18
|
puts "\e[31m#{
|
@@ -21,72 +20,65 @@ class EAD
|
|
21
20
|
}\e[0m"
|
22
21
|
puts "----------------\n\n"
|
23
22
|
|
24
|
-
raise StandardError
|
23
|
+
raise StandardError, msg = 'Incompatible version'
|
25
24
|
end
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
file
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_objects(file)
|
30
|
+
@nodes = JSON.parse(file)['nodes']
|
31
|
+
@edges = JSON.parse(file)['edges']
|
32
|
+
@tables = JSON.parse(file)['tables']
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
@tables = @tables.map do |(id)|
|
35
|
+
Table.new(id, @tables)
|
36
|
+
end
|
37
|
+
|
38
|
+
@nodes.map! do |node|
|
39
|
+
Entity.new(node)
|
36
40
|
end
|
37
|
-
end
|
38
41
|
|
39
|
-
|
40
|
-
|
41
|
-
if sub_block.entity
|
42
|
-
Item.new(sub_block)
|
43
|
-
elsif sub_block.entity_clone
|
44
|
-
ItemClone.new(sub_block)
|
45
|
-
elsif sub_block.entity_container || sub_block.entity_association
|
46
|
-
create_items(sub_block)
|
47
|
-
end
|
42
|
+
@edges.map! do |edge|
|
43
|
+
Association.new(edge)
|
48
44
|
end
|
49
45
|
end
|
50
46
|
|
51
|
-
def
|
52
|
-
|
53
|
-
block = Block.find(ead_id)
|
54
|
-
create_items(block)
|
47
|
+
def check_implement_objects(file)
|
48
|
+
create_objects(file)
|
55
49
|
|
56
|
-
|
57
|
-
|
58
|
-
item_clone.clone_parent = Item.find(item_clone.clone_parent)
|
59
|
-
parent.clones << item_clone
|
50
|
+
Entity.all.each do |entity|
|
51
|
+
entity.clone_parent.entities << entity
|
60
52
|
end
|
61
53
|
|
62
|
-
|
63
|
-
|
64
|
-
|
54
|
+
Table.all.each(&:create_model)
|
55
|
+
|
56
|
+
Table.all.each(&:add_reference_migration)
|
65
57
|
|
66
|
-
|
67
|
-
|
58
|
+
Association.set_middle_entities
|
59
|
+
|
60
|
+
Association.all.each do |association|
|
61
|
+
association.first_entity.update_model(association.second_entity, association)
|
68
62
|
end
|
69
63
|
end
|
70
64
|
|
71
65
|
def check_latest_version
|
72
|
-
# response = RestClient::Request.new(:method => :get, :url => 'https://api.github.com/repos/ozovalihasan/ead/tags')
|
73
|
-
# response = JSON.parse response
|
74
66
|
response = JSON.parse RestClient.get 'https://api.github.com/repos/ozovalihasan/ead/tags'
|
75
|
-
|
76
|
-
unless response.first['name'] ==
|
67
|
+
|
68
|
+
unless response.first['name'] == 'v0.4.2'
|
77
69
|
puts "\n\n----------------"
|
78
70
|
puts "\n\e[33m#{
|
79
71
|
'A new version of this gem has been released.'\
|
80
|
-
|
72
|
+
' Please check it. https://github.com/ozovalihasan/ead-g/releases'
|
81
73
|
}\e[0m"
|
82
74
|
|
83
75
|
puts "\n----------------\n\n"
|
84
76
|
end
|
85
|
-
rescue
|
77
|
+
rescue StandardError
|
86
78
|
puts "\n\n----------------"
|
87
79
|
puts "\n\e[31m#{
|
88
80
|
'If you want to check the latest version of this gem,'\
|
89
|
-
|
81
|
+
' you need to have a stable internet connection.'
|
90
82
|
}\e[0m"
|
91
83
|
|
92
84
|
puts "\n----------------\n\n"
|
@@ -94,7 +86,7 @@ class EAD
|
|
94
86
|
|
95
87
|
def start(user_arguments)
|
96
88
|
check_latest_version
|
97
|
-
import_JSON(user_arguments)
|
98
|
-
|
89
|
+
file = import_JSON(user_arguments)
|
90
|
+
check_implement_objects(file)
|
99
91
|
end
|
100
92
|
end
|
data/lib/entity.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'table_entity_base'
|
2
|
+
require 'association'
|
3
|
+
require 'project_file'
|
4
|
+
|
5
|
+
class Entity < TableEntityBase
|
6
|
+
attr_accessor(:name, :id, :twin_name, :clone_parent, :parent, :parent_association, :associations, :parent_associations,
|
7
|
+
:parents_has_one, :parents_has_many, :parents_through, :children_has_one, :children_has_many, :children_through,
|
8
|
+
:children_has_one_through, :children_has_many_through, :parents_has_one_through, :parents_has_many_through)
|
9
|
+
|
10
|
+
def initialize(node)
|
11
|
+
@id = node['id']
|
12
|
+
@name = node['data']['name'].split(' || ')[0].underscore.singularize
|
13
|
+
@twin_name = node['data']['name'].split(' || ')[1]&.underscore&.singularize
|
14
|
+
@clone_parent = Table.find(node['data']['tableId'])
|
15
|
+
|
16
|
+
@parent_associations = []
|
17
|
+
@associations = []
|
18
|
+
|
19
|
+
@parents_has_one = []
|
20
|
+
@parents_has_many = []
|
21
|
+
@parents_has_one_through = []
|
22
|
+
@parents_has_many_through = []
|
23
|
+
@parents_through = []
|
24
|
+
|
25
|
+
@children_has_one = []
|
26
|
+
@children_has_many = []
|
27
|
+
@children_has_one_through = []
|
28
|
+
@children_has_many_through = []
|
29
|
+
@children_through = []
|
30
|
+
end
|
31
|
+
|
32
|
+
def model_name
|
33
|
+
clone_parent.name.camelize
|
34
|
+
end
|
35
|
+
|
36
|
+
def tables_same?(entity)
|
37
|
+
table == entity.table
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.find_by_name(name)
|
41
|
+
all.find { |entity| entity.name == name }
|
42
|
+
end
|
43
|
+
|
44
|
+
def clone_name_different?
|
45
|
+
clone_parent.name != name
|
46
|
+
end
|
47
|
+
|
48
|
+
def one_polymorphic_names?(entity)
|
49
|
+
table.polymorphic && table.polymorphic_names.include?(entity.name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def table
|
53
|
+
clone_parent
|
54
|
+
end
|
55
|
+
|
56
|
+
def update_end_model_migration_files(start_entity, association)
|
57
|
+
polymorphic_end = one_polymorphic_names?(start_entity)
|
58
|
+
|
59
|
+
return if polymorphic_end
|
60
|
+
|
61
|
+
end_model_line = {}
|
62
|
+
end_migration_line = {}
|
63
|
+
|
64
|
+
if association.has_any?
|
65
|
+
end_model_line['belongs_to'] = ":#{start_entity.name}"
|
66
|
+
|
67
|
+
if tables_same?(start_entity)
|
68
|
+
end_model_line['optional'] = 'true'
|
69
|
+
end_migration_line['null'] = 'true'
|
70
|
+
else
|
71
|
+
end_migration_line['null'] = 'false'
|
72
|
+
end
|
73
|
+
|
74
|
+
if !polymorphic_end && start_entity.clone_name_different?
|
75
|
+
end_model_line['class_name'] = "\"#{start_entity.clone_parent.name.camelize}\""
|
76
|
+
end_migration_line['foreign_key'] = "{ to_table: :#{start_entity.clone_parent.name.pluralize} }"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
ProjectFile.add_belong_line(clone_parent.name, end_model_line) unless end_model_line.empty?
|
81
|
+
|
82
|
+
unless end_migration_line.empty?
|
83
|
+
migration_name = "Add#{start_entity.name.camelize}RefTo#{clone_parent.name.camelize}".underscore
|
84
|
+
|
85
|
+
ProjectFile.update_line(migration_name, 'reference_migration', /add_reference :#{clone_parent.name.pluralize}/,
|
86
|
+
end_migration_line)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def update_start_model_file(end_entity, association)
|
91
|
+
start_model = table.name
|
92
|
+
|
93
|
+
end_model = end_entity.name
|
94
|
+
intermediate_entity = association.through_entity
|
95
|
+
|
96
|
+
intermediate_model = intermediate_entity.name if intermediate_entity
|
97
|
+
|
98
|
+
if association.has_many? || (children_has_many_through.include? end_entity)
|
99
|
+
end_model = end_model.pluralize
|
100
|
+
intermediate_model = intermediate_model.pluralize if intermediate_model
|
101
|
+
end
|
102
|
+
|
103
|
+
line_content = {}
|
104
|
+
|
105
|
+
if association.has_many? || (children_has_many_through.include? end_entity)
|
106
|
+
line_content['has_many'] = if intermediate_entity&.one_polymorphic_names?(end_entity) && (association.has_many? || (children_has_many_through.include? end_entity))
|
107
|
+
":#{end_entity.table.name.pluralize}"
|
108
|
+
else
|
109
|
+
":#{end_model}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
if association.has_one? || (children_has_one_through.include? end_entity)
|
114
|
+
line_content['has_one'] = if intermediate_entity&.one_polymorphic_names?(end_entity) && (association.has_one? || (children_has_one_through.include? end_entity))
|
115
|
+
":#{end_entity.table.name}"
|
116
|
+
else
|
117
|
+
":#{end_model}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
if intermediate_entity
|
122
|
+
line_content['through'] = ":#{intermediate_model}"
|
123
|
+
if intermediate_entity.one_polymorphic_names?(end_entity)
|
124
|
+
line_content['source'] = ":#{end_entity.name}"
|
125
|
+
line_content['source_type'] = "\"#{end_entity.table.name.camelize}\" "
|
126
|
+
end
|
127
|
+
elsif !intermediate_entity
|
128
|
+
line_content['class_name'] = "\"#{end_entity.table.name.camelize}\"" if end_entity.clone_name_different?
|
129
|
+
|
130
|
+
if end_entity.one_polymorphic_names?(self)
|
131
|
+
line_content['as'] = ":#{name}"
|
132
|
+
elsif clone_name_different?
|
133
|
+
line_content['foreign_key'] = "\"#{name.singularize}_id\""
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
ProjectFile.add_line(start_model, end_model, line_content)
|
138
|
+
end
|
139
|
+
|
140
|
+
def update_model(end_entity, association)
|
141
|
+
end_entity.update_end_model_migration_files(self, association) if association.has_any?
|
142
|
+
|
143
|
+
update_start_model_file(end_entity, association)
|
144
|
+
end
|
145
|
+
end
|
data/lib/project_file.rb
CHANGED
@@ -9,8 +9,10 @@ class ProjectFile
|
|
9
9
|
when 'model'
|
10
10
|
tempfile_name = './app/models/model_update.rb'
|
11
11
|
file_name = "./app/models/#{name}.rb"
|
12
|
+
when 'reference_migration'
|
13
|
+
tempfile_name = './db/migrate/migration_update.rb'
|
14
|
+
file_name = Dir.glob("./db/migrate/*_#{name}.rb").first
|
12
15
|
end
|
13
|
-
|
14
16
|
tempfile = File.open(tempfile_name, 'w')
|
15
17
|
file = File.new(file_name)
|
16
18
|
|
@@ -29,10 +31,10 @@ class ProjectFile
|
|
29
31
|
open_close(name, type) do |file, tempfile|
|
30
32
|
file.each do |line|
|
31
33
|
if line.match(keywords)
|
32
|
-
line.gsub!(
|
34
|
+
line.gsub!(/ *\n/, '')
|
33
35
|
line_content.each do |key, value|
|
34
36
|
if line.include? key
|
35
|
-
line.gsub!(/#{key}:
|
37
|
+
line.gsub!(/#{key}: [^(\s,)]*/, "#{key}: #{value}#{Regexp.last_match(1)}")
|
36
38
|
else
|
37
39
|
line << ", #{key}: #{value}"
|
38
40
|
end
|
@@ -67,4 +69,27 @@ class ProjectFile
|
|
67
69
|
end
|
68
70
|
end
|
69
71
|
end
|
72
|
+
|
73
|
+
def self.add_belong_line(name, line_content)
|
74
|
+
open_close(name, 'model') do |file, tempfile|
|
75
|
+
line_found = false
|
76
|
+
file.each do |line|
|
77
|
+
tempfile << line
|
78
|
+
next unless line.include?('class') && !line_found
|
79
|
+
|
80
|
+
line_found = true
|
81
|
+
line_association = ''
|
82
|
+
line_content.each do |key, value|
|
83
|
+
line_association << if %w[belongs_to].include?(key)
|
84
|
+
" #{key} #{value}"
|
85
|
+
else
|
86
|
+
", #{key}: #{value}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
line_association << "\n"
|
91
|
+
tempfile << line_association
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
70
95
|
end
|
data/lib/table.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'table_entity_base'
|
2
|
+
require 'attribute'
|
3
|
+
require 'association'
|
4
|
+
require 'active_support/core_ext/string'
|
5
|
+
|
6
|
+
class Table < TableEntityBase
|
7
|
+
attr_accessor :name, :id, :twin_name, :attributes, :entities, :polymorphic, :polymorphic_names
|
8
|
+
|
9
|
+
def initialize(table_id, tables)
|
10
|
+
@id = table_id
|
11
|
+
@name = tables[table_id]['name'].split(' || ')[0].underscore.singularize
|
12
|
+
@entities = []
|
13
|
+
@polymorphic = false
|
14
|
+
@polymorphic_names = []
|
15
|
+
@attributes = []
|
16
|
+
tables[table_id]['attributes'].each do |(_attribute_id, attribute)|
|
17
|
+
@attributes << Attribute.new(attribute)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def model_name
|
22
|
+
name.camelize
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_references(entity)
|
26
|
+
command = "bundle exec rails generate migration Add#{entity.name.camelize}RefTo#{name.camelize} #{entity.name}:references"
|
27
|
+
|
28
|
+
system(command)
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_polymorphic_reference(command, poly_name)
|
32
|
+
command << " #{poly_name}:references{polymorphic}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def update_polymorphic_names
|
36
|
+
return if entities.size.zero?
|
37
|
+
|
38
|
+
belong_parents = []
|
39
|
+
entities.each do |entity|
|
40
|
+
entity.parent_associations.each do |association|
|
41
|
+
belong_parents << association.first_entity
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
belong_parent_names = belong_parents.map(&:name)
|
46
|
+
|
47
|
+
filtered_parent_names = belong_parent_names.find_all do |parent_name|
|
48
|
+
belong_parent_names.count(parent_name) > 1
|
49
|
+
end.uniq
|
50
|
+
|
51
|
+
@polymorphic_names = filtered_parent_names.find_all do |parent_name|
|
52
|
+
belong_parents.find_all do |entity|
|
53
|
+
entity.name == parent_name
|
54
|
+
end.map(&:clone_parent).map(&:name).uniq.size > 1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def check_polymorphic(command)
|
59
|
+
update_polymorphic_names
|
60
|
+
@polymorphic_names.each do |poly_name|
|
61
|
+
add_polymorphic_reference(command, poly_name)
|
62
|
+
end
|
63
|
+
|
64
|
+
@polymorphic = true if @polymorphic_names.size.positive?
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_model
|
68
|
+
return if File.exist?("./app/models/#{name}.rb")
|
69
|
+
|
70
|
+
command = 'bundle exec rails generate model '
|
71
|
+
command << model_name
|
72
|
+
attributes.each { |attribute| attribute.add_to(command) }
|
73
|
+
|
74
|
+
check_polymorphic(command)
|
75
|
+
|
76
|
+
system(command)
|
77
|
+
end
|
78
|
+
|
79
|
+
def add_reference_migration
|
80
|
+
entities.each do |entity|
|
81
|
+
(entity.parents_has_many + entity.parents_has_one).each do |parent|
|
82
|
+
next if entity.one_polymorphic_names?(parent)
|
83
|
+
|
84
|
+
add_references(parent)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
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.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hasan Ozovali
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -58,6 +58,20 @@ dependencies:
|
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '2.2'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: pry
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.14.1
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.14.1
|
61
75
|
- !ruby/object:Gem::Dependency
|
62
76
|
name: rspec
|
63
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,16 +111,16 @@ files:
|
|
97
111
|
- bin/ead
|
98
112
|
- lib/association.rb
|
99
113
|
- lib/attribute.rb
|
100
|
-
- lib/block.rb
|
101
114
|
- lib/ead.rb
|
102
|
-
- lib/
|
103
|
-
- lib/item_base.rb
|
104
|
-
- lib/item_clone.rb
|
115
|
+
- lib/entity.rb
|
105
116
|
- lib/project_file.rb
|
117
|
+
- lib/table.rb
|
118
|
+
- lib/table_entity_base.rb
|
106
119
|
homepage: https://rubygems.org/gems/ead
|
107
120
|
licenses:
|
108
121
|
- MIT
|
109
|
-
metadata:
|
122
|
+
metadata:
|
123
|
+
rubygems_mfa_required: 'true'
|
110
124
|
post_install_message:
|
111
125
|
rdoc_options: []
|
112
126
|
require_paths:
|
@@ -122,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
136
|
- !ruby/object:Gem::Version
|
123
137
|
version: '0'
|
124
138
|
requirements: []
|
125
|
-
rubygems_version: 3.
|
139
|
+
rubygems_version: 3.3.7
|
126
140
|
signing_key:
|
127
141
|
specification_version: 4
|
128
142
|
summary: Compiler for JSON files created by EAD
|
data/lib/block.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
class Block
|
2
|
-
attr_accessor :id, :content, :category, :attribute, :type, :association, :sub_blocks,
|
3
|
-
:clone_blocks, :cloneable, :entity, :entity_clone, :clone_parent, :entity_container, :entity_association
|
4
|
-
|
5
|
-
def initialize(id, items)
|
6
|
-
item = items[id]
|
7
|
-
@id = id
|
8
|
-
@content = item['content']
|
9
|
-
@category = item['category']
|
10
|
-
@entity = item['entity']
|
11
|
-
@entity_association = item['entityAssociation']
|
12
|
-
@entity_container = item['entityContainer']
|
13
|
-
@attribute = item['attribute']
|
14
|
-
@type = item['type']
|
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
|
20
|
-
@sub_blocks = []
|
21
|
-
item['subItemIds'].each do |sub_item_id|
|
22
|
-
sub_item_id = sub_item_id.to_s
|
23
|
-
@sub_blocks << Block.new(sub_item_id, items)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.all
|
28
|
-
ObjectSpace.each_object(self).to_a
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.find(id)
|
32
|
-
all.find { |block| block.id == id }
|
33
|
-
end
|
34
|
-
end
|
data/lib/item.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'item_base'
|
2
|
-
require 'attribute'
|
3
|
-
require 'association'
|
4
|
-
require 'active_support/core_ext/string'
|
5
|
-
|
6
|
-
class Item < ItemBase
|
7
|
-
attr_accessor :attributes, :clones, :polymorphic, :polymorphic_names
|
8
|
-
|
9
|
-
def initialize(block)
|
10
|
-
super(block)
|
11
|
-
@clones = []
|
12
|
-
@polymorphic = false
|
13
|
-
@polymorphic_names = []
|
14
|
-
@attributes = []
|
15
|
-
block.sub_blocks.each do |sub_block|
|
16
|
-
add_to_attributes(sub_block)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def add_to_attributes(block)
|
21
|
-
@attributes << Attribute.new(block.content, block.type)
|
22
|
-
end
|
23
|
-
|
24
|
-
def model_name
|
25
|
-
name.camelize
|
26
|
-
end
|
27
|
-
|
28
|
-
def add_references(command, item)
|
29
|
-
return if command.include? " #{item.name}:references"
|
30
|
-
|
31
|
-
command << " #{item.name}:references"
|
32
|
-
end
|
33
|
-
|
34
|
-
def add_polymorphic(command, poly_name)
|
35
|
-
command << " #{poly_name}:references{polymorphic}"
|
36
|
-
end
|
37
|
-
|
38
|
-
def update_polymorphic_names
|
39
|
-
return if clones.size.zero?
|
40
|
-
|
41
|
-
belong_parents = []
|
42
|
-
clones.each do |item|
|
43
|
-
if item.through_association && item.parent_has_many?
|
44
|
-
belong_parents << item.parent
|
45
|
-
belong_parents << item.through_child
|
46
|
-
elsif !item.parent_through_has_many? && item.parent
|
47
|
-
belong_parents << item.parent
|
48
|
-
end
|
49
|
-
end
|
50
|
-
belong_parent_names = belong_parents.map(&:name)
|
51
|
-
|
52
|
-
filtered_parent_names = belong_parent_names.find_all do |parent_name|
|
53
|
-
belong_parent_names.count(parent_name) > 1
|
54
|
-
end.uniq
|
55
|
-
|
56
|
-
@polymorphic_names = filtered_parent_names.find_all do |parent_name|
|
57
|
-
belong_parents.find_all do |item|
|
58
|
-
item.name == parent_name
|
59
|
-
end.map(&:clone_parent).map(&:name).uniq.size > 1
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def check_polymorphic(command)
|
64
|
-
update_polymorphic_names
|
65
|
-
@polymorphic_names.each do |poly_name|
|
66
|
-
add_polymorphic(command, poly_name)
|
67
|
-
end
|
68
|
-
|
69
|
-
@polymorphic = true if @polymorphic_names.size.positive?
|
70
|
-
end
|
71
|
-
|
72
|
-
def create_migration
|
73
|
-
return if File.exist?("./app/models/#{name}.rb")
|
74
|
-
|
75
|
-
command = 'bundle exec rails generate model '
|
76
|
-
command << model_name
|
77
|
-
attributes.each { |attribute| attribute.add_to(command) }
|
78
|
-
|
79
|
-
check_polymorphic(command)
|
80
|
-
|
81
|
-
clones.each do |item|
|
82
|
-
add_references(command, item.through_child) if item.parent_has_many? && item.through_association
|
83
|
-
|
84
|
-
next unless item.parent && !item.one_polymorphic_names?(item.parent) && (
|
85
|
-
item.parent_has_any? || item.parent_through_has_one?
|
86
|
-
)
|
87
|
-
|
88
|
-
add_references(command, item.parent)
|
89
|
-
end
|
90
|
-
system(command)
|
91
|
-
end
|
92
|
-
end
|
data/lib/item_base.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
class ItemBase
|
2
|
-
attr_accessor :name, :id, :twin_name
|
3
|
-
|
4
|
-
def initialize(block, _parent = nil, _parent_association = nil)
|
5
|
-
@id = block.id
|
6
|
-
@name = block.content.split(' || ')[0].underscore.singularize
|
7
|
-
@twin_name = block.content.split(' || ')[1]&.underscore&.singularize
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.all
|
11
|
-
ObjectSpace.each_object(self).to_a
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.find(id)
|
15
|
-
all.find { |item| item.id == id }
|
16
|
-
end
|
17
|
-
end
|
data/lib/item_clone.rb
DELETED
@@ -1,212 +0,0 @@
|
|
1
|
-
require 'item_base'
|
2
|
-
require 'association'
|
3
|
-
require 'project_file'
|
4
|
-
|
5
|
-
class ItemClone < ItemBase
|
6
|
-
attr_accessor :clone_parent, :parent, :parent_association, :associations
|
7
|
-
|
8
|
-
def initialize(block, parent = nil, parent_association = nil)
|
9
|
-
super(block)
|
10
|
-
@clone_parent = block.clone_parent
|
11
|
-
@parent = parent
|
12
|
-
@parent_association = parent_association
|
13
|
-
|
14
|
-
@associations = []
|
15
|
-
block.sub_blocks.each do |sub_block|
|
16
|
-
add_to_associations(sub_block)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def model_name
|
21
|
-
clone_parent.name.camelize
|
22
|
-
end
|
23
|
-
|
24
|
-
def add_to_associations(block)
|
25
|
-
@associations << Association.new(self, block)
|
26
|
-
end
|
27
|
-
|
28
|
-
def grand
|
29
|
-
parent.parent
|
30
|
-
end
|
31
|
-
|
32
|
-
def grand_association
|
33
|
-
parent.parent_association
|
34
|
-
end
|
35
|
-
|
36
|
-
def grand_has_many?
|
37
|
-
grand_association&.has_many?
|
38
|
-
end
|
39
|
-
|
40
|
-
def grand_has_one?
|
41
|
-
grand_association&.has_one?
|
42
|
-
end
|
43
|
-
|
44
|
-
def grand_real_self_real?
|
45
|
-
reals_same? grand
|
46
|
-
end
|
47
|
-
|
48
|
-
def reals_same?(item)
|
49
|
-
real_item == item.real_item
|
50
|
-
end
|
51
|
-
|
52
|
-
def parent_through?
|
53
|
-
parent_association&.through?
|
54
|
-
end
|
55
|
-
|
56
|
-
def parent_has_many?
|
57
|
-
parent_association&.has_many?
|
58
|
-
end
|
59
|
-
|
60
|
-
def parent_has_one?
|
61
|
-
parent_association&.has_one?
|
62
|
-
end
|
63
|
-
|
64
|
-
def parent_has_any?
|
65
|
-
parent_has_one? || parent_has_many?
|
66
|
-
end
|
67
|
-
|
68
|
-
def parent_through_has_one?
|
69
|
-
parent_through? && grand_has_one?
|
70
|
-
end
|
71
|
-
|
72
|
-
def parent_through_has_many?
|
73
|
-
parent_through? && grand_has_many?
|
74
|
-
end
|
75
|
-
|
76
|
-
def through_association
|
77
|
-
associations.find(&:through?)
|
78
|
-
end
|
79
|
-
|
80
|
-
def through_child
|
81
|
-
through_association&.second_items&.first
|
82
|
-
end
|
83
|
-
|
84
|
-
def through?(item)
|
85
|
-
item.present?
|
86
|
-
end
|
87
|
-
|
88
|
-
def clone_name_different?
|
89
|
-
clone_parent.name != name
|
90
|
-
end
|
91
|
-
|
92
|
-
def one_polymorphic_names?(item)
|
93
|
-
real_item.polymorphic && real_item.polymorphic_names.include?(item.name)
|
94
|
-
end
|
95
|
-
|
96
|
-
def real_item
|
97
|
-
clone_parent
|
98
|
-
end
|
99
|
-
|
100
|
-
def grand_many_through_reals_same?(item)
|
101
|
-
parent_through_has_many? && (grand == item) && reals_same?(item)
|
102
|
-
end
|
103
|
-
|
104
|
-
def parent_has_many_reals_same_through_child?(item)
|
105
|
-
item.parent_through_has_many? && (through_child == item) && item.reals_same?(parent)
|
106
|
-
end
|
107
|
-
|
108
|
-
def update_end_model_migration_files(start_item, association)
|
109
|
-
polymorphic_end = one_polymorphic_names?(start_item)
|
110
|
-
|
111
|
-
end_model_line = {}
|
112
|
-
end_migration_line = {}
|
113
|
-
if association.has_one? && start_item.parent&.reals_same?(self)
|
114
|
-
end_model_line['optional'] = 'true'
|
115
|
-
end_migration_line['null'] = 'true'
|
116
|
-
end
|
117
|
-
|
118
|
-
if association.has_any?
|
119
|
-
if reals_same?(start_item)
|
120
|
-
end_model_line['optional'] = 'true'
|
121
|
-
end_migration_line['null'] = 'true'
|
122
|
-
end
|
123
|
-
|
124
|
-
if !polymorphic_end && start_item.clone_name_different?
|
125
|
-
end_model_line['class_name'] = "\"#{start_item.clone_parent.name.camelize}\""
|
126
|
-
end_migration_line['foreign_key'] = "{ to_table: :#{start_item.clone_parent.name.pluralize} }"
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
ProjectFile.update_line(real_item.name, 'model', /belongs_to :#{start_item.name}/, end_model_line)
|
131
|
-
|
132
|
-
migration_name = real_item.name
|
133
|
-
ProjectFile.update_line(migration_name, 'migration', /t.references :#{start_item.name}/, end_migration_line)
|
134
|
-
end
|
135
|
-
|
136
|
-
def update_start_model_file(end_item, association, intermediate_item = nil)
|
137
|
-
start_model = real_item.name
|
138
|
-
|
139
|
-
end_model = if end_item.parent_has_many_reals_same_through_child?(self)
|
140
|
-
end_item.twin_name
|
141
|
-
else
|
142
|
-
end_item.name
|
143
|
-
end
|
144
|
-
|
145
|
-
intermediate_model = if grand_many_through_reals_same?(end_item)
|
146
|
-
intermediate_item.twin_name
|
147
|
-
elsif intermediate_item
|
148
|
-
intermediate_item.name
|
149
|
-
end
|
150
|
-
|
151
|
-
if association.has_many?
|
152
|
-
end_model = end_model.pluralize
|
153
|
-
intermediate_model = intermediate_model.pluralize if intermediate_model
|
154
|
-
end
|
155
|
-
|
156
|
-
line_content = {}
|
157
|
-
line_content[association.name] = if intermediate_item&.one_polymorphic_names?(end_item) && association.has_many?
|
158
|
-
":#{end_item.real_item.name.pluralize}"
|
159
|
-
else
|
160
|
-
":#{end_model}"
|
161
|
-
end
|
162
|
-
|
163
|
-
if intermediate_item
|
164
|
-
line_content['through'] = ":#{intermediate_model}"
|
165
|
-
if intermediate_item.one_polymorphic_names?(end_item)
|
166
|
-
line_content['source'] = ":#{end_item.name}"
|
167
|
-
line_content['source_type'] = "\"#{end_item.real_item.name.camelize}\" "
|
168
|
-
end
|
169
|
-
elsif !intermediate_item
|
170
|
-
line_content['class_name'] = "\"#{end_item.real_item.name.camelize}\"" if end_item.clone_name_different?
|
171
|
-
|
172
|
-
if end_item.one_polymorphic_names?(self)
|
173
|
-
line_content['as'] = ":#{name}"
|
174
|
-
elsif clone_name_different?
|
175
|
-
line_content['foreign_key'] = "\"#{name.singularize}_id\""
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
ProjectFile.add_line(start_model, end_model, line_content)
|
180
|
-
end
|
181
|
-
|
182
|
-
def update_model(end_item, association, intermediate_item = nil)
|
183
|
-
return unless association.has_one? || association.has_many?
|
184
|
-
|
185
|
-
end_item.update_end_model_migration_files(self, association) unless intermediate_item
|
186
|
-
update_start_model_file(end_item, association, intermediate_item)
|
187
|
-
end
|
188
|
-
|
189
|
-
def parent_through_add_associations
|
190
|
-
if parent_through_has_many?
|
191
|
-
update_model(parent, grand_association)
|
192
|
-
update_model(grand, grand_association, parent)
|
193
|
-
|
194
|
-
elsif parent_through_has_one?
|
195
|
-
parent.update_model(self, grand_association)
|
196
|
-
end
|
197
|
-
|
198
|
-
grand.update_model(self, grand_association, parent)
|
199
|
-
end
|
200
|
-
|
201
|
-
def add_associations
|
202
|
-
parent_through_add_associations if parent_through?
|
203
|
-
|
204
|
-
associations.each do |association|
|
205
|
-
next unless association.has_any?
|
206
|
-
|
207
|
-
association.second_items.each do |second_item|
|
208
|
-
update_model(second_item, association)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|