neo4apis-activerecord 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/
|