vorpal 0.1.0.rc3 → 1.1.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 +5 -5
- data/README.md +50 -33
- data/lib/vorpal/aggregate_mapper.rb +11 -0
- data/lib/vorpal/db_loader.rb +3 -4
- data/lib/vorpal/driver/postgresql.rb +181 -0
- data/lib/vorpal/dsl/config_builder.rb +37 -22
- data/lib/vorpal/dsl/configuration.rb +5 -4
- data/lib/vorpal/dsl/defaults_generator.rb +14 -4
- data/lib/vorpal/engine.rb +7 -8
- data/lib/vorpal/identity_map.rb +15 -14
- data/lib/vorpal/version.rb +1 -1
- data/vorpal.gemspec +11 -7
- metadata +57 -65
- data/.editorconfig +0 -13
- data/.gitignore +0 -16
- data/.rspec +0 -1
- data/.ruby-version +0 -1
- data/.yardopts +0 -1
- data/Gemfile +0 -4
- data/Rakefile +0 -10
- data/lib/vorpal/db_driver.rb +0 -143
- data/spec/helpers/db_helpers.rb +0 -51
- data/spec/helpers/profile_helpers.rb +0 -26
- data/spec/integration_spec_helper.rb +0 -36
- data/spec/unit_spec_helper.rb +0 -0
- data/spec/vorpal/acceptance/aggregate_mapper_spec.rb +0 -911
- data/spec/vorpal/integration/db_driver_spec.rb +0 -42
- data/spec/vorpal/performance/performance_spec.rb +0 -195
- data/spec/vorpal/unit/configs_spec.rb +0 -117
- data/spec/vorpal/unit/db_loader_spec.rb +0 -103
- data/spec/vorpal/unit/dsl/config_builder_spec.rb +0 -19
- data/spec/vorpal/unit/dsl/defaults_generator_spec.rb +0 -75
- data/spec/vorpal/unit/identity_map_spec.rb +0 -62
- data/spec/vorpal/unit/loaded_objects_spec.rb +0 -22
- data/spec/vorpal/unit/util/string_utils_spec.rb +0 -25
data/.gitignore
DELETED
data/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--colour
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.1.6
|
data/.yardopts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--no-private -m markdown lib/**/*.*
|
data/Gemfile
DELETED
data/Rakefile
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
#!/usr/bin/env rake
|
2
|
-
begin
|
3
|
-
require "bundler/gem_tasks"
|
4
|
-
rescue LoadError
|
5
|
-
puts 'You must `gem install bundler` and `bundle install` to run rake tasks associated with creating new versions of the gem.'
|
6
|
-
end
|
7
|
-
|
8
|
-
require 'rspec/core/rake_task'
|
9
|
-
RSpec::Core::RakeTask.new(:spec)
|
10
|
-
task :default => :spec
|
data/lib/vorpal/db_driver.rb
DELETED
@@ -1,143 +0,0 @@
|
|
1
|
-
require 'vorpal/util/string_utils.rb'
|
2
|
-
|
3
|
-
module Vorpal
|
4
|
-
# Interface between the database and Vorpal
|
5
|
-
#
|
6
|
-
# Currently only works for PostgreSQL via ActiveRecord.
|
7
|
-
class DbDriver
|
8
|
-
def initialize
|
9
|
-
@sequence_names = {}
|
10
|
-
end
|
11
|
-
|
12
|
-
def insert(class_config, db_objects)
|
13
|
-
if defined? ActiveRecord::Import
|
14
|
-
class_config.db_class.import(db_objects, validate: false)
|
15
|
-
else
|
16
|
-
db_objects.each do |db_object|
|
17
|
-
db_object.save!(validate: false)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def update(class_config, db_objects)
|
23
|
-
db_objects.each do |db_object|
|
24
|
-
db_object.save!(validate: false)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def destroy(class_config, ids)
|
29
|
-
class_config.db_class.delete_all(id: ids)
|
30
|
-
end
|
31
|
-
|
32
|
-
# Loads instances of the given class by primary key.
|
33
|
-
#
|
34
|
-
# @param class_config [ClassConfig]
|
35
|
-
# @return [[Object]] An array of entities.
|
36
|
-
def load_by_id(class_config, ids)
|
37
|
-
class_config.db_class.where(id: ids).to_a
|
38
|
-
end
|
39
|
-
|
40
|
-
# Loads instances of the given class whose foreign key has the given value.
|
41
|
-
#
|
42
|
-
# @param class_config [ClassConfig]
|
43
|
-
# @param foreign_key_info [ForeignKeyInfo]
|
44
|
-
# @return [[Object]] An array of entities.
|
45
|
-
def load_by_foreign_key(class_config, id, foreign_key_info)
|
46
|
-
arel = class_config.db_class.where(foreign_key_info.fk_column => id)
|
47
|
-
arel = arel.where(foreign_key_info.fk_type_column => foreign_key_info.fk_type) if foreign_key_info.polymorphic?
|
48
|
-
arel.order(:id).to_a
|
49
|
-
end
|
50
|
-
|
51
|
-
# Fetches primary key values to be used for new entities.
|
52
|
-
#
|
53
|
-
# @param class_config [ClassConfig] Config of the entity whose primary keys are being fetched.
|
54
|
-
# @return [[Integer]] An array of unused primary keys.
|
55
|
-
def get_primary_keys(class_config, count)
|
56
|
-
result = execute("select nextval($1) from generate_series(1,$2);", [sequence_name(class_config), count])
|
57
|
-
result.rows.map(&:first).map(&:to_i)
|
58
|
-
end
|
59
|
-
|
60
|
-
# Builds an ORM Class for accessing data in the given DB table.
|
61
|
-
#
|
62
|
-
# @param model_class [Class] The PORO class that we are creating a DB interface class for.
|
63
|
-
# @param table_name [String] Name of the DB table the DB class should interface with.
|
64
|
-
# @return [Class] ActiveRecord::Base Class
|
65
|
-
def build_db_class(model_class, table_name)
|
66
|
-
db_class = Class.new(ActiveRecord::Base) do
|
67
|
-
class << self
|
68
|
-
# This is overridden for two reasons:
|
69
|
-
# 1) For anonymous classes, #name normally returns nil. Class names in Ruby come from the
|
70
|
-
# name of the constant they are assigned to.
|
71
|
-
# 2) Because the default implementation for Class#name for anonymous classes is very, very
|
72
|
-
# slow. https://bugs.ruby-lang.org/issues/11119
|
73
|
-
# Remove this override once #2 has been fixed!
|
74
|
-
def name
|
75
|
-
@name ||= "Vorpal_generated_ActiveRecord__Base_class_for_#{vorpal_model_class_name}"
|
76
|
-
end
|
77
|
-
|
78
|
-
# Overridden because, like #name, the default implementation for anonymous classes is very,
|
79
|
-
# very slow.
|
80
|
-
def to_s
|
81
|
-
name
|
82
|
-
end
|
83
|
-
|
84
|
-
attr_accessor :vorpal_model_class_name
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
db_class.vorpal_model_class_name = Util::StringUtils.escape_class_name(model_class.name)
|
89
|
-
db_class.table_name = table_name
|
90
|
-
db_class
|
91
|
-
end
|
92
|
-
|
93
|
-
# Builds a composable query object (e.g. ActiveRecord::Relation) with Vorpal methods mixed in.
|
94
|
-
#
|
95
|
-
# @param class_config [ClassConfig] Config of the entity whose db representations should be returned.
|
96
|
-
def query(class_config, aggregate_mapper)
|
97
|
-
class_config.db_class.unscoped.extending(ArelQueryMethods.new(aggregate_mapper))
|
98
|
-
end
|
99
|
-
|
100
|
-
private
|
101
|
-
|
102
|
-
def sequence_name(class_config)
|
103
|
-
@sequence_names[class_config] ||= execute(
|
104
|
-
"SELECT substring(column_default from '''(.*)''') FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1 AND column_name = 'id' LIMIT 1",
|
105
|
-
[class_config.db_class.table_name]
|
106
|
-
).rows.first.first
|
107
|
-
end
|
108
|
-
|
109
|
-
def execute(sql, binds)
|
110
|
-
binds = binds.map { |row| [nil, row] }
|
111
|
-
ActiveRecord::Base.connection.exec_query(sql, 'SQL', binds)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
class ArelQueryMethods < Module
|
116
|
-
def initialize(mapper)
|
117
|
-
@mapper = mapper
|
118
|
-
end
|
119
|
-
|
120
|
-
def extended(descendant)
|
121
|
-
super
|
122
|
-
descendant.extend(Methods)
|
123
|
-
descendant.vorpal_aggregate_mapper = @mapper
|
124
|
-
end
|
125
|
-
|
126
|
-
# Methods in this module will appear on any composable
|
127
|
-
module Methods
|
128
|
-
attr_writer :vorpal_aggregate_mapper
|
129
|
-
|
130
|
-
# See {AggregateMapper#load_many}.
|
131
|
-
def load_many
|
132
|
-
db_roots = self.to_a
|
133
|
-
@vorpal_aggregate_mapper.load_many(db_roots)
|
134
|
-
end
|
135
|
-
|
136
|
-
# See {AggregateMapper#load_one}.
|
137
|
-
def load_one
|
138
|
-
db_root = self.first
|
139
|
-
@vorpal_aggregate_mapper.load_one(db_root)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
data/spec/helpers/db_helpers.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
module DbHelpers
|
2
|
-
module_function
|
3
|
-
|
4
|
-
CONNECTION_SETTINGS = {
|
5
|
-
adapter: 'postgresql',
|
6
|
-
host: 'localhost',
|
7
|
-
database: 'vorpal_test',
|
8
|
-
min_messages: 'error',
|
9
|
-
# Change the following to reflect your database settings
|
10
|
-
# username: 'vorpal',
|
11
|
-
# password: 'pass',
|
12
|
-
}
|
13
|
-
|
14
|
-
def ensure_database_exists
|
15
|
-
test_database_name = CONNECTION_SETTINGS.fetch(:database)
|
16
|
-
if !db_exists?(test_database_name)
|
17
|
-
db_connection.create_database(test_database_name)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def db_exists?(db_name)
|
22
|
-
ActiveRecord::Base.establish_connection(CONNECTION_SETTINGS.merge(database: 'template1'))
|
23
|
-
|
24
|
-
return db_connection.exec_query("SELECT 1 from pg_database WHERE datname='#{db_name}';").present?
|
25
|
-
end
|
26
|
-
|
27
|
-
def db_connection
|
28
|
-
ActiveRecord::Base.connection
|
29
|
-
end
|
30
|
-
|
31
|
-
def establish_connection
|
32
|
-
ActiveRecord::Base.establish_connection(CONNECTION_SETTINGS)
|
33
|
-
end
|
34
|
-
|
35
|
-
# when you change a table's columns, set force to true to re-generate the table in the DB
|
36
|
-
def define_table(table_name, columns, force)
|
37
|
-
if !db_connection.table_exists?(table_name) || force
|
38
|
-
db_connection.create_table(table_name, force: true) do |t|
|
39
|
-
columns.each do |name, type|
|
40
|
-
t.send(type, name)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def defineAr(table_name)
|
47
|
-
Class.new(ActiveRecord::Base) do
|
48
|
-
self.table_name = table_name
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'ruby-prof'
|
2
|
-
|
3
|
-
# In order to use these helpers do the following:
|
4
|
-
# 1) Add `spec.add_development_dependency "ruby-prof"` to the vorpal.gemspec file.
|
5
|
-
# 2) Do a `bundle update`
|
6
|
-
# 3) Add `require 'helpers/profile_helpers'` to the spec where you wish to profile.
|
7
|
-
module ProfileHelpers
|
8
|
-
module_function
|
9
|
-
|
10
|
-
# Runs a block a given number of times and outputs the profiling results in a 'Call Tree'
|
11
|
-
# format suitable for display by a tool like KCacheGrind.
|
12
|
-
#
|
13
|
-
# - Installing QCacheGrind on OSX: http://nickology.com/2014/04/16/view-xdebug-cachegrind-files-on-mac-os/
|
14
|
-
def output_callgrind(description, times=1, &block)
|
15
|
-
RubyProf.measure_mode = RubyProf::PROCESS_TIME
|
16
|
-
RubyProf.start
|
17
|
-
|
18
|
-
times.times(&block)
|
19
|
-
|
20
|
-
result = RubyProf.stop
|
21
|
-
printer = RubyProf::CallTreePrinter.new(result)
|
22
|
-
File.open("#{description}_#{DateTime.now.strftime("%FT%H:%M:%S%z")}.callgrind", "w") do |file|
|
23
|
-
printer.print(file)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'active_record'
|
2
|
-
require 'pg'
|
3
|
-
require 'helpers/db_helpers'
|
4
|
-
|
5
|
-
DbHelpers.ensure_database_exists
|
6
|
-
DbHelpers.establish_connection
|
7
|
-
|
8
|
-
RSpec.configure do |config|
|
9
|
-
config.include DbHelpers
|
10
|
-
|
11
|
-
# implements `use_transactional_fixtures = true`
|
12
|
-
config.before(:each) do
|
13
|
-
connection = ActiveRecord::Base.connection
|
14
|
-
if ActiveRecord::VERSION::MAJOR == 3
|
15
|
-
# from lib/active_record/fixtures.rb
|
16
|
-
connection.increment_open_transactions
|
17
|
-
connection.transaction_joinable = false
|
18
|
-
connection.begin_db_transaction
|
19
|
-
else
|
20
|
-
connection.begin_transaction(joinable: false)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
config.after(:each) do
|
25
|
-
connection = ActiveRecord::Base.connection
|
26
|
-
if ActiveRecord::VERSION::MAJOR == 3
|
27
|
-
if connection.open_transactions != 0
|
28
|
-
connection.rollback_db_transaction
|
29
|
-
connection.decrement_open_transactions
|
30
|
-
end
|
31
|
-
else
|
32
|
-
connection.rollback_transaction if connection.transaction_open?
|
33
|
-
end
|
34
|
-
ActiveRecord::Base.clear_active_connections!
|
35
|
-
end
|
36
|
-
end
|
data/spec/unit_spec_helper.rb
DELETED
File without changes
|
@@ -1,911 +0,0 @@
|
|
1
|
-
require 'integration_spec_helper'
|
2
|
-
require 'vorpal'
|
3
|
-
require 'virtus'
|
4
|
-
require 'activerecord-import/base'
|
5
|
-
|
6
|
-
describe 'AggregateMapper' do
|
7
|
-
|
8
|
-
# for testing polymorphic associations
|
9
|
-
class Bug
|
10
|
-
include Virtus.model
|
11
|
-
|
12
|
-
attribute :id, Integer
|
13
|
-
attribute :name, String
|
14
|
-
attribute :lives_on, Object
|
15
|
-
end
|
16
|
-
|
17
|
-
class Tree; end
|
18
|
-
|
19
|
-
class Trunk
|
20
|
-
include Virtus.model
|
21
|
-
|
22
|
-
attribute :id, Integer
|
23
|
-
attribute :length, Decimal
|
24
|
-
attribute :bugs, Array[Bug]
|
25
|
-
attribute :tree, Tree
|
26
|
-
end
|
27
|
-
|
28
|
-
class Branch
|
29
|
-
include Virtus.model
|
30
|
-
|
31
|
-
attribute :id, Integer
|
32
|
-
attribute :length, Decimal
|
33
|
-
attribute :tree, Tree
|
34
|
-
attribute :branches, Array[Branch]
|
35
|
-
attribute :bugs, Array[Bug]
|
36
|
-
end
|
37
|
-
|
38
|
-
class Fissure < ActiveRecord::Base; end
|
39
|
-
class Swamp < ActiveRecord::Base; end
|
40
|
-
|
41
|
-
class Tree
|
42
|
-
include Virtus.model
|
43
|
-
|
44
|
-
attribute :id, Integer
|
45
|
-
attribute :name, String
|
46
|
-
attribute :trunk, Trunk
|
47
|
-
attribute :environment, Object
|
48
|
-
attribute :fissures, Array[Fissure]
|
49
|
-
attribute :branches, Array[Branch]
|
50
|
-
end
|
51
|
-
|
52
|
-
before(:all) do
|
53
|
-
define_table('branches', {length: :decimal, tree_id: :integer, branch_id: :integer}, false)
|
54
|
-
define_table('bugs', {name: :text, lives_on_id: :integer, lives_on_type: :string}, false)
|
55
|
-
define_table('fissures', {length: :decimal, tree_id: :integer}, false)
|
56
|
-
define_table('trees', {name: :text, trunk_id: :integer, environment_id: :integer, environment_type: :string}, false)
|
57
|
-
define_table('trunks', {length: :decimal}, false)
|
58
|
-
define_table('swamps', {}, false)
|
59
|
-
end
|
60
|
-
|
61
|
-
describe 'new records' do
|
62
|
-
it 'saves attributes' do
|
63
|
-
test_mapper = configure
|
64
|
-
|
65
|
-
tree = Tree.new(name: 'backyard tree')
|
66
|
-
test_mapper.persist(tree)
|
67
|
-
|
68
|
-
tree_db = db_class_for(Tree, test_mapper).first
|
69
|
-
expect(tree_db.name).to eq 'backyard tree'
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'sets the id when first saved' do
|
73
|
-
test_mapper = configure
|
74
|
-
|
75
|
-
tree = Tree.new()
|
76
|
-
test_mapper.persist(tree)
|
77
|
-
|
78
|
-
expect(tree.id).to_not be nil
|
79
|
-
|
80
|
-
tree_db = db_class_for(Tree, test_mapper).first
|
81
|
-
expect(tree_db.id).to eq tree.id
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'saves AR::Base objects' do
|
85
|
-
test_mapper = configure
|
86
|
-
|
87
|
-
fissure = Fissure.new(length: 21)
|
88
|
-
tree = Tree.new(fissures: [fissure])
|
89
|
-
|
90
|
-
test_mapper.persist(tree)
|
91
|
-
|
92
|
-
expect(Fissure.first.length).to eq 21
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
describe 'on error' do
|
97
|
-
it 'nils ids of new objects' do
|
98
|
-
db_driver = Vorpal::DbDriver.new
|
99
|
-
test_mapper = configure(db_driver: db_driver)
|
100
|
-
|
101
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
102
|
-
|
103
|
-
expect(db_driver).to receive(:update).and_raise('not so good')
|
104
|
-
|
105
|
-
fissure = Fissure.new
|
106
|
-
tree = Tree.new(id: tree_db.id, fissures: [fissure])
|
107
|
-
|
108
|
-
expect {
|
109
|
-
test_mapper.persist(tree)
|
110
|
-
}.to raise_error(Exception)
|
111
|
-
|
112
|
-
expect(fissure.id).to eq nil
|
113
|
-
expect(tree.id).to_not eq nil
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
describe 'existing records' do
|
118
|
-
it 'updates attributes' do
|
119
|
-
test_mapper = configure
|
120
|
-
|
121
|
-
tree = Tree.new(name: 'little tree')
|
122
|
-
test_mapper.persist(tree)
|
123
|
-
|
124
|
-
tree.name = 'big tree'
|
125
|
-
test_mapper.persist(tree)
|
126
|
-
|
127
|
-
tree_db = db_class_for(Tree, test_mapper).first
|
128
|
-
expect(tree_db.name).to eq 'big tree'
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'does not change the id on update' do
|
132
|
-
test_mapper = configure
|
133
|
-
|
134
|
-
tree = Tree.new
|
135
|
-
test_mapper.persist(tree)
|
136
|
-
|
137
|
-
original_id = tree.id
|
138
|
-
|
139
|
-
tree.name = 'change it'
|
140
|
-
test_mapper.persist(tree)
|
141
|
-
|
142
|
-
expect(tree.id).to eq original_id
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'does not create additional records' do
|
146
|
-
test_mapper = configure
|
147
|
-
|
148
|
-
tree = Tree.new
|
149
|
-
test_mapper.persist(tree)
|
150
|
-
|
151
|
-
tree.name = 'change it'
|
152
|
-
test_mapper.persist(tree)
|
153
|
-
|
154
|
-
expect(db_class_for(Tree, test_mapper).count).to eq 1
|
155
|
-
end
|
156
|
-
|
157
|
-
it 'removes orphans' do
|
158
|
-
test_mapper = configure
|
159
|
-
|
160
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
161
|
-
db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
|
162
|
-
|
163
|
-
tree = Tree.new(id: tree_db.id, branches: [])
|
164
|
-
|
165
|
-
test_mapper.persist(tree)
|
166
|
-
|
167
|
-
expect(db_class_for(Branch, test_mapper).count).to eq 0
|
168
|
-
end
|
169
|
-
|
170
|
-
it 'does not remove orphans from unowned associations' do
|
171
|
-
test_mapper = configure_unowned
|
172
|
-
|
173
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
174
|
-
db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
|
175
|
-
|
176
|
-
tree = Tree.new(id: tree_db.id, branches: [])
|
177
|
-
|
178
|
-
test_mapper.persist(tree)
|
179
|
-
|
180
|
-
expect(db_class_for(Branch, test_mapper).count).to eq 1
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
it 'copies attributes to domain' do
|
185
|
-
test_mapper = configure
|
186
|
-
|
187
|
-
tree_db = db_class_for(Tree, test_mapper).create! name: 'tree name'
|
188
|
-
tree = test_mapper.load_one(tree_db)
|
189
|
-
|
190
|
-
expect(tree.id).to eq tree_db.id
|
191
|
-
expect(tree.name).to eq 'tree name'
|
192
|
-
end
|
193
|
-
|
194
|
-
it 'hydrates ActiveRecord::Base associations' do
|
195
|
-
test_mapper = configure
|
196
|
-
|
197
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
198
|
-
Fissure.create! length: 21, tree_id: tree_db.id
|
199
|
-
|
200
|
-
tree = test_mapper.load_one(tree_db)
|
201
|
-
|
202
|
-
expect(tree.fissures.first.length).to eq 21
|
203
|
-
end
|
204
|
-
|
205
|
-
describe 'cycles' do
|
206
|
-
it 'persists' do
|
207
|
-
test_mapper = configure_with_cycle
|
208
|
-
|
209
|
-
tree = Tree.new
|
210
|
-
long_branch = Branch.new(length: 100, tree: tree)
|
211
|
-
tree.branches << long_branch
|
212
|
-
|
213
|
-
test_mapper.persist(tree)
|
214
|
-
|
215
|
-
expect(db_class_for(Tree, test_mapper).count).to eq 1
|
216
|
-
end
|
217
|
-
|
218
|
-
it 'hydrates' do
|
219
|
-
test_mapper = configure_with_cycle
|
220
|
-
|
221
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
222
|
-
db_class_for(Branch, test_mapper).create!(length: 50, tree_id: tree_db.id)
|
223
|
-
|
224
|
-
tree = test_mapper.load_one(tree_db)
|
225
|
-
|
226
|
-
expect(tree).to be tree.branches.first.tree
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
describe 'recursive associations' do
|
231
|
-
it 'persists' do
|
232
|
-
test_mapper = configure_recursive
|
233
|
-
|
234
|
-
tree = Tree.new
|
235
|
-
long_branch = Branch.new(length: 100, tree: tree)
|
236
|
-
tree.branches << long_branch
|
237
|
-
short_branch = Branch.new(length: 50, tree: tree)
|
238
|
-
long_branch.branches << short_branch
|
239
|
-
|
240
|
-
test_mapper.persist(tree)
|
241
|
-
|
242
|
-
expect(db_class_for(Branch, test_mapper).count).to eq 2
|
243
|
-
end
|
244
|
-
|
245
|
-
it 'hydrates' do
|
246
|
-
test_mapper = configure_recursive
|
247
|
-
|
248
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
249
|
-
long_branch = db_class_for(Branch, test_mapper).create!(length: 100, tree_id: tree_db.id)
|
250
|
-
db_class_for(Branch, test_mapper).create!(length: 50, branch_id: long_branch.id)
|
251
|
-
|
252
|
-
tree = test_mapper.load_one(tree_db)
|
253
|
-
|
254
|
-
expect(tree.branches.first.branches.first.length).to eq 50
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
describe 'belongs_to associations' do
|
259
|
-
it 'saves attributes' do
|
260
|
-
test_mapper = configure
|
261
|
-
trunk = Trunk.new(length: 12)
|
262
|
-
tree = Tree.new(trunk: trunk)
|
263
|
-
|
264
|
-
test_mapper.persist(tree)
|
265
|
-
|
266
|
-
trunk_db = db_class_for(Trunk, test_mapper).first
|
267
|
-
expect(trunk_db.length).to eq 12
|
268
|
-
end
|
269
|
-
|
270
|
-
it 'saves foreign keys' do
|
271
|
-
test_mapper = configure
|
272
|
-
trunk = Trunk.new
|
273
|
-
tree = Tree.new(trunk: trunk)
|
274
|
-
|
275
|
-
test_mapper.persist(tree)
|
276
|
-
|
277
|
-
tree_db = db_class_for(Tree, test_mapper).first
|
278
|
-
expect(tree_db.trunk_id).to eq trunk.id
|
279
|
-
end
|
280
|
-
|
281
|
-
it 'updating does not create additional rows' do
|
282
|
-
test_mapper = configure
|
283
|
-
trunk = Trunk.new
|
284
|
-
tree = Tree.new(trunk: trunk)
|
285
|
-
|
286
|
-
test_mapper.persist(tree)
|
287
|
-
|
288
|
-
trunk.length = 21
|
289
|
-
|
290
|
-
expect{ test_mapper.persist(tree) }.to_not change{ db_class_for(Trunk, test_mapper).count }
|
291
|
-
end
|
292
|
-
|
293
|
-
it 'only saves entities that are owned' do
|
294
|
-
test_mapper = configure_unowned
|
295
|
-
|
296
|
-
trunk = Trunk.new
|
297
|
-
tree = Tree.new(trunk: trunk)
|
298
|
-
|
299
|
-
test_mapper.persist(tree)
|
300
|
-
|
301
|
-
expect(db_class_for(Trunk, test_mapper).count).to eq 0
|
302
|
-
end
|
303
|
-
|
304
|
-
it 'hydrates' do
|
305
|
-
test_mapper = configure
|
306
|
-
trunk_db = db_class_for(Trunk, test_mapper).create!(length: 21)
|
307
|
-
tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
|
308
|
-
|
309
|
-
new_tree = test_mapper.load_one(tree_db)
|
310
|
-
expect(new_tree.trunk.length).to eq 21
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
describe 'has_many associations' do
|
315
|
-
it 'saves' do
|
316
|
-
test_mapper = configure
|
317
|
-
tree = Tree.new
|
318
|
-
tree.branches << Branch.new(length: 100)
|
319
|
-
tree.branches << Branch.new(length: 3)
|
320
|
-
|
321
|
-
test_mapper.persist(tree)
|
322
|
-
|
323
|
-
branches = db_class_for(Branch, test_mapper).all
|
324
|
-
expect(branches.size).to eq 2
|
325
|
-
expect(branches.first.length).to eq 100
|
326
|
-
expect(branches.second.length).to eq 3
|
327
|
-
end
|
328
|
-
|
329
|
-
it 'saves foreign keys' do
|
330
|
-
test_mapper = configure
|
331
|
-
tree = Tree.new
|
332
|
-
tree.branches << Branch.new(length: 100)
|
333
|
-
|
334
|
-
test_mapper.persist(tree)
|
335
|
-
|
336
|
-
branches = db_class_for(Branch, test_mapper).all
|
337
|
-
expect(branches.first.tree_id).to eq tree.id
|
338
|
-
end
|
339
|
-
|
340
|
-
it 'updates' do
|
341
|
-
test_mapper = configure
|
342
|
-
tree = Tree.new
|
343
|
-
long_branch = Branch.new(length: 100)
|
344
|
-
tree.branches << long_branch
|
345
|
-
|
346
|
-
test_mapper.persist(tree)
|
347
|
-
|
348
|
-
long_branch.length = 120
|
349
|
-
|
350
|
-
test_mapper.persist(tree)
|
351
|
-
|
352
|
-
branches = db_class_for(Branch, test_mapper).all
|
353
|
-
expect(branches.first.length).to eq 120
|
354
|
-
end
|
355
|
-
|
356
|
-
it 'only saves entities that are owned' do
|
357
|
-
test_mapper = configure_unowned
|
358
|
-
|
359
|
-
tree = Tree.new
|
360
|
-
long_branch = Branch.new(length: 100)
|
361
|
-
tree.branches << long_branch
|
362
|
-
|
363
|
-
test_mapper.persist(tree)
|
364
|
-
|
365
|
-
expect(db_class_for(Branch, test_mapper).count).to eq 0
|
366
|
-
end
|
367
|
-
|
368
|
-
it 'hydrates' do
|
369
|
-
test_mapper = configure
|
370
|
-
|
371
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
372
|
-
db_class_for(Branch, test_mapper).create!(length: 50, tree_id: tree_db.id)
|
373
|
-
|
374
|
-
tree = test_mapper.load_one(tree_db)
|
375
|
-
|
376
|
-
expect(tree.branches.first.length).to eq 50
|
377
|
-
end
|
378
|
-
end
|
379
|
-
|
380
|
-
describe 'has_one associations' do
|
381
|
-
it 'saves' do
|
382
|
-
test_mapper = configure_has_one
|
383
|
-
tree = Tree.new(name: 'big tree')
|
384
|
-
trunk = Trunk.new(tree: tree)
|
385
|
-
|
386
|
-
test_mapper.persist(trunk)
|
387
|
-
|
388
|
-
expect(db_class_for(Tree, test_mapper).first.name).to eq 'big tree'
|
389
|
-
end
|
390
|
-
|
391
|
-
it 'saves foreign keys' do
|
392
|
-
test_mapper = configure_has_one
|
393
|
-
tree = Tree.new(name: 'big tree')
|
394
|
-
trunk = Trunk.new(tree: tree)
|
395
|
-
|
396
|
-
test_mapper.persist(trunk)
|
397
|
-
|
398
|
-
expect(db_class_for(Tree, test_mapper).first.trunk_id).to eq trunk.id
|
399
|
-
end
|
400
|
-
|
401
|
-
it 'only saves entities that are owned' do
|
402
|
-
test_mapper = configure_unowned_has_one
|
403
|
-
tree = Tree.new
|
404
|
-
trunk = Trunk.new(tree: tree)
|
405
|
-
|
406
|
-
test_mapper.persist(trunk)
|
407
|
-
|
408
|
-
expect(db_class_for(Tree, test_mapper).count).to eq 0
|
409
|
-
end
|
410
|
-
|
411
|
-
it 'hydrates' do
|
412
|
-
test_mapper = configure_has_one
|
413
|
-
|
414
|
-
trunk_db = db_class_for(Trunk, test_mapper).create!
|
415
|
-
db_class_for(Tree, test_mapper).create!(name: 'big tree', trunk_id: trunk_db.id)
|
416
|
-
|
417
|
-
trunk = test_mapper.load_one(trunk_db)
|
418
|
-
|
419
|
-
expect(trunk.tree.name).to eq 'big tree'
|
420
|
-
end
|
421
|
-
end
|
422
|
-
|
423
|
-
describe 'polymorphic associations' do
|
424
|
-
it 'saves with has_manys' do
|
425
|
-
test_mapper = configure_polymorphic_has_many
|
426
|
-
trunk = Trunk.new
|
427
|
-
branch = Branch.new
|
428
|
-
tree = Tree.new(trunk: trunk, branches: [branch])
|
429
|
-
|
430
|
-
trunk_bug = Bug.new
|
431
|
-
trunk.bugs << trunk_bug
|
432
|
-
branch_bug = Bug.new
|
433
|
-
branch.bugs << branch_bug
|
434
|
-
|
435
|
-
test_mapper.persist(tree)
|
436
|
-
|
437
|
-
expect(db_class_for(Bug, test_mapper).find(trunk_bug.id).lives_on_type).to eq Trunk.name
|
438
|
-
expect(db_class_for(Bug, test_mapper).find(branch_bug.id).lives_on_type).to eq Branch.name
|
439
|
-
end
|
440
|
-
|
441
|
-
it 'restores with has_manys' do
|
442
|
-
test_mapper = configure_polymorphic_has_many
|
443
|
-
|
444
|
-
trunk_db = db_class_for(Trunk, test_mapper).create!
|
445
|
-
tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
|
446
|
-
db_class_for(Bug, test_mapper).create!(name: 'trunk bug', lives_on_id: trunk_db.id, lives_on_type: Trunk.name)
|
447
|
-
db_class_for(Bug, test_mapper).create!(name: 'not a trunk bug!', lives_on_id: trunk_db.id, lives_on_type: 'some other table')
|
448
|
-
|
449
|
-
tree = test_mapper.load_one(tree_db)
|
450
|
-
|
451
|
-
expect(tree.trunk.bugs.map(&:name)).to eq ['trunk bug']
|
452
|
-
end
|
453
|
-
|
454
|
-
it 'saves with belongs_tos' do
|
455
|
-
test_mapper = configure_polymorphic_belongs_to
|
456
|
-
|
457
|
-
trunk_bug = Bug.new(lives_on: Trunk.new)
|
458
|
-
branch_bug = Bug.new(lives_on: Branch.new)
|
459
|
-
|
460
|
-
test_mapper.persist([trunk_bug, branch_bug])
|
461
|
-
|
462
|
-
expect(db_class_for(Bug, test_mapper).find(trunk_bug.id).lives_on_type).to eq Trunk.name
|
463
|
-
expect(db_class_for(Bug, test_mapper).find(branch_bug.id).lives_on_type).to eq Branch.name
|
464
|
-
end
|
465
|
-
|
466
|
-
it 'saves associations to unowned entities via belongs_to' do
|
467
|
-
test_mapper = configure_unowned_polymorphic_belongs_to
|
468
|
-
trunk = Trunk.new
|
469
|
-
|
470
|
-
trunk_bug = Bug.new(lives_on: trunk)
|
471
|
-
|
472
|
-
test_mapper.persist(trunk_bug)
|
473
|
-
|
474
|
-
expect(db_class_for(Bug, test_mapper).find(trunk_bug.id).lives_on_type).to eq Trunk.name
|
475
|
-
end
|
476
|
-
|
477
|
-
it 'restores with belongs_tos' do
|
478
|
-
test_mapper = configure_polymorphic_belongs_to
|
479
|
-
|
480
|
-
# makes sure that we are using the fk_type to discriminate against
|
481
|
-
# two entities with the same primary key value
|
482
|
-
trunk_db = db_class_for(Trunk, test_mapper).new(length: 99)
|
483
|
-
trunk_db.id = 99
|
484
|
-
trunk_db.save!
|
485
|
-
trunk_bug_db = db_class_for(Bug, test_mapper).create!(lives_on_id: trunk_db.id, lives_on_type: Trunk.name)
|
486
|
-
branch_db = db_class_for(Branch, test_mapper).new(length: 5)
|
487
|
-
branch_db.id = 99
|
488
|
-
branch_db.save!
|
489
|
-
branch_bug_db = db_class_for(Bug, test_mapper).create!(lives_on_id: branch_db.id, lives_on_type: Branch.name)
|
490
|
-
|
491
|
-
trunk_bug, branch_bug = test_mapper.load_many([trunk_bug_db, branch_bug_db])
|
492
|
-
|
493
|
-
expect(trunk_bug.lives_on.length).to eq 99
|
494
|
-
expect(branch_bug.lives_on.length).to eq 5
|
495
|
-
end
|
496
|
-
|
497
|
-
it 'restores active record objects' do
|
498
|
-
test_mapper = configure_ar_polymorphic_belongs_to
|
499
|
-
|
500
|
-
swamp = Swamp.create!
|
501
|
-
tree_db = db_class_for(Tree, test_mapper).create!(environment_id: swamp.id, environment_type: Swamp.name)
|
502
|
-
|
503
|
-
tree = test_mapper.load_one(tree_db)
|
504
|
-
|
505
|
-
expect(tree.environment).to eq swamp
|
506
|
-
end
|
507
|
-
end
|
508
|
-
|
509
|
-
describe 'arel' do
|
510
|
-
it 'loads many' do
|
511
|
-
test_mapper = configure
|
512
|
-
|
513
|
-
db_class_for(Tree, test_mapper).create!
|
514
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
515
|
-
|
516
|
-
trees = test_mapper.query.where(id: tree_db.id).load_many
|
517
|
-
|
518
|
-
expect(trees.map(&:id)).to eq [tree_db.id]
|
519
|
-
end
|
520
|
-
|
521
|
-
it 'loads one' do
|
522
|
-
test_mapper = configure
|
523
|
-
|
524
|
-
db_class_for(Tree, test_mapper).create!
|
525
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
526
|
-
|
527
|
-
trees = test_mapper.query.where(id: tree_db.id).load_one
|
528
|
-
|
529
|
-
expect(trees.id).to eq tree_db.id
|
530
|
-
end
|
531
|
-
end
|
532
|
-
|
533
|
-
describe 'load_many' do
|
534
|
-
it 'maps given db objects' do
|
535
|
-
test_mapper = configure
|
536
|
-
|
537
|
-
db_class_for(Tree, test_mapper).create!
|
538
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
539
|
-
|
540
|
-
trees = test_mapper.load_many([tree_db])
|
541
|
-
|
542
|
-
expect(trees.map(&:id)).to eq [tree_db.id]
|
543
|
-
end
|
544
|
-
|
545
|
-
it 'only returns roots' do
|
546
|
-
test_mapper = configure
|
547
|
-
|
548
|
-
db_class_for(Tree, test_mapper).create!
|
549
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
550
|
-
db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
|
551
|
-
|
552
|
-
trees = test_mapper.load_many([tree_db])
|
553
|
-
|
554
|
-
expect(trees.map(&:id)).to eq [tree_db.id]
|
555
|
-
end
|
556
|
-
end
|
557
|
-
|
558
|
-
describe 'destroy' do
|
559
|
-
it 'removes the entity from the database' do
|
560
|
-
test_mapper = configure
|
561
|
-
|
562
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
563
|
-
|
564
|
-
test_mapper.destroy([Tree.new(id: tree_db.id)])
|
565
|
-
|
566
|
-
expect(db_class_for(Tree, test_mapper).count).to eq 0
|
567
|
-
end
|
568
|
-
|
569
|
-
it 'removes has many children from the database' do
|
570
|
-
test_mapper = configure
|
571
|
-
|
572
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
573
|
-
db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
|
574
|
-
|
575
|
-
test_mapper.destroy(Tree.new(id: tree_db.id))
|
576
|
-
|
577
|
-
expect(db_class_for(Branch, test_mapper).count).to eq 0
|
578
|
-
end
|
579
|
-
|
580
|
-
it 'removes belongs to children from the database' do
|
581
|
-
test_mapper = configure
|
582
|
-
|
583
|
-
trunk_db = db_class_for(Trunk, test_mapper).create!
|
584
|
-
tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
|
585
|
-
|
586
|
-
test_mapper.destroy(Tree.new(id: tree_db.id))
|
587
|
-
|
588
|
-
expect(db_class_for(Trunk, test_mapper).count).to eq 0
|
589
|
-
end
|
590
|
-
|
591
|
-
it 'removes AR children from the database' do
|
592
|
-
test_mapper = configure
|
593
|
-
|
594
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
595
|
-
Fissure.create!(tree_id: tree_db.id)
|
596
|
-
|
597
|
-
test_mapper.destroy(Tree.new(id: tree_db.id))
|
598
|
-
|
599
|
-
expect(Fissure.count).to eq 0
|
600
|
-
end
|
601
|
-
|
602
|
-
it 'leaves unowned belongs to children in the database' do
|
603
|
-
test_mapper = configure_unowned
|
604
|
-
|
605
|
-
trunk_db = db_class_for(Trunk, test_mapper).create!
|
606
|
-
tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
|
607
|
-
|
608
|
-
test_mapper.destroy(Tree.new(id: tree_db.id))
|
609
|
-
|
610
|
-
expect(db_class_for(Trunk, test_mapper).count).to eq 1
|
611
|
-
end
|
612
|
-
|
613
|
-
it 'leaves unowned has many children in the database' do
|
614
|
-
test_mapper = configure_unowned
|
615
|
-
|
616
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
617
|
-
db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
|
618
|
-
|
619
|
-
test_mapper.destroy(Tree.new(id: tree_db.id))
|
620
|
-
|
621
|
-
expect(db_class_for(Branch, test_mapper).count).to eq 1
|
622
|
-
end
|
623
|
-
end
|
624
|
-
|
625
|
-
describe 'destroy_by_id' do
|
626
|
-
it 'removes the entity from the database' do
|
627
|
-
test_mapper = configure
|
628
|
-
|
629
|
-
tree_db = db_class_for(Tree, test_mapper).create!
|
630
|
-
|
631
|
-
test_mapper.destroy_by_id([tree_db.id])
|
632
|
-
|
633
|
-
expect(db_class_for(Tree, test_mapper).count).to eq 0
|
634
|
-
end
|
635
|
-
end
|
636
|
-
|
637
|
-
describe 'non-existent values' do
|
638
|
-
it 'load_many returns an empty array when given an empty array' do
|
639
|
-
test_mapper = configure
|
640
|
-
|
641
|
-
results = test_mapper.load_many([])
|
642
|
-
expect(results).to eq []
|
643
|
-
end
|
644
|
-
|
645
|
-
it 'load_many throws an exception when given a nil db_object' do
|
646
|
-
test_mapper = configure
|
647
|
-
|
648
|
-
expect {
|
649
|
-
test_mapper.load_many([nil])
|
650
|
-
}.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
|
651
|
-
end
|
652
|
-
|
653
|
-
it 'load_one returns nil when given nil' do
|
654
|
-
test_mapper = configure
|
655
|
-
|
656
|
-
result = test_mapper.load_one(nil)
|
657
|
-
expect(result).to eq nil
|
658
|
-
end
|
659
|
-
|
660
|
-
it 'persist ignores empty arrays' do
|
661
|
-
test_mapper = configure
|
662
|
-
|
663
|
-
results = test_mapper.persist([])
|
664
|
-
expect(results).to eq []
|
665
|
-
end
|
666
|
-
|
667
|
-
it 'persist throws an exception when given a collection with a nil root' do
|
668
|
-
test_mapper = configure
|
669
|
-
expect {
|
670
|
-
test_mapper.persist([nil])
|
671
|
-
}.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
|
672
|
-
end
|
673
|
-
|
674
|
-
it 'persist throws an exception when given a nil root' do
|
675
|
-
test_mapper = configure
|
676
|
-
expect {
|
677
|
-
test_mapper.persist(nil)
|
678
|
-
}.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
|
679
|
-
end
|
680
|
-
|
681
|
-
it 'destroy ignores empty arrays' do
|
682
|
-
test_mapper = configure
|
683
|
-
|
684
|
-
results = test_mapper.destroy([])
|
685
|
-
expect(results).to eq []
|
686
|
-
end
|
687
|
-
|
688
|
-
it 'destroy throws an exception when given a nil root' do
|
689
|
-
test_mapper = configure
|
690
|
-
|
691
|
-
expect {
|
692
|
-
test_mapper.destroy(nil)
|
693
|
-
}.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
|
694
|
-
end
|
695
|
-
|
696
|
-
it 'destroy throws an exception when given a collection with a nil root' do
|
697
|
-
test_mapper = configure
|
698
|
-
|
699
|
-
expect {
|
700
|
-
test_mapper.destroy([nil])
|
701
|
-
}.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
|
702
|
-
end
|
703
|
-
|
704
|
-
it 'destroy_by_id ignores empty arrays' do
|
705
|
-
test_mapper = configure
|
706
|
-
|
707
|
-
results = test_mapper.destroy_by_id([])
|
708
|
-
expect(results).to eq []
|
709
|
-
end
|
710
|
-
|
711
|
-
it 'destroy_by_id ignores ids that do not exist' do
|
712
|
-
test_mapper = configure
|
713
|
-
|
714
|
-
test_mapper.destroy_by_id([99])
|
715
|
-
end
|
716
|
-
|
717
|
-
it 'destroy_by_id throws an exception when given a collection with a nil id' do
|
718
|
-
test_mapper = configure
|
719
|
-
|
720
|
-
expect {
|
721
|
-
test_mapper.destroy_by_id([nil])
|
722
|
-
}.to raise_error(Vorpal::InvalidPrimaryKeyValue, "Nil primary key values are not allowed.")
|
723
|
-
end
|
724
|
-
|
725
|
-
it 'destroy_by_id throws an exception when given a nil id' do
|
726
|
-
test_mapper = configure
|
727
|
-
|
728
|
-
expect {
|
729
|
-
test_mapper.destroy_by_id(nil)
|
730
|
-
}.to raise_error(Vorpal::InvalidPrimaryKeyValue, "Nil primary key values are not allowed.")
|
731
|
-
end
|
732
|
-
end
|
733
|
-
|
734
|
-
private
|
735
|
-
|
736
|
-
def db_class_for(clazz, mapper)
|
737
|
-
mapper.engine.mapper_for(clazz).db_class
|
738
|
-
end
|
739
|
-
|
740
|
-
def configure_polymorphic_has_many
|
741
|
-
engine = Vorpal.define do
|
742
|
-
map Tree do
|
743
|
-
attributes :name
|
744
|
-
has_many :branches
|
745
|
-
belongs_to :trunk
|
746
|
-
end
|
747
|
-
|
748
|
-
map Trunk do
|
749
|
-
attributes :length
|
750
|
-
has_many :bugs, fk: :lives_on_id, fk_type: :lives_on_type
|
751
|
-
end
|
752
|
-
|
753
|
-
map Branch do
|
754
|
-
attributes :length
|
755
|
-
has_many :bugs, fk: :lives_on_id, fk_type: :lives_on_type
|
756
|
-
end
|
757
|
-
|
758
|
-
map Bug do
|
759
|
-
attributes :name
|
760
|
-
end
|
761
|
-
end
|
762
|
-
engine.mapper_for(Tree)
|
763
|
-
end
|
764
|
-
|
765
|
-
def configure_polymorphic_belongs_to
|
766
|
-
engine = Vorpal.define do
|
767
|
-
map Bug do
|
768
|
-
attributes :name
|
769
|
-
belongs_to :lives_on, fk: :lives_on_id, fk_type: :lives_on_type, child_classes: [Trunk, Branch]
|
770
|
-
end
|
771
|
-
|
772
|
-
map Trunk do
|
773
|
-
attributes :length
|
774
|
-
end
|
775
|
-
|
776
|
-
map Branch do
|
777
|
-
attributes :length
|
778
|
-
end
|
779
|
-
end
|
780
|
-
engine.mapper_for(Bug)
|
781
|
-
end
|
782
|
-
|
783
|
-
def configure_ar_polymorphic_belongs_to
|
784
|
-
engine = Vorpal.define do
|
785
|
-
map Tree do
|
786
|
-
attributes :name
|
787
|
-
belongs_to :environment, owned: false, fk: :environment_id, fk_type: :environment_type, child_class: Swamp
|
788
|
-
end
|
789
|
-
|
790
|
-
map Swamp, to: Swamp
|
791
|
-
end
|
792
|
-
engine.mapper_for(Tree)
|
793
|
-
end
|
794
|
-
|
795
|
-
def configure_unowned_polymorphic_belongs_to
|
796
|
-
engine = Vorpal.define do
|
797
|
-
map Bug do
|
798
|
-
attributes :name
|
799
|
-
belongs_to :lives_on, owned: false, fk: :lives_on_id, fk_type: :lives_on_type, child_classes: [Trunk, Branch]
|
800
|
-
end
|
801
|
-
|
802
|
-
map Trunk do
|
803
|
-
attributes :length
|
804
|
-
end
|
805
|
-
|
806
|
-
map Branch do
|
807
|
-
attributes :length
|
808
|
-
end
|
809
|
-
end
|
810
|
-
engine.mapper_for(Bug)
|
811
|
-
end
|
812
|
-
|
813
|
-
def configure_unowned
|
814
|
-
engine = Vorpal.define do
|
815
|
-
map Tree do
|
816
|
-
attributes :name
|
817
|
-
has_many :branches, owned: false
|
818
|
-
belongs_to :trunk, owned: false
|
819
|
-
end
|
820
|
-
|
821
|
-
map Trunk do
|
822
|
-
attributes :length
|
823
|
-
end
|
824
|
-
|
825
|
-
map Branch do
|
826
|
-
attributes :length
|
827
|
-
end
|
828
|
-
end
|
829
|
-
engine.mapper_for(Tree)
|
830
|
-
end
|
831
|
-
|
832
|
-
def configure_recursive
|
833
|
-
engine = Vorpal.define do
|
834
|
-
map Branch do
|
835
|
-
attributes :length
|
836
|
-
has_many :branches
|
837
|
-
end
|
838
|
-
|
839
|
-
map Tree do
|
840
|
-
attributes :name
|
841
|
-
has_many :branches
|
842
|
-
end
|
843
|
-
end
|
844
|
-
engine.mapper_for(Tree)
|
845
|
-
end
|
846
|
-
|
847
|
-
def configure_with_cycle
|
848
|
-
engine = Vorpal.define do
|
849
|
-
map Branch do
|
850
|
-
attributes :length
|
851
|
-
belongs_to :tree
|
852
|
-
end
|
853
|
-
|
854
|
-
map Tree do
|
855
|
-
attributes :name
|
856
|
-
has_many :branches
|
857
|
-
end
|
858
|
-
end
|
859
|
-
engine.mapper_for(Tree)
|
860
|
-
end
|
861
|
-
|
862
|
-
def configure(options={})
|
863
|
-
engine = Vorpal.define(options) do
|
864
|
-
map Tree do
|
865
|
-
attributes :name
|
866
|
-
belongs_to :trunk
|
867
|
-
has_many :fissures
|
868
|
-
has_many :branches
|
869
|
-
end
|
870
|
-
|
871
|
-
map Trunk do
|
872
|
-
attributes :length
|
873
|
-
end
|
874
|
-
|
875
|
-
map Branch do
|
876
|
-
attributes :length
|
877
|
-
end
|
878
|
-
|
879
|
-
map Fissure, to: Fissure
|
880
|
-
end
|
881
|
-
engine.mapper_for(Tree)
|
882
|
-
end
|
883
|
-
|
884
|
-
def configure_has_one
|
885
|
-
engine = Vorpal.define do
|
886
|
-
map Trunk do
|
887
|
-
attributes :length
|
888
|
-
has_one :tree
|
889
|
-
end
|
890
|
-
|
891
|
-
map Tree do
|
892
|
-
attributes :name
|
893
|
-
end
|
894
|
-
end
|
895
|
-
engine.mapper_for(Trunk)
|
896
|
-
end
|
897
|
-
|
898
|
-
def configure_unowned_has_one
|
899
|
-
engine = Vorpal.define do
|
900
|
-
map Trunk do
|
901
|
-
attributes :length
|
902
|
-
has_one :tree, owned: false
|
903
|
-
end
|
904
|
-
|
905
|
-
map Tree do
|
906
|
-
attributes :name
|
907
|
-
end
|
908
|
-
end
|
909
|
-
engine.mapper_for(Trunk)
|
910
|
-
end
|
911
|
-
end
|