rrod 0.0.1 → 1.0.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/README.md +33 -18
- data/lib/rrod/all.rb +24 -1
- data/lib/rrod/caster/nested_model.rb +16 -0
- data/lib/rrod/caster.rb +34 -0
- data/lib/rrod/cli.rb +9 -2
- data/lib/rrod/configuration.rb +40 -0
- data/lib/rrod/model/attribute.rb +80 -0
- data/lib/rrod/model/attribute_methods.rb +85 -0
- data/lib/rrod/model/collection.rb +37 -0
- data/lib/rrod/model/finders.rb +59 -0
- data/lib/rrod/model/persistence.rb +35 -0
- data/lib/rrod/model/schema.rb +30 -0
- data/lib/rrod/model/serialization.rb +12 -0
- data/lib/rrod/model.rb +38 -0
- data/lib/rrod/query.rb +30 -0
- data/lib/rrod/test_server/rspec.rb +50 -0
- data/lib/rrod/test_server/runner.rb +56 -0
- data/lib/rrod/test_server.rb +77 -0
- data/lib/rrod/version.rb +2 -3
- data/rrod.gemspec +7 -1
- data/spec/rrod/caster_spec.rb +117 -0
- data/spec/rrod/configuration_spec.rb +55 -0
- data/spec/rrod/model/attribute_methods_spec.rb +64 -0
- data/spec/rrod/model/attribute_spec.rb +102 -0
- data/spec/rrod/model/collection_spec.rb +39 -0
- data/spec/rrod/model/finders_spec.rb +78 -0
- data/spec/rrod/model/persistence_spec.rb +43 -0
- data/spec/rrod/model/schema_spec.rb +59 -0
- data/spec/rrod/model/serialization_spec.rb +17 -0
- data/spec/rrod/model/validations_spec.rb +50 -0
- data/spec/rrod/model_spec.rb +50 -0
- data/spec/rrod/query_spec.rb +34 -0
- data/spec/rrod_spec.rb +4 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/models/car.rb +3 -0
- data/spec/support/models/person.rb +41 -0
- data/spec/support/test_server.yml.example +17 -0
- metadata +106 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54fca12a0dd242e700196f2689c7e0c10b20f238
|
4
|
+
data.tar.gz: a218efee402307b755b0e681d1872d231d619771
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4d07847ef76659034a92ca8dcc2711dd47af332dd8e525a411a226885df9fc6de90542fb155d289a941fd89236d6d14bf7466a852db9f5d347d0c8096584abc
|
7
|
+
data.tar.gz: 48e8aca8812277c91321f8120785d399a2c9d3a8c4cbca7732c24ad8a0cff4abab4a9a75af0f395b1414af69f813c7ebf2f1d88faf9ad46663e9fef84223b9e4
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,36 +1,51 @@
|
|
1
|
+
<!--- TODO use consistent capitalization with Rrod and Riak as well as backticks-->
|
1
2
|
# Rrod
|
2
3
|
### Riak ruby object database.
|
3
4
|
Rrod lets you use the super awesome database, riak, to model and persist your
|
4
5
|
ruby objects.
|
5
6
|
|
6
|
-
|
7
|
-
First, you must make sure you
|
8
|
-
http://docs.basho.com/riak/latest/quickstart/#Install-Riak.
|
9
|
-
These guys have extremely good docs
|
10
|
-
|
7
|
+
## Riak Installation
|
8
|
+
First, you must make sure you
|
9
|
+
[have Riak installed](http://docs.basho.com/riak/latest/quickstart/#Install-Riak).
|
10
|
+
These guys have extremely good docs and will usually answer your questions
|
11
|
+
in freenode IRC #riak. You must also make sure you have
|
12
|
+
[enabled search](http://docs.basho.com/riak/latest/ops/advanced/configs/search/)
|
13
|
+
for your Riak installation.
|
11
14
|
|
12
|
-
## Installation
|
15
|
+
## Rrod Installation
|
13
16
|
Add `rrod` to your Gemfile and run `bundle` or execute `gem install rrod`.
|
14
17
|
|
15
|
-
|
16
|
-
Once you have
|
17
|
-
|
18
|
+
## Usage
|
19
|
+
Once you have Riak and Rrod installed you can begin to play. `Rrod` will
|
20
|
+
connect to Riak on localhost using protocol buffers on port 8087. What you
|
21
|
+
say? Don't worry about it.
|
18
22
|
|
19
|
-
|
23
|
+
Next, if you installed Rrod by adding it to your Gemfile, run
|
20
24
|
|
21
|
-
|
25
|
+
```
|
26
|
+
$ bundle exec rrod pry
|
27
|
+
```
|
22
28
|
|
23
|
-
|
24
|
-
|
29
|
+
Otherwise, if you installed using `gem install rrod`, run:
|
30
|
+
|
31
|
+
```
|
32
|
+
$ rrod pry
|
33
|
+
```
|
34
|
+
|
35
|
+
This will set you up with an pry environment with `Rrod` loaded.
|
36
|
+
Next you will wave your magic wand and enter the following incantations:
|
25
37
|
|
26
38
|
```ruby
|
27
|
-
Car = Class.new
|
28
|
-
car =
|
29
|
-
|
30
|
-
@car = Car.
|
31
|
-
@car.
|
39
|
+
Car = Class.new { include Rrod::Model }
|
40
|
+
car = Car.new(wheels: 5, color: 'black', make: 'Jeep')
|
41
|
+
car.save
|
42
|
+
@car = Car.find_first_by make: 'Jeep'
|
43
|
+
@car.wheels # => 5
|
32
44
|
```
|
33
45
|
|
46
|
+
`Rrod` lets you have arbitrary attributes on your ruby objects and persist and
|
47
|
+
retreive them from Riak.
|
48
|
+
|
34
49
|
## Contributing
|
35
50
|
|
36
51
|
1. Fork it
|
data/lib/rrod/all.rb
CHANGED
@@ -1 +1,24 @@
|
|
1
|
-
require '
|
1
|
+
require 'active_model'
|
2
|
+
require 'active_support/concern'
|
3
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
4
|
+
require 'active_support/core_ext/hash/keys'
|
5
|
+
require 'active_support/core_ext/string/conversions'
|
6
|
+
require 'active_support/core_ext/string/inflections'
|
7
|
+
require 'active_support/core_ext/string/starts_ends_with'
|
8
|
+
require 'american_date'
|
9
|
+
require 'bigdecimal'
|
10
|
+
require 'riak'
|
11
|
+
|
12
|
+
require 'rrod/version' # first
|
13
|
+
require 'rrod/configuration'
|
14
|
+
require 'rrod/caster'
|
15
|
+
require 'rrod/caster/nested_model'
|
16
|
+
require 'rrod/model/attribute'
|
17
|
+
require 'rrod/model/attribute_methods'
|
18
|
+
require 'rrod/model/collection'
|
19
|
+
require 'rrod/model/finders'
|
20
|
+
require 'rrod/model/persistence'
|
21
|
+
require 'rrod/model/schema'
|
22
|
+
require 'rrod/model/serialization'
|
23
|
+
require 'rrod/model'
|
24
|
+
require 'rrod/query'
|
data/lib/rrod/caster.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rrod
|
2
|
+
class Caster
|
3
|
+
|
4
|
+
def initialize(&casting)
|
5
|
+
@casting = casting
|
6
|
+
end
|
7
|
+
|
8
|
+
def rrod_cast(value)
|
9
|
+
return if value.nil?
|
10
|
+
@casting.(value)
|
11
|
+
end
|
12
|
+
|
13
|
+
module Boolean
|
14
|
+
extend self
|
15
|
+
def rrod_cast(value)
|
16
|
+
[nil, false, 'false', 0, '0'].include?(value) ? false : true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
BigDecimal = new { |value| ::BigDecimal.new(value.to_s) }
|
21
|
+
Date = new { |value| value.to_date }
|
22
|
+
DateTime = new { |value| value.to_datetime }
|
23
|
+
Float = new { |value| value.to_f }
|
24
|
+
Integer = new { |value| value.to_i }
|
25
|
+
Numeric = new { |value|
|
26
|
+
float_value = value.to_f
|
27
|
+
int_value = value.to_i
|
28
|
+
float_value == int_value ? int_value : float_value
|
29
|
+
}
|
30
|
+
String = new { |value| value.to_s }
|
31
|
+
Symbol = new { |value| value.to_sym }
|
32
|
+
Time = new { |value| value.to_time }
|
33
|
+
end
|
34
|
+
end
|
data/lib/rrod/cli.rb
CHANGED
@@ -1,16 +1,23 @@
|
|
1
1
|
require 'thor'
|
2
|
+
require 'rrod'
|
2
3
|
|
3
4
|
module Rrod
|
4
5
|
class Cli < Thor
|
5
6
|
package_name "Rrod"
|
6
7
|
|
7
8
|
map "-i" => :pry
|
9
|
+
map "-t" => :test
|
8
10
|
|
9
11
|
desc "pry", "start an interactive ruby session with Rrod loaded"
|
10
12
|
def pry
|
11
13
|
require 'pry'
|
12
|
-
|
13
|
-
|
14
|
+
TOPLEVEL_BINDING.pry
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "test", "start the Rrod::TestServer"
|
18
|
+
def test
|
19
|
+
require 'rrod/test_server/runner'
|
20
|
+
Rrod::TestServer::Runner.run
|
14
21
|
end
|
15
22
|
end
|
16
23
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Rrod
|
2
|
+
module Config
|
3
|
+
def configure
|
4
|
+
yield configuration if block_given?
|
5
|
+
end
|
6
|
+
|
7
|
+
def configuration
|
8
|
+
@configuration ||= Configuration.new
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
extend Config
|
13
|
+
|
14
|
+
class Configuration
|
15
|
+
attr_accessor :client, :http_port, :pb_port, :protocol,
|
16
|
+
:test_server_yml, :test_server_search_startup_timeout, :nodes
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@protocol = 'pbc'
|
20
|
+
@test_server_yml = File.expand_path('spec/support/test_server.yml', '.')
|
21
|
+
@test_server_search_startup_timeout = 40 # because it's a test
|
22
|
+
end
|
23
|
+
|
24
|
+
def client
|
25
|
+
@client ||= Riak::Client.new(client_options)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def client_options
|
31
|
+
attributes = %w[http_port pb_port protocol nodes]
|
32
|
+
attributes.inject({}) do |acc, method|
|
33
|
+
acc.tap { |hash|
|
34
|
+
value = public_send(method)
|
35
|
+
hash[method.to_sym] = value unless value.nil?
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Rrod
|
2
|
+
module Model
|
3
|
+
class Attribute
|
4
|
+
|
5
|
+
def self.reader_definition(name)
|
6
|
+
-> { read_attribute name }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.writer_definition(name)
|
10
|
+
->(value) { write_attribute name, value }
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :model, :name, :type, :options, :default
|
14
|
+
|
15
|
+
# @param [Class] The class that is declaring the attribute
|
16
|
+
# @param [Symbol] The name of the attribute
|
17
|
+
# @param [Class] The type of the attribute for marshalling
|
18
|
+
# @param [Hash] Options for the attribute (they are optional).
|
19
|
+
def initialize(model, name, type, options={})
|
20
|
+
self.model = model
|
21
|
+
self.name = name.to_sym
|
22
|
+
self.type = type
|
23
|
+
self.default = options.delete(:default)
|
24
|
+
self.options = options
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Object] default value or result of call on default value
|
28
|
+
def default
|
29
|
+
@default.respond_to?(:call) ? @default.call : @default
|
30
|
+
end
|
31
|
+
|
32
|
+
def define
|
33
|
+
define_reader
|
34
|
+
define_writer
|
35
|
+
apply_validators
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def cast(value)
|
40
|
+
caster = type.respond_to?(:rrod_cast) ? type : rrod_caster
|
41
|
+
caster ? caster.rrod_cast(value) : value
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def name=(value)
|
47
|
+
@name = value.to_sym
|
48
|
+
end
|
49
|
+
|
50
|
+
def type=(value)
|
51
|
+
@type = value
|
52
|
+
@type.extend(Rrod::Caster::NestedModel) if nested_model?
|
53
|
+
end
|
54
|
+
|
55
|
+
def nested_model?
|
56
|
+
type.is_a?(Array) and type.first.ancestors.include?(Rrod::Model)
|
57
|
+
end
|
58
|
+
|
59
|
+
def define_reader
|
60
|
+
model.send :define_method, name, self.class.reader_definition(name)
|
61
|
+
end
|
62
|
+
|
63
|
+
def define_writer
|
64
|
+
model.send :define_method, "#{name}=", self.class.writer_definition(name)
|
65
|
+
end
|
66
|
+
|
67
|
+
def apply_validators
|
68
|
+
model.validates name, options if options.present?
|
69
|
+
end
|
70
|
+
|
71
|
+
def rrod_caster
|
72
|
+
"Rrod::Caster::#{type}".constantize
|
73
|
+
rescue NameError
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# stand-in for true/false attribute types
|
80
|
+
Boolean = Module.new unless defined? ::Boolean
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Rrod
|
2
|
+
module Model
|
3
|
+
module AttributeMethods
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
@attributes = {}
|
7
|
+
self.magic_methods = attributes.keys
|
8
|
+
self.attributes = attributes
|
9
|
+
end
|
10
|
+
|
11
|
+
def id
|
12
|
+
read_attribute :id
|
13
|
+
end
|
14
|
+
|
15
|
+
def id=(value)
|
16
|
+
write_attribute :id, value
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns a new hash with all of the object's attributes.
|
20
|
+
# @return [Hash] the object's attributes
|
21
|
+
def attributes
|
22
|
+
@attributes.keys.inject({}) { |acc, key|
|
23
|
+
acc.tap { |hash| hash[key] = respond_to?(key) ? public_send(key) : nil }
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Mass assign the attributes of the object.
|
28
|
+
# @param [Hash] the attributes to mass assign
|
29
|
+
def attributes=(attrs)
|
30
|
+
attrs.each do |key, value|
|
31
|
+
public_send "#{key}=", value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Read a single attribute of the object.
|
36
|
+
# @param [Symbol, String] the key of the attribute to read
|
37
|
+
# @return the attribute at the given key
|
38
|
+
def read_attribute(key)
|
39
|
+
@attributes[key.to_s]
|
40
|
+
end
|
41
|
+
alias :[] :read_attribute
|
42
|
+
|
43
|
+
# Write a given value to the attributes for a given key.
|
44
|
+
# @param [Symbol, String] the key of the attribute to write
|
45
|
+
# @param the value to write to attributes
|
46
|
+
def write_attribute(key, value)
|
47
|
+
@attributes[key.to_s] = self.class.cast_attribute(key, value)
|
48
|
+
end
|
49
|
+
alias :[]= :write_attribute
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def magic_methods=(keys)
|
54
|
+
return if self.class.schema? # classes with attributes don't get magic methods
|
55
|
+
@magic_methods = keys.inject([]) { |acc, k| acc << k.to_s << "#{k}=" }
|
56
|
+
end
|
57
|
+
|
58
|
+
def magic_methods
|
59
|
+
@magic_methods || []
|
60
|
+
end
|
61
|
+
|
62
|
+
def define_singleton_reader(attribute)
|
63
|
+
define_singleton_method attribute, Attribute.reader_definition(attribute)
|
64
|
+
end
|
65
|
+
|
66
|
+
def define_singleton_writer(attribute)
|
67
|
+
define_singleton_method "#{attribute}=", Attribute.writer_definition(attribute)
|
68
|
+
end
|
69
|
+
|
70
|
+
def method_missing(method_id, *args, &block)
|
71
|
+
method = method_id.to_s
|
72
|
+
return super unless magic_methods.include?(method)
|
73
|
+
|
74
|
+
accessor = method.ends_with?('=') ? :writer : :reader
|
75
|
+
send "define_singleton_#{accessor}", method.chomp('=')
|
76
|
+
send method_id, *args
|
77
|
+
end
|
78
|
+
|
79
|
+
def respond_to_missing?(*args)
|
80
|
+
magic_methods.include? args.first.to_s
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Rrod
|
2
|
+
module Model
|
3
|
+
class Collection
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
delegate(*%w[clear count each length size], to: :collection)
|
7
|
+
|
8
|
+
def initialize(collection=[])
|
9
|
+
self.collection = collection
|
10
|
+
end
|
11
|
+
|
12
|
+
def collection=(collection)
|
13
|
+
raise InvalidCollectionTypeError.new unless collection.respond_to?(:each)
|
14
|
+
collection.map { |member| push member }
|
15
|
+
rescue InvalidMemberTypeError => e
|
16
|
+
clear and raise e
|
17
|
+
end
|
18
|
+
|
19
|
+
def collection
|
20
|
+
@collection ||= []
|
21
|
+
end
|
22
|
+
|
23
|
+
def push(value)
|
24
|
+
raise InvalidMemberTypeError.new unless Rrod::Model === (value)
|
25
|
+
collection.push(value)
|
26
|
+
end
|
27
|
+
alias :<< :push
|
28
|
+
|
29
|
+
def serializable_hash(*)
|
30
|
+
collection.map(&:serializable_hash)
|
31
|
+
end
|
32
|
+
|
33
|
+
InvalidCollectionTypeError = Class.new(StandardError)
|
34
|
+
InvalidMemberTypeError = Class.new(StandardError)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Rrod
|
2
|
+
module Model
|
3
|
+
module Finders
|
4
|
+
|
5
|
+
def find(id)
|
6
|
+
find_one(id).tap { |found| raise NotFound.new if found.nil? }
|
7
|
+
end
|
8
|
+
|
9
|
+
def find_one(id)
|
10
|
+
robject = bucket.get(id)
|
11
|
+
found(id, robject.data, robject)
|
12
|
+
rescue Riak::FailedRequest => e
|
13
|
+
raise e unless e.not_found?
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_first_by(attributes)
|
17
|
+
query = Query.new(attributes)
|
18
|
+
|
19
|
+
if query.using_id?
|
20
|
+
find_one(query.id)
|
21
|
+
else
|
22
|
+
docs = search(query)
|
23
|
+
docs.any? ? found(nil, docs.first) : nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def find_first_by!(attributes)
|
28
|
+
find_first_by(attributes).tap { |model| raise NotFound.new if model.nil? }
|
29
|
+
end
|
30
|
+
|
31
|
+
def find_all_by(attributes)
|
32
|
+
query = Query.new(attributes)
|
33
|
+
raise ArgumentError.new('Cannot pass id to find_all_by') if query.using_id?
|
34
|
+
search(query).map { |doc| found(nil, doc) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def find_all_by!(attributes)
|
38
|
+
find_all_by(attributes).tap { |models| raise NotFound.new if models.empty? }
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def search(query)
|
44
|
+
client.search(bucket_name, query.to_s)['docs']
|
45
|
+
end
|
46
|
+
|
47
|
+
def found(key, data, robject=nil)
|
48
|
+
new(data).tap { |instance|
|
49
|
+
instance.id = key
|
50
|
+
instance.robject = robject
|
51
|
+
instance.instance_variable_set(:@persisted, true)
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
NotFound = Class.new(StandardError)
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Rrod
|
2
|
+
module Model
|
3
|
+
module Persistence
|
4
|
+
attr_accessor :robject
|
5
|
+
|
6
|
+
def persisted?
|
7
|
+
@persisted
|
8
|
+
end
|
9
|
+
|
10
|
+
def new?
|
11
|
+
!persisted?
|
12
|
+
end
|
13
|
+
alias :new_record? :new?
|
14
|
+
|
15
|
+
def save(options={})
|
16
|
+
options.fetch(:validate, true) ?
|
17
|
+
(valid? and persist) : persist
|
18
|
+
end
|
19
|
+
|
20
|
+
def persist
|
21
|
+
bucket.enable_index!
|
22
|
+
robject.raw_data = to_json
|
23
|
+
robject.key = id unless id.nil?
|
24
|
+
robject.store
|
25
|
+
self.id = robject.key
|
26
|
+
@persisted = true
|
27
|
+
end
|
28
|
+
|
29
|
+
def robject
|
30
|
+
@robject ||= bucket.new
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Rrod
|
2
|
+
module Model
|
3
|
+
module Schema
|
4
|
+
|
5
|
+
def attributes
|
6
|
+
@attributes ||= {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def attribute(name, type, options={})
|
10
|
+
attributes[name.to_sym] = Attribute.new(self, name, type, options).define
|
11
|
+
end
|
12
|
+
|
13
|
+
def cast_attribute(key, value)
|
14
|
+
attribute = attributes[key.to_sym]
|
15
|
+
attribute ? attribute.cast(value) : value
|
16
|
+
end
|
17
|
+
|
18
|
+
def schema?
|
19
|
+
attributes.any?
|
20
|
+
end
|
21
|
+
|
22
|
+
def rrod_cast(value)
|
23
|
+
return if value.nil?
|
24
|
+
return value if value.is_a?(Rrod::Model)
|
25
|
+
found(nil, value)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/rrod/model.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module Rrod
|
2
|
+
module Model
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
include AttributeMethods
|
6
|
+
include Persistence
|
7
|
+
include Serialization
|
8
|
+
include ActiveModel::Serializers::JSON
|
9
|
+
include ActiveModel::Serializers::Xml
|
10
|
+
include ActiveModel::Validations
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
include Finders
|
14
|
+
include Schema
|
15
|
+
|
16
|
+
def client
|
17
|
+
Rrod.configuration.client
|
18
|
+
end
|
19
|
+
|
20
|
+
def bucket
|
21
|
+
@bucket ||= client[bucket_name]
|
22
|
+
end
|
23
|
+
|
24
|
+
# TODO make class attribute
|
25
|
+
def bucket_name
|
26
|
+
name.tableize
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def client
|
31
|
+
self.class.client
|
32
|
+
end
|
33
|
+
|
34
|
+
def bucket
|
35
|
+
self.class.bucket
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/rrod/query.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module Rrod
|
2
|
+
class Query
|
3
|
+
attr_accessor :options
|
4
|
+
|
5
|
+
def initialize(options)
|
6
|
+
self.options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def id
|
10
|
+
options[:id]
|
11
|
+
end
|
12
|
+
|
13
|
+
def using_id?
|
14
|
+
id.present?
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
options.map { |key, value| "#{key}:#{value}" }.join(" AND ")
|
19
|
+
end
|
20
|
+
|
21
|
+
def options=(options)
|
22
|
+
@options = options.with_indifferent_access
|
23
|
+
raise ArgumentError.new("no search options") if options.blank?
|
24
|
+
raise ArgumentError.new("cannot mix id with other options") if using_id? and options.keys.count > 1
|
25
|
+
rescue => e
|
26
|
+
@options.clear and raise e
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|