gotime-cassandra_object 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +42 -0
- data/LICENSE +13 -0
- data/README.markdown +79 -0
- data/Rakefile +74 -0
- data/TODO +2 -0
- data/VERSION +1 -0
- data/gotime-cassandra_object.gemspec +134 -0
- data/lib/cassandra_object.rb +13 -0
- data/lib/cassandra_object/associations.rb +35 -0
- data/lib/cassandra_object/associations/one_to_many.rb +136 -0
- data/lib/cassandra_object/associations/one_to_one.rb +77 -0
- data/lib/cassandra_object/attributes.rb +93 -0
- data/lib/cassandra_object/base.rb +97 -0
- data/lib/cassandra_object/callbacks.rb +10 -0
- data/lib/cassandra_object/collection.rb +8 -0
- data/lib/cassandra_object/cursor.rb +86 -0
- data/lib/cassandra_object/dirty.rb +27 -0
- data/lib/cassandra_object/identity.rb +61 -0
- data/lib/cassandra_object/identity/abstract_key_factory.rb +36 -0
- data/lib/cassandra_object/identity/key.rb +20 -0
- data/lib/cassandra_object/identity/natural_key_factory.rb +51 -0
- data/lib/cassandra_object/identity/uuid_key_factory.rb +37 -0
- data/lib/cassandra_object/indexes.rb +129 -0
- data/lib/cassandra_object/log_subscriber.rb +17 -0
- data/lib/cassandra_object/migrations.rb +72 -0
- data/lib/cassandra_object/mocking.rb +15 -0
- data/lib/cassandra_object/persistence.rb +195 -0
- data/lib/cassandra_object/serialization.rb +6 -0
- data/lib/cassandra_object/type_registration.rb +7 -0
- data/lib/cassandra_object/types.rb +128 -0
- data/lib/cassandra_object/validation.rb +49 -0
- data/test/basic_scenarios_test.rb +243 -0
- data/test/callbacks_test.rb +19 -0
- data/test/config/cassandra.in.sh +53 -0
- data/test/config/log4j.properties +38 -0
- data/test/config/storage-conf.xml +221 -0
- data/test/connection.rb +25 -0
- data/test/cursor_test.rb +66 -0
- data/test/dirty_test.rb +34 -0
- data/test/fixture_models.rb +90 -0
- data/test/identity/natural_key_factory_test.rb +94 -0
- data/test/index_test.rb +69 -0
- data/test/legacy/test_helper.rb +18 -0
- data/test/migration_test.rb +21 -0
- data/test/one_to_many_associations_test.rb +163 -0
- data/test/test_case.rb +28 -0
- data/test/test_helper.rb +16 -0
- data/test/time_test.rb +32 -0
- data/test/types_test.rb +252 -0
- data/test/validation_test.rb +25 -0
- data/test/z_mock_test.rb +36 -0
- metadata +243 -0
data/CHANGELOG
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (3.0.3)
|
5
|
+
activesupport (= 3.0.3)
|
6
|
+
builder (~> 2.1.2)
|
7
|
+
i18n (~> 0.4)
|
8
|
+
activesupport (3.0.3)
|
9
|
+
builder (2.1.2)
|
10
|
+
cassandra (0.9.0)
|
11
|
+
json
|
12
|
+
rake
|
13
|
+
simple_uuid (>= 0.1.0)
|
14
|
+
thrift_client (>= 0.6.0)
|
15
|
+
git (1.2.5)
|
16
|
+
i18n (0.5.0)
|
17
|
+
jeweler (1.5.1)
|
18
|
+
bundler (~> 1.0.0)
|
19
|
+
git (>= 1.2.5)
|
20
|
+
rake
|
21
|
+
json (1.4.6)
|
22
|
+
nokogiri (1.4.4)
|
23
|
+
rake (0.8.7)
|
24
|
+
rcov (0.9.9)
|
25
|
+
shoulda (2.11.3)
|
26
|
+
simple_uuid (0.1.1)
|
27
|
+
thrift (0.5.0)
|
28
|
+
thrift_client (0.6.0)
|
29
|
+
thrift (~> 0.5.0)
|
30
|
+
|
31
|
+
PLATFORMS
|
32
|
+
ruby
|
33
|
+
|
34
|
+
DEPENDENCIES
|
35
|
+
activemodel (~> 3)
|
36
|
+
activesupport (~> 3)
|
37
|
+
bundler (~> 1.0.0)
|
38
|
+
cassandra
|
39
|
+
jeweler (~> 1.5.1)
|
40
|
+
nokogiri
|
41
|
+
rcov
|
42
|
+
shoulda
|
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2009 Koziarski Software Ltd
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# Cassandra Object
|
2
|
+
|
3
|
+
Cassandra Object provides a nice API for working with [Cassandra](http://incubator.apache.org/cassandra/). CassandraObjects are mostly duck-type compatible with ActiveRecord objects so most of your controller code should work ok. Note that they're *mostly* compatible, Cassandra has no support for dynamic queries, or sorting. So the following kinds of operations aren't supported and *never will be*.
|
4
|
+
|
5
|
+
* `:order`
|
6
|
+
* `:conditions`
|
7
|
+
* `:joins`
|
8
|
+
* `:group`
|
9
|
+
|
10
|
+
There isn't much in the way of documentation yet, but a few examples.
|
11
|
+
|
12
|
+
class Customer < CassandraObject::Base
|
13
|
+
attribute :first_name, :type => :string
|
14
|
+
attribute :last_name, :type => :string
|
15
|
+
attribute :date_of_birth, :type => :date
|
16
|
+
attribute :signed_up_at, :type => :time_with_zone
|
17
|
+
|
18
|
+
validate :should_be_cool
|
19
|
+
|
20
|
+
key :uuid
|
21
|
+
|
22
|
+
index :date_of_birth
|
23
|
+
|
24
|
+
association :invoices, :unique=>false, :inverse_of=>:customer
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def should_be_cool
|
29
|
+
unless ["Michael", "Anika", "Evan", "James"].include?(first_name)
|
30
|
+
errors.add(:first_name, "must be that of a cool person")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Invoice < CassandraObject::Base
|
36
|
+
attribute :number, :type=>:integer
|
37
|
+
attribute :total, :type=>:float
|
38
|
+
attribute :gst_number, :type=>:string
|
39
|
+
|
40
|
+
# indexes can have a single entry also.
|
41
|
+
index :number, :unique=>true
|
42
|
+
|
43
|
+
# bi-directional associations with read-repair support.
|
44
|
+
association :customer, :unique=>true, :inverse_of=>:invoices
|
45
|
+
|
46
|
+
# Read migration support
|
47
|
+
migrate 1 do |attrs|
|
48
|
+
attrs["total"] ||= rand(2000) / 100.0
|
49
|
+
end
|
50
|
+
|
51
|
+
migrate 2 do |attrs|
|
52
|
+
attrs["gst_number"] = "66-666-666"
|
53
|
+
end
|
54
|
+
|
55
|
+
key :natural, :attributes => :number
|
56
|
+
end
|
57
|
+
|
58
|
+
@invoice = Invoice.get("12345")
|
59
|
+
@invoice.customer.invoices.all.include?(@invoice) # true
|
60
|
+
|
61
|
+
# FAQ
|
62
|
+
|
63
|
+
## How do I make this work?
|
64
|
+
|
65
|
+
Here are some basic directions:
|
66
|
+
|
67
|
+
1. `git clone git://github.com/NZKoz/cassandra_object.git`
|
68
|
+
2. Run the bundler `gem bundle`
|
69
|
+
3. Make sure the tests pass `rake test`
|
70
|
+
|
71
|
+
This gem has backwards compatibility with active support version 2.3.x, this is to enable people to use it with rails 2.3 applications. This backwards compatibility may not continue after the 1.0 release.
|
72
|
+
|
73
|
+
## Should I use this in production?
|
74
|
+
|
75
|
+
Only if you're looking to help out with the development, there are a bunch of rough edges right now.
|
76
|
+
|
77
|
+
## Why do you use a superclass and not a module.
|
78
|
+
|
79
|
+
Because.
|
data/Rakefile
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "gotime-cassandra_object"
|
16
|
+
gem.homepage = "http://github.com/gotime/cassandra_object"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{Cassandra ActiveModel}
|
19
|
+
gem.description = %Q{Cassandra ActiveModel}
|
20
|
+
gem.email = "grantr@gmail.com"
|
21
|
+
gem.authors = ["Michael Koziarski", "grantr"]
|
22
|
+
end
|
23
|
+
Jeweler::RubygemsDotOrgTasks.new
|
24
|
+
|
25
|
+
require 'rake/testtask'
|
26
|
+
Rake::TestTask.new(:test) do |test|
|
27
|
+
test.libs << 'lib' << 'test'
|
28
|
+
test.pattern = 'test/**/test_*.rb'
|
29
|
+
test.verbose = true
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'rcov/rcovtask'
|
33
|
+
Rcov::RcovTask.new do |test|
|
34
|
+
test.libs << 'test'
|
35
|
+
test.pattern = 'test/**/test_*.rb'
|
36
|
+
test.verbose = true
|
37
|
+
end
|
38
|
+
|
39
|
+
task :default => :test
|
40
|
+
|
41
|
+
require 'rake/rdoctask'
|
42
|
+
Rake::RDocTask.new do |rdoc|
|
43
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "cassandra_object #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
50
|
+
|
51
|
+
task :cleanup do
|
52
|
+
unless defined?(CassandraObject)
|
53
|
+
$: << 'test'
|
54
|
+
$: << 'lib'
|
55
|
+
require 'test_helper'
|
56
|
+
end
|
57
|
+
puts "Clearing keyspace! ..."
|
58
|
+
CassandraObject::Base.connection.clear_keyspace!
|
59
|
+
puts "Cleared"
|
60
|
+
end
|
61
|
+
|
62
|
+
task :config_snippet do
|
63
|
+
unless defined?(CassandraObject)
|
64
|
+
$: << 'test'
|
65
|
+
$: << 'lib'
|
66
|
+
require 'test_helper'
|
67
|
+
end
|
68
|
+
|
69
|
+
puts CassandraObject::Base.storage_config_xml
|
70
|
+
end
|
71
|
+
|
72
|
+
task :default=>[:test, :cleanup] do
|
73
|
+
end
|
74
|
+
|
data/TODO
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.6.1
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{gotime-cassandra_object}
|
8
|
+
s.version = "0.6.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Michael Koziarski", "grantr"]
|
12
|
+
s.date = %q{2010-12-10}
|
13
|
+
s.description = %q{Cassandra ActiveModel}
|
14
|
+
s.email = %q{grantr@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.markdown",
|
18
|
+
"TODO"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
"CHANGELOG",
|
22
|
+
"Gemfile",
|
23
|
+
"Gemfile.lock",
|
24
|
+
"LICENSE",
|
25
|
+
"README.markdown",
|
26
|
+
"Rakefile",
|
27
|
+
"TODO",
|
28
|
+
"VERSION",
|
29
|
+
"cassandra_object.gemspec",
|
30
|
+
"lib/cassandra_object.rb",
|
31
|
+
"lib/cassandra_object/associations.rb",
|
32
|
+
"lib/cassandra_object/associations/one_to_many.rb",
|
33
|
+
"lib/cassandra_object/associations/one_to_one.rb",
|
34
|
+
"lib/cassandra_object/attributes.rb",
|
35
|
+
"lib/cassandra_object/base.rb",
|
36
|
+
"lib/cassandra_object/callbacks.rb",
|
37
|
+
"lib/cassandra_object/collection.rb",
|
38
|
+
"lib/cassandra_object/cursor.rb",
|
39
|
+
"lib/cassandra_object/dirty.rb",
|
40
|
+
"lib/cassandra_object/identity.rb",
|
41
|
+
"lib/cassandra_object/identity/abstract_key_factory.rb",
|
42
|
+
"lib/cassandra_object/identity/key.rb",
|
43
|
+
"lib/cassandra_object/identity/natural_key_factory.rb",
|
44
|
+
"lib/cassandra_object/identity/uuid_key_factory.rb",
|
45
|
+
"lib/cassandra_object/indexes.rb",
|
46
|
+
"lib/cassandra_object/log_subscriber.rb",
|
47
|
+
"lib/cassandra_object/migrations.rb",
|
48
|
+
"lib/cassandra_object/mocking.rb",
|
49
|
+
"lib/cassandra_object/persistence.rb",
|
50
|
+
"lib/cassandra_object/serialization.rb",
|
51
|
+
"lib/cassandra_object/type_registration.rb",
|
52
|
+
"lib/cassandra_object/types.rb",
|
53
|
+
"lib/cassandra_object/validation.rb",
|
54
|
+
"test/basic_scenarios_test.rb",
|
55
|
+
"test/callbacks_test.rb",
|
56
|
+
"test/config/cassandra.in.sh",
|
57
|
+
"test/config/log4j.properties",
|
58
|
+
"test/config/storage-conf.xml",
|
59
|
+
"test/connection.rb",
|
60
|
+
"test/cursor_test.rb",
|
61
|
+
"test/dirty_test.rb",
|
62
|
+
"test/fixture_models.rb",
|
63
|
+
"test/identity/natural_key_factory_test.rb",
|
64
|
+
"test/index_test.rb",
|
65
|
+
"test/legacy/test_helper.rb",
|
66
|
+
"test/migration_test.rb",
|
67
|
+
"test/one_to_many_associations_test.rb",
|
68
|
+
"test/test_case.rb",
|
69
|
+
"test/test_helper.rb",
|
70
|
+
"test/time_test.rb",
|
71
|
+
"test/types_test.rb",
|
72
|
+
"test/validation_test.rb",
|
73
|
+
"test/z_mock_test.rb"
|
74
|
+
]
|
75
|
+
s.homepage = %q{http://github.com/gotime/cassandra_object}
|
76
|
+
s.licenses = ["MIT"]
|
77
|
+
s.require_paths = ["lib"]
|
78
|
+
s.rubygems_version = %q{1.3.7}
|
79
|
+
s.summary = %q{Cassandra ActiveModel}
|
80
|
+
s.test_files = [
|
81
|
+
"test/basic_scenarios_test.rb",
|
82
|
+
"test/callbacks_test.rb",
|
83
|
+
"test/connection.rb",
|
84
|
+
"test/cursor_test.rb",
|
85
|
+
"test/dirty_test.rb",
|
86
|
+
"test/fixture_models.rb",
|
87
|
+
"test/identity/natural_key_factory_test.rb",
|
88
|
+
"test/index_test.rb",
|
89
|
+
"test/legacy/test_helper.rb",
|
90
|
+
"test/migration_test.rb",
|
91
|
+
"test/one_to_many_associations_test.rb",
|
92
|
+
"test/test_case.rb",
|
93
|
+
"test/test_helper.rb",
|
94
|
+
"test/time_test.rb",
|
95
|
+
"test/types_test.rb",
|
96
|
+
"test/validation_test.rb",
|
97
|
+
"test/z_mock_test.rb"
|
98
|
+
]
|
99
|
+
|
100
|
+
if s.respond_to? :specification_version then
|
101
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
102
|
+
s.specification_version = 3
|
103
|
+
|
104
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
105
|
+
s.add_runtime_dependency(%q<activesupport>, ["~> 3"])
|
106
|
+
s.add_runtime_dependency(%q<activemodel>, ["~> 3"])
|
107
|
+
s.add_runtime_dependency(%q<cassandra>, [">= 0"])
|
108
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
109
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
110
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
111
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
|
112
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
113
|
+
else
|
114
|
+
s.add_dependency(%q<activesupport>, ["~> 3"])
|
115
|
+
s.add_dependency(%q<activemodel>, ["~> 3"])
|
116
|
+
s.add_dependency(%q<cassandra>, [">= 0"])
|
117
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
118
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
119
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
120
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
121
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
122
|
+
end
|
123
|
+
else
|
124
|
+
s.add_dependency(%q<activesupport>, ["~> 3"])
|
125
|
+
s.add_dependency(%q<activemodel>, ["~> 3"])
|
126
|
+
s.add_dependency(%q<cassandra>, [">= 0"])
|
127
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
128
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
129
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
130
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
131
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'cassandra_object/associations/one_to_many'
|
2
|
+
require 'cassandra_object/associations/one_to_one'
|
3
|
+
|
4
|
+
module CassandraObject
|
5
|
+
module Associations
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
class_inheritable_hash :associations
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def column_family_configuration
|
14
|
+
super << {:Name=>"#{name}Relationships", :CompareWith=>"UTF8Type", :CompareSubcolumnsWith=>"TimeUUIDType", :ColumnType=>"Super"}
|
15
|
+
end
|
16
|
+
|
17
|
+
def association(association_name, options= {})
|
18
|
+
if options[:unique]
|
19
|
+
write_inheritable_hash(:associations, {association_name => OneToOneAssociation.new(association_name, self, options)})
|
20
|
+
else
|
21
|
+
write_inheritable_hash(:associations, {association_name => OneToManyAssociation.new(association_name, self, options)})
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove(key)
|
26
|
+
begin
|
27
|
+
connection.remove("#{name}Relationships", key.to_s)
|
28
|
+
rescue Cassandra::AccessError => e
|
29
|
+
raise e unless e.message =~ /Invalid column family/
|
30
|
+
end
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
class OneToManyAssociation
|
3
|
+
def initialize(association_name, owner_class, options)
|
4
|
+
@association_name = association_name.to_s
|
5
|
+
@owner_class = owner_class
|
6
|
+
@target_class_name = options[:class_name] || association_name.to_s.singularize.camelize
|
7
|
+
@options = options
|
8
|
+
|
9
|
+
define_methods!
|
10
|
+
end
|
11
|
+
|
12
|
+
def find(owner, options = {})
|
13
|
+
reversed = options.has_key?(:reversed) ? options[:reversed] : reversed?
|
14
|
+
cursor = CassandraObject::Cursor.new(target_class, column_family, owner.key.to_s, @association_name, :start_after => options[:start_after], :reversed => reversed)
|
15
|
+
cursor.find(options[:limit] || 100)
|
16
|
+
end
|
17
|
+
|
18
|
+
def add(owner, record, set_inverse = true)
|
19
|
+
connection.insert(column_family, owner.key.to_s, {@association_name=>{new_key=>record.key.to_s}})
|
20
|
+
if has_inverse? && set_inverse
|
21
|
+
inverse.set_inverse(record, owner)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def new_key
|
26
|
+
SimpleUUID::UUID.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def column_family
|
30
|
+
@owner_class.to_s + "Relationships"
|
31
|
+
end
|
32
|
+
|
33
|
+
def connection
|
34
|
+
@owner_class.connection
|
35
|
+
end
|
36
|
+
|
37
|
+
def target_class
|
38
|
+
@target_class ||= @target_class_name.constantize
|
39
|
+
end
|
40
|
+
|
41
|
+
def new_proxy(owner)
|
42
|
+
OneToManyAssociationProxy.new(self, owner)
|
43
|
+
end
|
44
|
+
|
45
|
+
def has_inverse?
|
46
|
+
@options[:inverse_of]
|
47
|
+
end
|
48
|
+
|
49
|
+
def inverse
|
50
|
+
has_inverse? && target_class.associations[@options[:inverse_of]]
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_inverse(owner, record)
|
54
|
+
add(owner, record, false)
|
55
|
+
end
|
56
|
+
|
57
|
+
def reversed?
|
58
|
+
@options[:reversed] == true
|
59
|
+
end
|
60
|
+
|
61
|
+
def define_methods!
|
62
|
+
@owner_class.class_eval <<-eos
|
63
|
+
def #{@association_name}
|
64
|
+
@_#{@association_name} ||= self.class.associations[:#{@association_name}].new_proxy(self)
|
65
|
+
end
|
66
|
+
eos
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class OneToManyAssociationProxy
|
71
|
+
def initialize(association, owner)
|
72
|
+
@association = association
|
73
|
+
@owner = owner
|
74
|
+
end
|
75
|
+
|
76
|
+
include Enumerable
|
77
|
+
def each
|
78
|
+
target.each do |i|
|
79
|
+
yield i
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def <<(record)
|
84
|
+
@association.add(@owner, record)
|
85
|
+
if loaded?
|
86
|
+
@target << record
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get the targets of this association proxy
|
91
|
+
#
|
92
|
+
# @param [Hash] options the options with which to modify this query
|
93
|
+
# @option options [String] :start_after the key after which to start returning results
|
94
|
+
# @option options [Boolean] :reversed (false or association default) return the results in reverse order
|
95
|
+
# @option options [Integer] :limit the max number of results to return
|
96
|
+
# @return [Array<CassandraObject::Base>] an array of objects of type self#target_class
|
97
|
+
#
|
98
|
+
def all(options = {})
|
99
|
+
@association.find(@owner, options)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Create a record of the associated type with
|
103
|
+
# the supplied attributes and add it to this
|
104
|
+
# association
|
105
|
+
#
|
106
|
+
# @param [Hash] attributes the attributes with which to create the object
|
107
|
+
# @return [CassandraObject::Base] the newly created object
|
108
|
+
#
|
109
|
+
def create(attributes)
|
110
|
+
@association.target_class.create(attributes).tap do |record|
|
111
|
+
if record.valid?
|
112
|
+
self << record
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def create!(attributes)
|
118
|
+
@association.target_class.create!(attributes).tap do |record|
|
119
|
+
self << record
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def target
|
124
|
+
@target ||= begin
|
125
|
+
@loaded = true
|
126
|
+
@association.find(@owner)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
alias to_a target
|
131
|
+
|
132
|
+
def loaded?
|
133
|
+
defined?(@loaded) && @loaded
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|