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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f2ed4f89083577a03b71106a03c4dd24872f8736
4
- data.tar.gz: b90a58d0a0b9f10b7556bef961f5d87cf530c6bb
3
+ metadata.gz: ab2aa8e3fdbb40523bfb2bdf22f200c91e0dfc93
4
+ data.tar.gz: 5b408d16b2b3f86854576265a9dcd7b213ca1eeb
5
5
  SHA512:
6
- metadata.gz: b8057af9d9498fc9dfac9227041563b2709f85796bba838290deb616ef812f44ea446a459b22bb093f65ffddfa6d93a2c503a53b3c23d9b1236c43bb10dfa4a8
7
- data.tar.gz: fb3f26d22fe4da3a6e573ee78266f7bad145fe49df1c8de7d21d20d0a52b0e217f2f1da4a5a31468f8d1b9896174d342c845059482e7cb6cf5f59bde5e52b8a3
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[:import_has_many]
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/table_resolver'
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 TableResolver
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.reflect_on_all_associations.map do |association_reflection|
72
- association_reflection.name if import_association?(association_reflection.macro)
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
@@ -22,7 +22,7 @@ module Neo4Apis
22
22
  case standardize(column)
23
23
  when 'id', 'uuid', /#{standardize(class_name.singularize)}id/, /#{standardize(class_name.pluralize)}id/
24
24
  true
25
- when
25
+ when
26
26
  true
27
27
  end
28
28
  end.tap do |found_key| # rubocop:disable Style/MultilineBlockChain
@@ -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.1'
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.5.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.6.1
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-01-09 00:00:00.000000000 Z
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.5.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.5.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/