riagent 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +73 -0
- data/LICENSE +202 -0
- data/README.md +230 -0
- data/Rakefile +47 -0
- data/lib/rails/generators/riagent/install/install_generator.rb +35 -0
- data/lib/rails/generators/riagent/install/templates/riak.yml +16 -0
- data/lib/riagent/active_document.rb +53 -0
- data/lib/riagent/associations.rb +119 -0
- data/lib/riagent/configuration.rb +73 -0
- data/lib/riagent/conversion.rb +83 -0
- data/lib/riagent/errors.rb +33 -0
- data/lib/riagent/persistence/riak_json_strategy.rb +62 -0
- data/lib/riagent/persistence.rb +166 -0
- data/lib/riagent/railtie.rb +35 -0
- data/lib/riagent/search_schema.rb +58 -0
- data/lib/riagent/version.rb +23 -0
- data/lib/riagent.rb +29 -0
- data/riagent.gemspec +51 -0
- data/test/config/riak.yml.example +19 -0
- data/test/examples/models/address_book.rb +32 -0
- data/test/examples/models/blog_post.rb +31 -0
- data/test/examples/models/contact.rb +29 -0
- data/test/examples/models/user.rb +41 -0
- data/test/integration/persistence_integration_test.rb +76 -0
- data/test/seeds.rb +30 -0
- data/test/test_helper.rb +33 -0
- data/test/unit/active_document_test.rb +41 -0
- data/test/unit/active_model_lint_test.rb +33 -0
- data/test/unit/associations_has_many_test.rb +32 -0
- data/test/unit/associations_has_one_test.rb +85 -0
- data/test/unit/config_test.rb +37 -0
- data/test/unit/embedded_test.rb +38 -0
- data/test/unit/persistence_riak_json_test.rb +118 -0
- data/test/unit/persistence_test.rb +57 -0
- data/test/unit/search_schema_test.rb +26 -0
- data/test/unit/validation_test.rb +39 -0
- metadata +227 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
## -------------------------------------------------------------------
|
2
|
+
##
|
3
|
+
## Copyright (c) "2014" Dmitri Zagidulin and Basho Technologies, Inc.
|
4
|
+
##
|
5
|
+
## This file is provided to you under the Apache License,
|
6
|
+
## Version 2.0 (the "License"); you may not use this file
|
7
|
+
## except in compliance with the License. You may obtain
|
8
|
+
## a copy of the License at
|
9
|
+
##
|
10
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
##
|
12
|
+
## Unless required by applicable law or agreed to in writing,
|
13
|
+
## software distributed under the License is distributed on an
|
14
|
+
## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
## KIND, either express or implied. See the License for the
|
16
|
+
## specific language governing permissions and limitations
|
17
|
+
## under the License.
|
18
|
+
##
|
19
|
+
## -------------------------------------------------------------------
|
20
|
+
|
21
|
+
require 'active_support/concern'
|
22
|
+
require "active_model"
|
23
|
+
require "active_model/naming"
|
24
|
+
require 'riagent/document'
|
25
|
+
require 'riagent/conversion'
|
26
|
+
require 'riagent/persistence'
|
27
|
+
require 'riagent/associations'
|
28
|
+
require 'riagent/search_schema'
|
29
|
+
|
30
|
+
module Riagent
|
31
|
+
module ActiveDocument
|
32
|
+
extend ActiveSupport::Concern
|
33
|
+
extend ActiveModel::Naming
|
34
|
+
include ActiveModel::Validations
|
35
|
+
|
36
|
+
included do
|
37
|
+
include Riagent::Document
|
38
|
+
include Riagent::Conversion
|
39
|
+
include Riagent::Persistence
|
40
|
+
include Riagent::Associations
|
41
|
+
extend Riagent::SearchSchema
|
42
|
+
end
|
43
|
+
|
44
|
+
module ClassMethods
|
45
|
+
# Returns string representation for the collection name
|
46
|
+
# Used to determine the RiakJson::Collection name, or the Riak Bucket name
|
47
|
+
# Uses ActiveModel::Naming functionality to derive the name
|
48
|
+
def collection_name
|
49
|
+
self.model_name.plural
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
## -------------------------------------------------------------------
|
2
|
+
##
|
3
|
+
## Copyright (c) "2014" Dmitri Zagidulin and Basho Technologies, Inc.
|
4
|
+
##
|
5
|
+
## This file is provided to you under the Apache License,
|
6
|
+
## Version 2.0 (the "License"); you may not use this file
|
7
|
+
## except in compliance with the License. You may obtain
|
8
|
+
## a copy of the License at
|
9
|
+
##
|
10
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
##
|
12
|
+
## Unless required by applicable law or agreed to in writing,
|
13
|
+
## software distributed under the License is distributed on an
|
14
|
+
## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
## KIND, either express or implied. See the License for the
|
16
|
+
## specific language governing permissions and limitations
|
17
|
+
## under the License.
|
18
|
+
##
|
19
|
+
## -------------------------------------------------------------------
|
20
|
+
|
21
|
+
require "active_support/concern"
|
22
|
+
|
23
|
+
module Riagent
|
24
|
+
module Associations
|
25
|
+
extend ActiveSupport::Concern
|
26
|
+
|
27
|
+
module ClassMethods
|
28
|
+
def has_many(name, options={})
|
29
|
+
query_type = options[:using]
|
30
|
+
target_class = options[:class]
|
31
|
+
case query_type
|
32
|
+
when :solr
|
33
|
+
has_many_using_solr(name, target_class, query_type, options)
|
34
|
+
else
|
35
|
+
raise ArgumentError, ":using query type not supported"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Create a has_many association where the collection will be loaded
|
40
|
+
# via RiakJson Solr queries.
|
41
|
+
def has_many_using_solr(name, target_class, query_type, options)
|
42
|
+
target_getter_method = "#{name}".to_sym
|
43
|
+
|
44
|
+
# Create a <target name>_cache attribute accessors
|
45
|
+
# These will be used to store the actual loaded collection
|
46
|
+
target_cache_attribute = "#{name}_cache".to_sym
|
47
|
+
attr_accessor target_cache_attribute
|
48
|
+
|
49
|
+
# Create the getter method
|
50
|
+
define_method(target_getter_method) do
|
51
|
+
# First, check to see if the target collection has already been loaded/cached
|
52
|
+
# cached_collection = send(target_cache_attribute)
|
53
|
+
# if cached_collection.nil?
|
54
|
+
#
|
55
|
+
# source_key_value = send(:key) # Get the source (parent) id
|
56
|
+
# cached_collection = target_class.find(target_key)
|
57
|
+
# send(target_setter_method, cached_collection) # Cache the loaded target collection
|
58
|
+
# end
|
59
|
+
# cached_value
|
60
|
+
end
|
61
|
+
|
62
|
+
target_setter_method = "#{name}=".to_sym
|
63
|
+
|
64
|
+
# Create the setter method=
|
65
|
+
define_method(target_setter_method) do | target |
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def has_one(name, options={})
|
70
|
+
target_key_attribute = "#{name}_key"
|
71
|
+
target_class = options[:class]
|
72
|
+
|
73
|
+
# Create a <target name>_key attribute,
|
74
|
+
attribute target_key_attribute, String, default: ''
|
75
|
+
|
76
|
+
# Create a <target name>_cache attribute accessors
|
77
|
+
# These will be used to store the actual instance of the target
|
78
|
+
target_cache_attribute = "#{name}_cache".to_sym
|
79
|
+
attr_accessor target_cache_attribute
|
80
|
+
|
81
|
+
target_getter_method = "#{name}".to_sym
|
82
|
+
target_setter_method = "#{name}=".to_sym
|
83
|
+
|
84
|
+
# Create the setter method=
|
85
|
+
define_method(target_setter_method) do | target |
|
86
|
+
# Only assignments of the correct target class are allowed
|
87
|
+
unless target.kind_of? target_class
|
88
|
+
raise ArgumentError, "Invalid argument type #{target.class}, #{target_class} expected."
|
89
|
+
end
|
90
|
+
target_key = target ? target.key : nil
|
91
|
+
attribute_setter = "#{target_key_attribute}=".to_sym
|
92
|
+
send(attribute_setter, target_key)
|
93
|
+
attribute_cache_getter = "#{target_cache_attribute}="
|
94
|
+
send(attribute_cache_getter, target)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Create the getter method
|
98
|
+
define_method(target_getter_method) do
|
99
|
+
# First, check to see if the target instance has already been loaded/cached
|
100
|
+
cached_value = send(target_cache_attribute)
|
101
|
+
if cached_value.nil?
|
102
|
+
target_key = send(target_key_attribute)
|
103
|
+
cached_value = target_class.find(target_key)
|
104
|
+
send(target_setter_method, cached_value) # Cache the loaded target instance
|
105
|
+
end
|
106
|
+
cached_value
|
107
|
+
end
|
108
|
+
|
109
|
+
# Create build_<target> method
|
110
|
+
build_helper_method = "build_#{name}".to_sym
|
111
|
+
define_method(build_helper_method) do | attributes |
|
112
|
+
target_instance = target_class.new attributes
|
113
|
+
target_instance.key = self.key # The target object gets the source's key by default
|
114
|
+
send(target_setter_method, target_instance)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
## -------------------------------------------------------------------
|
2
|
+
##
|
3
|
+
## Copyright (c) "2014" Dmitri Zagidulin and Basho Technologies, Inc.
|
4
|
+
##
|
5
|
+
## This file is provided to you under the Apache License,
|
6
|
+
## Version 2.0 (the "License"); you may not use this file
|
7
|
+
## except in compliance with the License. You may obtain
|
8
|
+
## a copy of the License at
|
9
|
+
##
|
10
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
##
|
12
|
+
## Unless required by applicable law or agreed to in writing,
|
13
|
+
## software distributed under the License is distributed on an
|
14
|
+
## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
## KIND, either express or implied. See the License for the
|
16
|
+
## specific language governing permissions and limitations
|
17
|
+
## under the License.
|
18
|
+
##
|
19
|
+
## -------------------------------------------------------------------
|
20
|
+
|
21
|
+
require "active_support/concern"
|
22
|
+
|
23
|
+
module Riagent
|
24
|
+
module Configuration
|
25
|
+
def config
|
26
|
+
@config ||= {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def config=(value)
|
30
|
+
@config = value
|
31
|
+
end
|
32
|
+
|
33
|
+
def config_for(environment=:development)
|
34
|
+
if self.config.present?
|
35
|
+
env_config = self.config[environment.to_s]
|
36
|
+
else
|
37
|
+
env_config = {
|
38
|
+
'host' => ENV['RIAK_HOST'],
|
39
|
+
'http_port' => ENV['RIAK_HTTP_PORT'],
|
40
|
+
'pb_port' => ENV['RIAK_PB_PORT']
|
41
|
+
}
|
42
|
+
end
|
43
|
+
env_config
|
44
|
+
end
|
45
|
+
|
46
|
+
def init_clients(environment=:development)
|
47
|
+
self.init_riak_json_client(environment)
|
48
|
+
end
|
49
|
+
|
50
|
+
def init_riak_json_client(environment=:development)
|
51
|
+
env_config = self.config_for(environment)
|
52
|
+
client = RiakJson::Client.new(env_config['host'], env_config['http_port'])
|
53
|
+
self.riak_json_client = client
|
54
|
+
end
|
55
|
+
|
56
|
+
def load_config_file(config_file_path)
|
57
|
+
config_file = File.expand_path(config_file_path)
|
58
|
+
config_hash = YAML.load(ERB.new(File.read(config_file)).result)
|
59
|
+
self.config = config_hash
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [RiakJson::Client] The client for the current thread.
|
63
|
+
def riak_json_client
|
64
|
+
Thread.current[:riak_json_client] ||= nil
|
65
|
+
end
|
66
|
+
|
67
|
+
# Sets the client for the current thread.
|
68
|
+
# @param [RiakJson::Client] value the client
|
69
|
+
def riak_json_client=(value)
|
70
|
+
Thread.current[:riak_json_client] = value
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
## -------------------------------------------------------------------
|
2
|
+
##
|
3
|
+
## Copyright (c) "2014" Dmitri Zagidulin and Basho Technologies, Inc.
|
4
|
+
##
|
5
|
+
## This file is provided to you under the Apache License,
|
6
|
+
## Version 2.0 (the "License"); you may not use this file
|
7
|
+
## except in compliance with the License. You may obtain
|
8
|
+
## a copy of the License at
|
9
|
+
##
|
10
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
##
|
12
|
+
## Unless required by applicable law or agreed to in writing,
|
13
|
+
## software distributed under the License is distributed on an
|
14
|
+
## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
## KIND, either express or implied. See the License for the
|
16
|
+
## specific language governing permissions and limitations
|
17
|
+
## under the License.
|
18
|
+
##
|
19
|
+
## -------------------------------------------------------------------
|
20
|
+
|
21
|
+
require 'active_model'
|
22
|
+
require 'active_model/conversion'
|
23
|
+
|
24
|
+
module Riagent
|
25
|
+
module Conversion
|
26
|
+
# Has this document been deleted?
|
27
|
+
# Required by ActiveModel::Conversion API
|
28
|
+
# @return [Boolean]
|
29
|
+
def destroyed?
|
30
|
+
@destroyed ||= false
|
31
|
+
end
|
32
|
+
|
33
|
+
# Is this a new, unsaved document?
|
34
|
+
# Required by ActiveModel::Conversion API
|
35
|
+
# @return [Boolean]
|
36
|
+
def new_record?
|
37
|
+
!persisted?
|
38
|
+
end
|
39
|
+
|
40
|
+
# Mark the document as saved/persisted
|
41
|
+
# Called by +save+, and when instantiating query results (see ::Persistence)
|
42
|
+
def persist!
|
43
|
+
@persisted = true
|
44
|
+
end
|
45
|
+
|
46
|
+
# Has this document been saved to RiakJson?
|
47
|
+
# Required by ActiveModel::Conversion API
|
48
|
+
# @return [Boolean]
|
49
|
+
def persisted?
|
50
|
+
@persisted ||= false
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns an Enumerable of all key attributes if any is set, or +nil+ if
|
54
|
+
# the document is not persisted
|
55
|
+
# Required by ActiveModel::Conversion API
|
56
|
+
def to_key
|
57
|
+
self.new_record? ? nil : [self.key]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns an instance of an ActiveModel object (ie, itself)
|
61
|
+
# Required by ActiveModel::Conversion API
|
62
|
+
def to_model
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns a +string+ representing the object's key suitable for use in URLs,
|
67
|
+
# or +nil+ if <tt>persisted?</tt> is +false+.
|
68
|
+
# Required by ActiveModel::Conversion API
|
69
|
+
# @return [String, nil]
|
70
|
+
def to_param
|
71
|
+
self.key
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns a +string+ identifying the path associated with the object.
|
75
|
+
# ActionPack uses this to find a suitable partial to represent the object.
|
76
|
+
# Used in Rails helper methods such as +link_to+
|
77
|
+
# Required by ActiveModel::Conversion API
|
78
|
+
# @return [String]
|
79
|
+
def to_partial_path
|
80
|
+
"#{self.class.collection_name}/#{self.key}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
## -------------------------------------------------------------------
|
2
|
+
##
|
3
|
+
## Copyright (c) "2014" Dmitri Zagidulin and Basho Technologies, Inc.
|
4
|
+
##
|
5
|
+
## This file is provided to you under the Apache License,
|
6
|
+
## Version 2.0 (the "License"); you may not use this file
|
7
|
+
## except in compliance with the License. You may obtain
|
8
|
+
## a copy of the License at
|
9
|
+
##
|
10
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
##
|
12
|
+
## Unless required by applicable law or agreed to in writing,
|
13
|
+
## software distributed under the License is distributed on an
|
14
|
+
## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
## KIND, either express or implied. See the License for the
|
16
|
+
## specific language governing permissions and limitations
|
17
|
+
## under the License.
|
18
|
+
##
|
19
|
+
## -------------------------------------------------------------------
|
20
|
+
|
21
|
+
module Riagent
|
22
|
+
# Generic Riagent exception class
|
23
|
+
class RiagentError < StandardError
|
24
|
+
end
|
25
|
+
|
26
|
+
# Raised by <tt>save!</tt> when a document does not pass validation
|
27
|
+
class InvalidDocumentError < RiagentError
|
28
|
+
attr_reader :document # :nodoc:
|
29
|
+
def initialize(document) # :nodoc:
|
30
|
+
@document = document
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
## -------------------------------------------------------------------
|
2
|
+
##
|
3
|
+
## Copyright (c) "2014" Dmitri Zagidulin and Basho Technologies, Inc.
|
4
|
+
##
|
5
|
+
## This file is provided to you under the Apache License,
|
6
|
+
## Version 2.0 (the "License"); you may not use this file
|
7
|
+
## except in compliance with the License. You may obtain
|
8
|
+
## a copy of the License at
|
9
|
+
##
|
10
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
##
|
12
|
+
## Unless required by applicable law or agreed to in writing,
|
13
|
+
## software distributed under the License is distributed on an
|
14
|
+
## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
## KIND, either express or implied. See the License for the
|
16
|
+
## specific language governing permissions and limitations
|
17
|
+
## under the License.
|
18
|
+
##
|
19
|
+
## -------------------------------------------------------------------
|
20
|
+
|
21
|
+
require "riak_json"
|
22
|
+
require "active_support/concern"
|
23
|
+
|
24
|
+
module Riagent
|
25
|
+
module Persistence
|
26
|
+
module RiakJsonStrategy
|
27
|
+
extend ActiveSupport::Concern
|
28
|
+
|
29
|
+
module ClassMethods
|
30
|
+
def client
|
31
|
+
@client ||= Riagent.riak_json_client
|
32
|
+
end
|
33
|
+
|
34
|
+
def client=(client)
|
35
|
+
@client = client
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a RiakJson::Collection instance for this document
|
39
|
+
def collection
|
40
|
+
@collection ||= self.client.collection(self.collection_name)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Sets the RiakJson::Collection instance for this document
|
44
|
+
def collection=(collection_obj)
|
45
|
+
@collection = collection_obj
|
46
|
+
end
|
47
|
+
|
48
|
+
# Converts from a RiakJson::Document instance to an instance of ActiveDocument
|
49
|
+
# @return [ActiveDocument, nil] ActiveDocument instance, or nil if the Document is nil
|
50
|
+
def from_rj_document(doc, persisted=false)
|
51
|
+
return nil if doc.nil?
|
52
|
+
active_doc_instance = self.instantiate(doc.attributes)
|
53
|
+
active_doc_instance.key = doc.key
|
54
|
+
if persisted
|
55
|
+
active_doc_instance.persist! # Mark as persisted / not new
|
56
|
+
end
|
57
|
+
active_doc_instance
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
## -------------------------------------------------------------------
|
2
|
+
##
|
3
|
+
## Copyright (c) "2014" Dmitri Zagidulin and Basho Technologies, Inc.
|
4
|
+
##
|
5
|
+
## This file is provided to you under the Apache License,
|
6
|
+
## Version 2.0 (the "License"); you may not use this file
|
7
|
+
## except in compliance with the License. You may obtain
|
8
|
+
## a copy of the License at
|
9
|
+
##
|
10
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
##
|
12
|
+
## Unless required by applicable law or agreed to in writing,
|
13
|
+
## software distributed under the License is distributed on an
|
14
|
+
## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
## KIND, either express or implied. See the License for the
|
16
|
+
## specific language governing permissions and limitations
|
17
|
+
## under the License.
|
18
|
+
##
|
19
|
+
## -------------------------------------------------------------------
|
20
|
+
|
21
|
+
require "active_support/concern"
|
22
|
+
require "riagent/persistence/riak_json_strategy"
|
23
|
+
|
24
|
+
module Riagent
|
25
|
+
module Persistence
|
26
|
+
extend ActiveSupport::Concern
|
27
|
+
|
28
|
+
included do
|
29
|
+
extend ActiveModel::Callbacks
|
30
|
+
define_model_callbacks :create, :update, :save, :destroy
|
31
|
+
end
|
32
|
+
|
33
|
+
# Delete the document from its collection
|
34
|
+
def destroy
|
35
|
+
run_callbacks(:destroy) do
|
36
|
+
self.class.collection.remove(self)
|
37
|
+
@destroyed = true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Performs validations and saves the document
|
42
|
+
# The validation process can be skipped by passing <tt>validate: false</tt>.
|
43
|
+
# Also triggers :before_create / :after_create type callbacks
|
44
|
+
# @return [String] Returns the key for the inserted document
|
45
|
+
def save(options={:validate => true})
|
46
|
+
context = new_record? ? :create : :update
|
47
|
+
return false if options[:validate] && !valid?(context)
|
48
|
+
|
49
|
+
run_callbacks(context) do
|
50
|
+
result = self.class.collection.insert(self)
|
51
|
+
self.persist!
|
52
|
+
result
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Attempts to validate and save the document just like +save+ but will raise a +Riagent::InvalidDocumentError+
|
57
|
+
# exception instead of returning +false+ if the doc is not valid.
|
58
|
+
def save!(options={:validate => true})
|
59
|
+
unless save(options)
|
60
|
+
raise Riagent::InvalidDocumentError.new(self)
|
61
|
+
end
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
# Update an object's attributes and save it
|
66
|
+
def update(attrs)
|
67
|
+
run_callbacks(:update) do
|
68
|
+
self.attributes = attrs
|
69
|
+
self.save
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Perform an update(), raise an error if the doc is not valid
|
74
|
+
def update!(attrs)
|
75
|
+
unless update(attrs)
|
76
|
+
raise Riagent::InvalidDocumentError.new(self)
|
77
|
+
end
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
# Update attributes (alias for update() for Rails versions < 4)
|
82
|
+
def update_attributes(attrs)
|
83
|
+
self.update(attrs)
|
84
|
+
end
|
85
|
+
|
86
|
+
module ClassMethods
|
87
|
+
# Returns all documents (within results/pagination limit)
|
88
|
+
# from a collection.
|
89
|
+
# Implemented instead of all() to get around current RiakJson API limitations
|
90
|
+
# @param [String,Symbol] Name of a document field
|
91
|
+
# @param [Integer] Optional results limit
|
92
|
+
# @return [Array] of ActiveDocument instances
|
93
|
+
def all_for_field(field_name, results_limit=1000)
|
94
|
+
query = {
|
95
|
+
field_name => {'$regex' => "/.*/"},
|
96
|
+
'$per_page'=>results_limit
|
97
|
+
}.to_json
|
98
|
+
result = self.collection.find_all(query)
|
99
|
+
if result.present?
|
100
|
+
result.documents.map {|doc| self.from_rj_document(doc, persisted=true) }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Determines the document's persistence strategy
|
105
|
+
# Valid options: [:riak_json]
|
106
|
+
# Usage:
|
107
|
+
# <code>
|
108
|
+
# class SomeModel
|
109
|
+
# include Riagent::ActiveDocument
|
110
|
+
# collection_type :riak_json # persist to a RiakJson::Collection
|
111
|
+
# end
|
112
|
+
# </code>
|
113
|
+
def collection_type(coll_type)
|
114
|
+
@collection_type = coll_type
|
115
|
+
case @collection_type
|
116
|
+
when :riak_json
|
117
|
+
self.persistence_strategy = :riak_json
|
118
|
+
include Riagent::Persistence::RiakJsonStrategy
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Load a document by key.
|
123
|
+
def find(key)
|
124
|
+
return nil if key.nil? or key.empty?
|
125
|
+
doc = self.collection.find_by_key(key)
|
126
|
+
self.from_rj_document(doc, persisted=true)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Return the first document that matches the query
|
130
|
+
def find_one(query)
|
131
|
+
if query.kind_of? Hash
|
132
|
+
query = query.to_json
|
133
|
+
end
|
134
|
+
doc = self.collection.find_one(query)
|
135
|
+
if doc.present?
|
136
|
+
self.from_rj_document(doc, persisted=true)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_collection_type
|
141
|
+
@collection_type ||= nil
|
142
|
+
end
|
143
|
+
|
144
|
+
def persistence_strategy
|
145
|
+
@persistence_strategy ||= nil
|
146
|
+
end
|
147
|
+
|
148
|
+
def persistence_strategy=(strategy)
|
149
|
+
@persistence_strategy = strategy
|
150
|
+
end
|
151
|
+
|
152
|
+
# Return all documents that match the query
|
153
|
+
def where(query)
|
154
|
+
if query.kind_of? Hash
|
155
|
+
query = query.to_json
|
156
|
+
end
|
157
|
+
result = self.collection.find_all(query)
|
158
|
+
if result.present?
|
159
|
+
result.documents.map do |doc|
|
160
|
+
self.from_rj_document(doc, persisted=true)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
## -------------------------------------------------------------------
|
2
|
+
##
|
3
|
+
## Copyright (c) "2014" Dmitri Zagidulin and Basho Technologies, Inc.
|
4
|
+
##
|
5
|
+
## This file is provided to you under the Apache License,
|
6
|
+
## Version 2.0 (the "License"); you may not use this file
|
7
|
+
## except in compliance with the License. You may obtain
|
8
|
+
## a copy of the License at
|
9
|
+
##
|
10
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
##
|
12
|
+
## Unless required by applicable law or agreed to in writing,
|
13
|
+
## software distributed under the License is distributed on an
|
14
|
+
## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
## KIND, either express or implied. See the License for the
|
16
|
+
## specific language governing permissions and limitations
|
17
|
+
## under the License.
|
18
|
+
##
|
19
|
+
## -------------------------------------------------------------------
|
20
|
+
|
21
|
+
require 'rails/railtie'
|
22
|
+
require 'riak_json'
|
23
|
+
|
24
|
+
module Riagent
|
25
|
+
# Railtie for Rails integration and initialization
|
26
|
+
class Railtie < Rails::Railtie
|
27
|
+
initializer "riagent.configure_rails_initialization" do
|
28
|
+
config_file = Rails.root.join('config', 'riak.yml')
|
29
|
+
if File.exist?(config_file)
|
30
|
+
Riagent.load_config_file(config_file)
|
31
|
+
Riagent.init_clients(Rails.env) # Set up the client for the current environment
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
## -------------------------------------------------------------------
|
2
|
+
##
|
3
|
+
## Copyright (c) "2014" Dmitri Zagidulin and Basho Technologies, Inc.
|
4
|
+
##
|
5
|
+
## This file is provided to you under the Apache License,
|
6
|
+
## Version 2.0 (the "License"); you may not use this file
|
7
|
+
## except in compliance with the License. You may obtain
|
8
|
+
## a copy of the License at
|
9
|
+
##
|
10
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
##
|
12
|
+
## Unless required by applicable law or agreed to in writing,
|
13
|
+
## software distributed under the License is distributed on an
|
14
|
+
## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
## KIND, either express or implied. See the License for the
|
16
|
+
## specific language governing permissions and limitations
|
17
|
+
## under the License.
|
18
|
+
##
|
19
|
+
## -------------------------------------------------------------------
|
20
|
+
|
21
|
+
module Riagent
|
22
|
+
# Generates RiakJson::CollectionSchema objects (translated into Solr schemas by RiakJson)
|
23
|
+
# from annotated document attributes.
|
24
|
+
# Usage:
|
25
|
+
# <code>
|
26
|
+
# class SampleModel
|
27
|
+
# include Riagent::ActiveDocument
|
28
|
+
# collection_type :riak_json
|
29
|
+
# attribute :name, required: true, search_index: { as: :text }
|
30
|
+
# end
|
31
|
+
# puts SampleModel.schema.inspect
|
32
|
+
# # => <RiakJson::CollectionSchema:0x000001050eef10 @fields=[{:name=>"name", :type=>"text", :require=>true}]>
|
33
|
+
#
|
34
|
+
# SampleModel.save_solr_schema() # sets that schema for the collection
|
35
|
+
# </code>
|
36
|
+
module SearchSchema
|
37
|
+
# Returns a CollectionSchema instance, derived from the document attributes
|
38
|
+
def schema
|
39
|
+
schema = RiakJson::CollectionSchema.new
|
40
|
+
self.attribute_set.each do | attribute |
|
41
|
+
if attribute.options.include? :search_index
|
42
|
+
field_type = attribute.options[:search_index][:as]
|
43
|
+
schema.add_field(field_type, attribute.options[:name], attribute.options[:required])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
schema
|
47
|
+
end
|
48
|
+
|
49
|
+
# Saves the generated Solr indexing schema to RiakJson.
|
50
|
+
# Usage:
|
51
|
+
# <code>
|
52
|
+
# SampleModel.save_solr_schema()
|
53
|
+
# </code>
|
54
|
+
def save_solr_schema
|
55
|
+
self.collection.set_schema(self.schema)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|