neo4apis-activerecord 0.6.1 → 0.7.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/README.md +18 -2
- data/lib/neo4apis/activerecord.rb +2 -4
- data/lib/neo4apis/cli/activerecord.rb +20 -55
- data/lib/neo4apis/model_resolver.rb +58 -0
- data/lib/neo4apis/table_resolver.rb +1 -1
- data/neo4apis-activerecord.gemspec +2 -2
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab2aa8e3fdbb40523bfb2bdf22f200c91e0dfc93
|
4
|
+
data.tar.gz: 5b408d16b2b3f86854576265a9dcd7b213ca1eeb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 122c016581350b4e990b7767e10f930cf93642db49f96c70f3a78b3a178509ad5fd432177c7fa0ad959f85885ad11246bb126043ab0e88c28371e309c0ae7a0d
|
7
|
+
data.tar.gz: d3502d4d5c0ff5f25885df4dbdbe2f608146f3bd6297187b71c9c0307dfb0aabe8e4e1d49791428b936e0b23995f18380d43e059a2186cb5f4b93e14d3a03e05
|
data/README.md
CHANGED
@@ -36,14 +36,16 @@ For a list of all options run:
|
|
36
36
|
|
37
37
|
neo4apis activerecord --help
|
38
38
|
|
39
|
+
Some options of particular interest:
|
40
|
+
|
39
41
|
### `--identify-model`
|
40
42
|
|
41
43
|
The `--identify-model` option looks for tables' names/primay keys/foreign keys automatically. Potential options are generated and the database is examined to find out which fits.
|
42
44
|
|
43
45
|
As an example: for a table of posts the following possibilities would checked:
|
44
46
|
|
45
|
-
* Names: `posts`, `post`, `Posts`, or `Post`
|
46
|
-
* Primary keys: `id`, `post_id`, `PostId`, or `uuid`
|
47
|
+
* Names: Looks for names like `posts`, `post`, `Posts`, or `Post`
|
48
|
+
* Primary keys: Table schema is examined first. If no primary key is specified it will look for columns like `id`, `post_id`, `PostId`, or `uuid`
|
47
49
|
* Foreign keys: `author_id` or `AuthorId` will be assumed to go to a table of authors (with a name identified as above)
|
48
50
|
|
49
51
|
### `--import-belongs-to`
|
@@ -53,3 +55,17 @@ As an example: for a table of posts the following possibilities would checked:
|
|
53
55
|
|
54
56
|
Either specify that a certain class of associations be imported from ActiveRecord models or specify all with `--import-all-associations`
|
55
57
|
|
58
|
+
## Using `neo4apis-activerecord` from ruby
|
59
|
+
|
60
|
+
If you'd like to do custom importing, you can use `neo4apis-activerecord` in the following way:
|
61
|
+
|
62
|
+
Neo4Apis::ActiveRecord.model_importer(SomeModel)
|
63
|
+
|
64
|
+
neo4apis_activerecord = Neo4Apis::ActiveRecord.new(Neo4j::Session.open, import_all_associations: true)
|
65
|
+
|
66
|
+
neo4apis_activerecord.batch do
|
67
|
+
SomeModel.where(condition: 'value').find_each do |object|
|
68
|
+
neo4apis_activerecord.import object
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
@@ -3,8 +3,6 @@ require 'ostruct'
|
|
3
3
|
|
4
4
|
module Neo4Apis
|
5
5
|
class ActiveRecord < Base
|
6
|
-
prefix nil
|
7
|
-
|
8
6
|
batch_size 1000
|
9
7
|
|
10
8
|
def self.model_importer(model_class)
|
@@ -21,8 +19,8 @@ module Neo4Apis
|
|
21
19
|
referenced_object = object.send(association_reflection.name)
|
22
20
|
add_model_relationship association_reflection.name, node, referenced_object if referenced_object
|
23
21
|
end
|
24
|
-
when :has_many
|
25
|
-
if options[:
|
22
|
+
when :has_many, :has_and_belongs_to_many
|
23
|
+
if options[:"import_#{association_reflection.macro}"]
|
26
24
|
object.send(association_reflection.name).each do |referenced_object|
|
27
25
|
add_model_relationship association_reflection.name, node, referenced_object if referenced_object
|
28
26
|
end
|
@@ -2,13 +2,15 @@ require 'active_record'
|
|
2
2
|
require 'active_support/inflector'
|
3
3
|
require 'thor'
|
4
4
|
require 'colorize'
|
5
|
-
require 'neo4apis/
|
5
|
+
require 'neo4apis/model_resolver'
|
6
6
|
require 'neo4apis/cli/base'
|
7
7
|
|
8
8
|
module Neo4Apis
|
9
9
|
module CLI
|
10
10
|
class ActiveRecord < CLI::Base
|
11
|
-
include
|
11
|
+
include ModelResolver
|
12
|
+
|
13
|
+
class_option :debug, type: :boolean, default: false, desc: 'Output debugging information'
|
12
14
|
|
13
15
|
class_option :import_all_associations, type: :boolean, default: false, desc: 'Shortcut for --import-belongs-to --import-has-many --import-has-one'
|
14
16
|
class_option :import_belongs_to, type: :boolean, default: nil
|
@@ -54,6 +56,12 @@ module Neo4Apis
|
|
54
56
|
|
55
57
|
private
|
56
58
|
|
59
|
+
def debug_log(*messages)
|
60
|
+
return unless options[:debug]
|
61
|
+
|
62
|
+
puts(*messages)
|
63
|
+
end
|
64
|
+
|
57
65
|
def import_models_or_tables(*models_or_table_names)
|
58
66
|
model_classes = models_or_table_names.map(&method(:get_model))
|
59
67
|
|
@@ -68,10 +76,8 @@ module Neo4Apis
|
|
68
76
|
query = model_class.all
|
69
77
|
|
70
78
|
# Eager load association for faster import
|
71
|
-
include_list = model_class
|
72
|
-
|
73
|
-
end.compact
|
74
|
-
query = query.includes(*include_list.map(&:to_sym)) if include_list.present?
|
79
|
+
include_list = include_list_for_model(model_class)
|
80
|
+
query = query.includes(*include_list) if include_list.present?
|
75
81
|
|
76
82
|
query.find_each do |object|
|
77
83
|
neo4apis_client.import model_class.name.to_sym, object
|
@@ -80,6 +86,14 @@ module Neo4Apis
|
|
80
86
|
end
|
81
87
|
end
|
82
88
|
|
89
|
+
def include_list_for_model(model_class)
|
90
|
+
model_class.reflect_on_all_associations.map do |association_reflection|
|
91
|
+
association_reflection.name.to_sym if import_association?(association_reflection.macro)
|
92
|
+
end.compact.tap do |include_list|
|
93
|
+
debug_log 'include_list', include_list.inspect
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
83
97
|
def setup
|
84
98
|
if File.exist?(options[:startup_environment])
|
85
99
|
require options[:startup_environment]
|
@@ -102,55 +116,6 @@ module Neo4Apis
|
|
102
116
|
end
|
103
117
|
|
104
118
|
|
105
|
-
def get_model(model_or_table_name)
|
106
|
-
get_model_class(model_or_table_name).tap do |model_class|
|
107
|
-
if options[:identify_model]
|
108
|
-
apply_identified_table_name!(model_class)
|
109
|
-
apply_identified_primary_key!(model_class)
|
110
|
-
apply_identified_model_associations!(model_class)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def get_model_class(model_or_table_name)
|
116
|
-
return model_or_table_name if model_or_table_name.is_a?(Class) && model_or_table_name.ancestors.include?(::ActiveRecord::Base)
|
117
|
-
|
118
|
-
model_class = model_or_table_name.gsub(/\s+/, '_')
|
119
|
-
model_class = model_or_table_name.classify unless model_or_table_name.match(/^[A-Z]/)
|
120
|
-
model_class.constantize
|
121
|
-
rescue NameError
|
122
|
-
Object.const_set(model_class, Class.new(::ActiveRecord::Base))
|
123
|
-
end
|
124
|
-
|
125
|
-
def apply_identified_model_associations!(model_class)
|
126
|
-
model_class.columns.each do |column|
|
127
|
-
match = column.name.match(/^(.*)(_id|Id)$/)
|
128
|
-
next if not match
|
129
|
-
|
130
|
-
begin
|
131
|
-
base = match[1].gsub(/ +/, '_').tableize
|
132
|
-
|
133
|
-
if identify_table_name(tables, base.classify) && model_class.name != base.classify
|
134
|
-
model_class.belongs_to base.singularize.to_sym, foreign_key: column.name, class_name: base.classify
|
135
|
-
end
|
136
|
-
rescue UnfoundTableError
|
137
|
-
nil
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def apply_identified_table_name!(model_class)
|
143
|
-
identity = identify_table_name(tables, model_class.name)
|
144
|
-
model_class.table_name = identity if identity
|
145
|
-
end
|
146
|
-
|
147
|
-
def apply_identified_primary_key!(model_class)
|
148
|
-
identity = ::ActiveRecord::Base.connection.primary_key(model_class.table_name)
|
149
|
-
identity ||= identify_primary_key(model_class.column_names, model_class.name)
|
150
|
-
model_class.primary_key = identity if identity
|
151
|
-
end
|
152
|
-
|
153
|
-
|
154
119
|
def active_record_config
|
155
120
|
require 'yaml'
|
156
121
|
YAML.load(File.read(options[:active_record_config_path]))[options[:active_record_environment]]
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'neo4apis/table_resolver'
|
2
|
+
|
3
|
+
module Neo4Apis
|
4
|
+
module ModelResolver
|
5
|
+
def self.included(included_class)
|
6
|
+
included_class.include TableResolver
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_model(model_or_table_name)
|
10
|
+
get_model_class(model_or_table_name).tap do |model_class|
|
11
|
+
if options[:identify_model]
|
12
|
+
apply_identified_table_name!(model_class)
|
13
|
+
apply_identified_primary_key!(model_class)
|
14
|
+
apply_identified_model_associations!(model_class)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_model_class(model_or_table_name)
|
20
|
+
return model_or_table_name if model_or_table_name.is_a?(Class) && model_or_table_name.ancestors.include?(::ActiveRecord::Base)
|
21
|
+
|
22
|
+
model_class = model_or_table_name.gsub(/\s+/, '_')
|
23
|
+
model_class = model_or_table_name.classify unless model_or_table_name.match(/^[A-Z]/)
|
24
|
+
model_class.constantize
|
25
|
+
rescue NameError
|
26
|
+
Object.const_set(model_class, Class.new(::ActiveRecord::Base))
|
27
|
+
end
|
28
|
+
|
29
|
+
def apply_identified_model_associations!(model_class)
|
30
|
+
model_class.columns.each do |column|
|
31
|
+
match = column.match(/^(.+)_id$/i) || column.match(/^(.+)id$/i)
|
32
|
+
next if not match
|
33
|
+
|
34
|
+
begin
|
35
|
+
base = match[1].gsub(/ +/, '_').tableize
|
36
|
+
|
37
|
+
if identify_table_name(tables, base.classify) && model_class.name != base.classify
|
38
|
+
debug_log "Defining: belongs_to #{base.singularize.to_sym.inspect}, foreign_key: #{column.name.inspect}, class_name: #{base.classify.inspect}"
|
39
|
+
model_class.belongs_to base.singularize.to_sym, foreign_key: column.name, class_name: base.classify
|
40
|
+
end
|
41
|
+
rescue UnfoundTableError
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def apply_identified_table_name!(model_class)
|
48
|
+
identity = identify_table_name(tables, model_class.name)
|
49
|
+
model_class.table_name = identity if identity
|
50
|
+
end
|
51
|
+
|
52
|
+
def apply_identified_primary_key!(model_class)
|
53
|
+
identity = ::ActiveRecord::Base.connection.primary_key(model_class.table_name)
|
54
|
+
identity ||= identify_primary_key(model_class.column_names, model_class.name)
|
55
|
+
model_class.primary_key = identity if identity
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'neo4apis-activerecord'
|
6
|
-
s.version = '0.
|
6
|
+
s.version = '0.7.0'
|
7
7
|
s.required_ruby_version = '>= 1.9.1'
|
8
8
|
|
9
9
|
s.authors = 'Brian Underwood'
|
@@ -18,6 +18,6 @@ A ruby gem using neo4apis to make importing SQL data to neo4j easy
|
|
18
18
|
s.require_path = 'lib'
|
19
19
|
s.files = Dir.glob('{bin,lib,config}/**/*') + %w(README.md Gemfile neo4apis-activerecord.gemspec)
|
20
20
|
|
21
|
-
s.add_dependency('neo4apis', '~> 0.
|
21
|
+
s.add_dependency('neo4apis', '~> 0.6.0')
|
22
22
|
s.add_dependency('activerecord', '~> 4.0')
|
23
23
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neo4apis-activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Underwood
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: neo4apis
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.6.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.6.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activerecord
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,6 +50,7 @@ files:
|
|
50
50
|
- lib/neo4apis-activerecord.rb
|
51
51
|
- lib/neo4apis/activerecord.rb
|
52
52
|
- lib/neo4apis/cli/activerecord.rb
|
53
|
+
- lib/neo4apis/model_resolver.rb
|
53
54
|
- lib/neo4apis/table_resolver.rb
|
54
55
|
- neo4apis-activerecord.gemspec
|
55
56
|
homepage: https://github.com/neo4jrb/neo4apis-activerecord/
|