ead 0.2.0 → 0.4.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 +4 -4
- data/lib/association.rb +105 -18
- data/lib/attribute.rb +3 -3
- data/lib/ead.rb +69 -38
- data/lib/entity.rb +145 -0
- data/lib/project_file.rb +30 -3
- data/lib/table.rb +88 -0
- data/lib/table_entity_base.rb +9 -0
- metadata +42 -8
- data/lib/block.rb +0 -34
- data/lib/item.rb +0 -70
- data/lib/item_base.rb +0 -239
- data/lib/item_clone.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0246f506ee0396b4da7f7dfd2cd58b856893a05148b593f999b7f0a704cb0f5
|
4
|
+
data.tar.gz: dd5e95c1b53959a0762c667d66913a60c3b222ec237d9a40c1931371a13e65bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa2bb67008c2de407ce152432cfee9a0ea5f8cdb222d2e89a8f28ca79d690970ca4200d9ae52f6150a5f7df7ec14ae7b2169abd83d8a6e6388058862c0bb3b6d
|
7
|
+
data.tar.gz: e269830ca88205dc5f2fe681574d7fe9b634c1fb76519651a6344083ca48003dd1ae79384b2e06d4313c77762d14e5e52ed52954aef8871f47e665c594bdc115
|
data/lib/association.rb
CHANGED
@@ -1,27 +1,114 @@
|
|
1
|
-
require '
|
1
|
+
require 'table'
|
2
2
|
|
3
3
|
class Association
|
4
|
-
attr_accessor :
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
4
|
+
attr_accessor :first_entity, :second_entity, :name, :middle_entities_has_one, :middle_entities_has_many,
|
5
|
+
:through_entity
|
6
|
+
|
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
|
21
46
|
end
|
22
47
|
end
|
23
48
|
end
|
24
49
|
|
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
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.set_middle_entities
|
107
|
+
associations = all.select(&:through?)
|
108
|
+
|
109
|
+
associations.each(&:set_middle_entity)
|
110
|
+
end
|
111
|
+
|
25
112
|
def has_many?
|
26
113
|
name == 'has_many'
|
27
114
|
end
|
data/lib/attribute.rb
CHANGED
data/lib/ead.rb
CHANGED
@@ -1,61 +1,92 @@
|
|
1
1
|
require 'json'
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
require '
|
2
|
+
require 'table'
|
3
|
+
require 'entity'
|
4
|
+
require 'rest-client'
|
5
5
|
|
6
6
|
class EAD
|
7
7
|
def import_JSON(user_arguments)
|
8
8
|
file = File.read(user_arguments[0] || './EAD.json')
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
|
10
|
+
unless ['0.4.0'].include? JSON.parse(file)['version']
|
11
|
+
puts "\n\n----------------"
|
12
|
+
puts "\e[31m#{
|
13
|
+
'Versions of your EAD file and the gem are not compatible.'\
|
14
|
+
' So, you may have some unexpected results.'\
|
15
|
+
'To run your EAD file correctly, please run'
|
16
|
+
}\e[0m"
|
17
|
+
|
18
|
+
puts "\e[31m#{
|
19
|
+
"\ngem install ead -v #{JSON.parse(file)['version']}"
|
20
|
+
}\e[0m"
|
21
|
+
puts "----------------\n\n"
|
22
|
+
|
23
|
+
raise StandardError, msg = 'Incompatible version'
|
18
24
|
end
|
25
|
+
|
26
|
+
file
|
19
27
|
end
|
20
28
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
create_items(sub_block)
|
29
|
-
end
|
29
|
+
def create_objects(file)
|
30
|
+
@nodes = JSON.parse(file)['nodes']
|
31
|
+
@edges = JSON.parse(file)['edges']
|
32
|
+
@tables = JSON.parse(file)['tables']
|
33
|
+
|
34
|
+
@tables = @tables.map do |(id)|
|
35
|
+
Table.new(id, @tables)
|
30
36
|
end
|
31
|
-
end
|
32
37
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
create_items(block)
|
38
|
+
@nodes.map! do |node|
|
39
|
+
Entity.new(node)
|
40
|
+
end
|
37
41
|
|
38
|
-
|
39
|
-
|
40
|
-
item_clone.clone_parent = Item.find(item_clone.clone_parent)
|
41
|
-
parent.clones << item_clone
|
42
|
+
@edges.map! do |edge|
|
43
|
+
Association.new(edge)
|
42
44
|
end
|
45
|
+
end
|
43
46
|
|
44
|
-
|
45
|
-
|
47
|
+
def check_implement_objects(file)
|
48
|
+
create_objects(file)
|
49
|
+
|
50
|
+
Entity.all.each do |entity|
|
51
|
+
entity.clone_parent.entities << entity
|
46
52
|
end
|
47
53
|
|
48
|
-
|
49
|
-
|
54
|
+
Table.all.each(&:create_model)
|
55
|
+
|
56
|
+
Table.all.each(&:add_reference_migration)
|
57
|
+
|
58
|
+
Association.set_middle_entities
|
59
|
+
|
60
|
+
Association.all.each do |association|
|
61
|
+
association.first_entity.update_model(association.second_entity, association)
|
50
62
|
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def check_latest_version
|
66
|
+
response = JSON.parse RestClient.get 'https://api.github.com/repos/ozovalihasan/ead/tags'
|
51
67
|
|
52
|
-
|
53
|
-
|
68
|
+
unless response.first['name'] == 'v0.4.0'
|
69
|
+
puts "\n\n----------------"
|
70
|
+
puts "\n\e[33m#{
|
71
|
+
'A new version of this gem has been released.'\
|
72
|
+
' Please check it. https://github.com/ozovalihasan/ead-g/releases'
|
73
|
+
}\e[0m"
|
74
|
+
|
75
|
+
puts "\n----------------\n\n"
|
54
76
|
end
|
77
|
+
rescue StandardError
|
78
|
+
puts "\n\n----------------"
|
79
|
+
puts "\n\e[31m#{
|
80
|
+
'If you want to check the latest version of this gem,'\
|
81
|
+
' you need to have a stable internet connection.'
|
82
|
+
}\e[0m"
|
83
|
+
|
84
|
+
puts "\n----------------\n\n"
|
55
85
|
end
|
56
86
|
|
57
87
|
def start(user_arguments)
|
58
|
-
|
59
|
-
|
88
|
+
check_latest_version
|
89
|
+
file = import_JSON(user_arguments)
|
90
|
+
check_implement_objects(file)
|
60
91
|
end
|
61
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
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
1
3
|
class ProjectFile
|
2
4
|
def self.open_close(name, type, &block)
|
3
5
|
case type
|
@@ -7,8 +9,10 @@ class ProjectFile
|
|
7
9
|
when 'model'
|
8
10
|
tempfile_name = './app/models/model_update.rb'
|
9
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
|
10
15
|
end
|
11
|
-
|
12
16
|
tempfile = File.open(tempfile_name, 'w')
|
13
17
|
file = File.new(file_name)
|
14
18
|
|
@@ -27,10 +31,10 @@ class ProjectFile
|
|
27
31
|
open_close(name, type) do |file, tempfile|
|
28
32
|
file.each do |line|
|
29
33
|
if line.match(keywords)
|
30
|
-
line.gsub!(
|
34
|
+
line.gsub!(/ *\n/, '')
|
31
35
|
line_content.each do |key, value|
|
32
36
|
if line.include? key
|
33
|
-
line.gsub!(/#{key}:
|
37
|
+
line.gsub!(/#{key}: [^(\s,)]*/, "#{key}: #{value}#{Regexp.last_match(1)}")
|
34
38
|
else
|
35
39
|
line << ", #{key}: #{value}"
|
36
40
|
end
|
@@ -65,4 +69,27 @@ class ProjectFile
|
|
65
69
|
end
|
66
70
|
end
|
67
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
|
68
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,15 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ead
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.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:
|
11
|
+
date: 2022-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rest-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.0.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.2
|
13
33
|
- !ruby/object:Gem::Dependency
|
14
34
|
name: activesupport
|
15
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +58,20 @@ dependencies:
|
|
38
58
|
- - "~>"
|
39
59
|
- !ruby/object:Gem::Version
|
40
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
|
41
75
|
- !ruby/object:Gem::Dependency
|
42
76
|
name: rspec
|
43
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -77,16 +111,16 @@ files:
|
|
77
111
|
- bin/ead
|
78
112
|
- lib/association.rb
|
79
113
|
- lib/attribute.rb
|
80
|
-
- lib/block.rb
|
81
114
|
- lib/ead.rb
|
82
|
-
- lib/
|
83
|
-
- lib/item_base.rb
|
84
|
-
- lib/item_clone.rb
|
115
|
+
- lib/entity.rb
|
85
116
|
- lib/project_file.rb
|
117
|
+
- lib/table.rb
|
118
|
+
- lib/table_entity_base.rb
|
86
119
|
homepage: https://rubygems.org/gems/ead
|
87
120
|
licenses:
|
88
121
|
- MIT
|
89
|
-
metadata:
|
122
|
+
metadata:
|
123
|
+
rubygems_mfa_required: 'true'
|
90
124
|
post_install_message:
|
91
125
|
rdoc_options: []
|
92
126
|
require_paths:
|
@@ -102,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
102
136
|
- !ruby/object:Gem::Version
|
103
137
|
version: '0'
|
104
138
|
requirements: []
|
105
|
-
rubygems_version: 3.
|
139
|
+
rubygems_version: 3.3.7
|
106
140
|
signing_key:
|
107
141
|
specification_version: 4
|
108
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_container, :attribute, :type, :association, :sub_blocks,
|
3
|
-
:clone_blocks, :cloneable, :entity, :entity_clone, :clone_parent, :entity_container
|
4
|
-
|
5
|
-
def initialize(id, items)
|
6
|
-
item = items[id]
|
7
|
-
@id = id
|
8
|
-
@content = item['content']
|
9
|
-
@category = item['category']
|
10
|
-
@attribute_container = item['attributeContainer']
|
11
|
-
@entity = item['entity']
|
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,70 +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 :clones, :polymorphic, :polymorphic_names
|
8
|
-
|
9
|
-
def initialize(block, parent = nil, parent_association = nil)
|
10
|
-
super(block, parent, parent_association)
|
11
|
-
@clones = []
|
12
|
-
@polymorphic = false
|
13
|
-
@polymorphic_names = []
|
14
|
-
end
|
15
|
-
|
16
|
-
def model_name
|
17
|
-
name.camelize
|
18
|
-
end
|
19
|
-
|
20
|
-
def add_references(command, item)
|
21
|
-
return if command.include? " #{item.name}:references"
|
22
|
-
|
23
|
-
command << " #{item.name}:references"
|
24
|
-
end
|
25
|
-
|
26
|
-
def add_polymorphic(command, poly_name)
|
27
|
-
command << " #{poly_name}:references{polymorphic}"
|
28
|
-
end
|
29
|
-
|
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
|
36
|
-
end
|
37
|
-
|
38
|
-
def check_polymorphic(command)
|
39
|
-
update_polymorphic_names
|
40
|
-
@polymorphic_names.each do |poly_name|
|
41
|
-
add_polymorphic(command, poly_name)
|
42
|
-
end
|
43
|
-
|
44
|
-
@polymorphic = true if @polymorphic_names.size.positive?
|
45
|
-
end
|
46
|
-
|
47
|
-
def create_migration
|
48
|
-
return if File.exist?("./app/models/#{name}.rb")
|
49
|
-
|
50
|
-
command = 'bundle exec rails generate model '
|
51
|
-
command << model_name
|
52
|
-
attributes.each { |attribute| attribute.add_to(command) }
|
53
|
-
|
54
|
-
check_polymorphic(command)
|
55
|
-
|
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)
|
60
|
-
end
|
61
|
-
|
62
|
-
next unless item.parent && !item.one_polymorphic_names?(item.parent) && (
|
63
|
-
item.parent_has_any? || item.parent_through_has_one?
|
64
|
-
)
|
65
|
-
|
66
|
-
add_references(command, item.parent)
|
67
|
-
end
|
68
|
-
system(command)
|
69
|
-
end
|
70
|
-
end
|
data/lib/item_base.rb
DELETED
@@ -1,239 +0,0 @@
|
|
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
DELETED
@@ -1,14 +0,0 @@
|
|
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
|