rrod 0.0.1 → 1.0.0.alpha.1
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 +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
|