riagent 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4eadd9aec51f179844d1ac1a5ff54826ba59ad35
4
- data.tar.gz: 4cbaed26f3b6f06e43c0405f401b69835f10ca81
3
+ metadata.gz: 189f3608c683deba5f7d5396006eca9567270aef
4
+ data.tar.gz: 92e10aef1130cbf20a18f5796659f1ea7e6ced30
5
5
  SHA512:
6
- metadata.gz: b31c273dbcc22ad47467ce2f7d5875ce6b04be513124b38973695130266341ed4e8440bc786d34f7e9d044271b0f77a46abc50b05f4f0155086765cfbe852bac
7
- data.tar.gz: e59f9bdd5a8e332de5e56c49e3565c772e485fbff10e19ae3f96fd1ac79e0d6ad0e4436d1c041290c471fe95ffe50c4216710d6bc8f86a187fa5e743966e0acf
6
+ metadata.gz: c6246e9dfff27679cd03f175fd0500fe67f8ad7b410eff03a3b421dccb5b589cf5554464ada2dffa5e3f8828657c1bc36ace4bc431c7a91360325672865fb7d8
7
+ data.tar.gz: a028746246a003269eaf376248b64713415e25d1279a1f6c1ed2dfc6ca6a4d6dd2b52c6ec55a53e382d98540b747c30aaa0c296b21bf5fdcd0580633b5733c98
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- riagent (0.0.1)
4
+ riagent (0.0.2)
5
5
  activemodel (~> 4.0)
6
6
  activesupport (~> 4.0)
7
7
  riagent-document
@@ -11,56 +11,56 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- activemodel (4.0.2)
15
- activesupport (= 4.0.2)
14
+ activemodel (4.0.5)
15
+ activesupport (= 4.0.5)
16
16
  builder (~> 3.1.0)
17
- activesupport (4.0.2)
18
- i18n (~> 0.6, >= 0.6.4)
17
+ activesupport (4.0.5)
18
+ i18n (~> 0.6, >= 0.6.9)
19
19
  minitest (~> 4.2)
20
20
  multi_json (~> 1.3)
21
21
  thread_safe (~> 0.1)
22
22
  tzinfo (~> 0.3.37)
23
- atomic (1.1.14)
24
- axiom-types (0.0.5)
25
- descendants_tracker (~> 0.0.1)
26
- ice_nine (~> 0.9)
23
+ axiom-types (0.1.1)
24
+ descendants_tracker (~> 0.0.4)
25
+ ice_nine (~> 0.11.0)
26
+ thread_safe (~> 0.3, >= 0.3.1)
27
27
  beefcake (0.3.7)
28
28
  builder (3.1.4)
29
29
  coercible (1.0.0)
30
30
  descendants_tracker (~> 0.0.1)
31
- descendants_tracker (0.0.3)
31
+ descendants_tracker (0.0.4)
32
+ thread_safe (~> 0.3, >= 0.3.1)
32
33
  equalizer (0.0.9)
33
34
  i18n (0.6.9)
34
35
  ice_nine (0.11.0)
35
36
  innertube (1.0.2)
36
37
  json (1.8.1)
37
- mime-types (2.1)
38
+ mime-types (2.3)
38
39
  minitest (4.7.5)
39
40
  minitest-spec-context (0.0.3)
40
- multi_json (1.8.4)
41
- rake (10.1.1)
41
+ multi_json (1.10.1)
42
+ rake (10.3.2)
42
43
  rest-client (1.6.7)
43
44
  mime-types (>= 1.16)
44
45
  riagent-document (0.0.1)
45
46
  activesupport (~> 4.0)
46
47
  virtus
47
- riak-client (1.4.3)
48
+ riak-client (1.4.4.1)
48
49
  beefcake (~> 0.3.7)
49
50
  builder (>= 2.1.2)
50
51
  i18n (>= 0.4.0)
51
52
  innertube (~> 1.0.2)
52
53
  multi_json (~> 1.0)
53
- riak_json (0.0.2)
54
+ riak_json (0.0.4)
54
55
  json
55
56
  rest-client
56
- thread_safe (0.1.3)
57
- atomic
58
- tzinfo (0.3.38)
59
- virtus (1.0.1)
60
- axiom-types (~> 0.0.5)
57
+ thread_safe (0.3.4)
58
+ tzinfo (0.3.39)
59
+ virtus (1.0.2)
60
+ axiom-types (~> 0.1)
61
61
  coercible (~> 1.0)
62
- descendants_tracker (~> 0.0.1)
63
- equalizer (~> 0.0.7)
62
+ descendants_tracker (~> 0.0.3)
63
+ equalizer (~> 0.0.9)
64
64
 
65
65
  PLATFORMS
66
66
  ruby
@@ -39,6 +39,8 @@ module Riagent
39
39
  include Riagent::Persistence
40
40
  include Riagent::Associations
41
41
  extend Riagent::SearchSchema
42
+
43
+ attr_accessor :source_object
42
44
  end
43
45
 
44
46
  module ClassMethods
@@ -19,6 +19,7 @@
19
19
  ## -------------------------------------------------------------------
20
20
 
21
21
  require "active_support/concern"
22
+ require "riak"
22
23
 
23
24
  module Riagent
24
25
  module Configuration
@@ -30,6 +31,9 @@ module Riagent
30
31
  @config = value
31
32
  end
32
33
 
34
+ # Return a configuration hash for a given environment
35
+ # @param [Symbol] environment Environment for which to load the client configs
36
+ # @return [Hash]
33
37
  def config_for(environment=:development)
34
38
  if self.config.present?
35
39
  env_config = self.config[environment.to_s]
@@ -42,15 +46,28 @@ module Riagent
42
46
  end
43
47
  env_config
44
48
  end
45
-
46
- def init_clients(environment=:development)
47
- self.init_riak_json_client(environment)
49
+
50
+ # @param [Hash] env_config Configuration hash for a given environment
51
+ def init_riak_json_client(env_config)
52
+ client = RiakJson::Client.new(env_config['host'], env_config['http_port'])
53
+ self.riak_json_client = client
54
+ end
55
+
56
+ # @param [Hash] env_config Configuration hash for a given environment
57
+ def init_riak_client(env_config)
58
+ client = Riak::Client.new host: env_config['host'], pb_port: env_config['pb_port'], protocol: 'pbc'
59
+ self.riak_client = client
48
60
  end
49
61
 
50
- def init_riak_json_client(environment=:development)
62
+ # Initialize a Riagent persistence client for a given environment
63
+ # Either called explicitly (see test/test_helper.rb for example usage)
64
+ # or called by Rails through the 'riagent.configure_rails_initialization' initializer
65
+ # in lib/railtie.rb
66
+ # @param [Symbol] environment
67
+ def init_clients(environment=:development)
51
68
  env_config = self.config_for(environment)
52
- client = RiakJson::Client.new(env_config['host'], env_config['http_port'])
53
- self.riak_json_client = client
69
+ self.init_riak_json_client(env_config)
70
+ self.init_riak_client(env_config)
54
71
  end
55
72
 
56
73
  def load_config_file(config_file_path)
@@ -59,12 +76,23 @@ module Riagent
59
76
  self.config = config_hash
60
77
  end
61
78
 
62
- # @return [RiakJson::Client] The client for the current thread.
79
+ # @return [Riak::Client] The Riak client for the current thread.
80
+ def riak_client
81
+ Thread.current[:riak_client] ||= nil
82
+ end
83
+
84
+ # Sets the Riak client for the current thread.
85
+ # @param [Riak::Client] value the client
86
+ def riak_client=(value)
87
+ Thread.current[:riak_client] = value
88
+ end
89
+
90
+ # @return [RiakJson::Client] The RiakJson client for the current thread.
63
91
  def riak_json_client
64
92
  Thread.current[:riak_json_client] ||= nil
65
93
  end
66
-
67
- # Sets the client for the current thread.
94
+
95
+ # Sets the RiakJson client for the current thread.
68
96
  # @param [RiakJson::Client] value the client
69
97
  def riak_json_client=(value)
70
98
  Thread.current[:riak_json_client] = value
@@ -29,6 +29,7 @@ module Riagent
29
29
  def destroyed?
30
30
  @destroyed ||= false
31
31
  end
32
+ alias :deleted? :destroyed?
32
33
 
33
34
  # Is this a new, unsaved document?
34
35
  # Required by ActiveModel::Conversion API
@@ -37,7 +38,7 @@ module Riagent
37
38
  !persisted?
38
39
  end
39
40
 
40
- # Mark the document as saved/persisted
41
+ # Marks the document as saved/persisted
41
42
  # Called by +save+, and when instantiating query results (see ::Persistence)
42
43
  def persist!
43
44
  @persisted = true
@@ -66,7 +67,7 @@ module Riagent
66
67
  # Returns a +string+ representing the object's key suitable for use in URLs,
67
68
  # or +nil+ if <tt>persisted?</tt> is +false+.
68
69
  # Required by ActiveModel::Conversion API
69
- # @return [String, nil]
70
+ # @return [String|nil]
70
71
  def to_param
71
72
  self.key
72
73
  end
@@ -19,12 +19,19 @@
19
19
  ## -------------------------------------------------------------------
20
20
 
21
21
  require "active_support/concern"
22
+ require "riagent/persistence/persistence_strategy"
22
23
  require "riagent/persistence/riak_json_strategy"
24
+ require "riagent/persistence/riak_no_index_strategy"
23
25
 
24
26
  module Riagent
27
+ # Provides a common persistence API for RiakJson Documents.
28
+ # Most persistence calls are delegated to the Collection class instance,
29
+ # which are implemented in persistence/*_strategy.rb modules.
25
30
  module Persistence
26
31
  extend ActiveSupport::Concern
27
32
 
33
+ COLLECTION_TYPES = [:riak_json, :riak_no_index]
34
+
28
35
  included do
29
36
  extend ActiveModel::Callbacks
30
37
  define_model_callbacks :create, :update, :save, :destroy
@@ -32,8 +39,9 @@ module Riagent
32
39
 
33
40
  # Delete the document from its collection
34
41
  def destroy
42
+ return nil if self.new_record?
35
43
  run_callbacks(:destroy) do
36
- self.class.collection.remove(self)
44
+ self.class.persistence.remove(self)
37
45
  @destroyed = true
38
46
  end
39
47
  end
@@ -43,13 +51,17 @@ module Riagent
43
51
  # Also triggers :before_create / :after_create type callbacks
44
52
  # @return [String] Returns the key for the inserted document
45
53
  def save(options={:validate => true})
46
- context = new_record? ? :create : :update
54
+ context = self.new_record? ? :create : :update
47
55
  return false if options[:validate] && !valid?(context)
48
56
 
49
57
  run_callbacks(context) do
50
- result = self.class.collection.insert(self)
58
+ if context == :create
59
+ key = self.class.persistence.insert(self)
60
+ else
61
+ key = self.class.persistence.update(self)
62
+ end
51
63
  self.persist!
52
- result
64
+ key
53
65
  end
54
66
  end
55
67
 
@@ -84,25 +96,14 @@ module Riagent
84
96
  end
85
97
 
86
98
  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
99
+ # Return all the documents in the collection
100
+ # @param [Integer] results_limit Number of results returned
101
+ # @return [Array|nil] of ActiveDocument instances
102
+ def all(results_limit=1000)
103
+ self.persistence.all(results_limit)
102
104
  end
103
105
 
104
- # Determines the document's persistence strategy
105
- # Valid options: [:riak_json]
106
+ # Set the document's persistence strategy
106
107
  # Usage:
107
108
  # <code>
108
109
  # class SomeModel
@@ -111,55 +112,50 @@ module Riagent
111
112
  # end
112
113
  # </code>
113
114
  def collection_type(coll_type)
115
+ unless COLLECTION_TYPES.include? coll_type
116
+ raise ArgumentError, "Invalid collection type: #{coll_type.to_s}"
117
+ end
114
118
  @collection_type = coll_type
115
119
  case @collection_type
116
120
  when :riak_json
117
- self.persistence_strategy = :riak_json
118
- include Riagent::Persistence::RiakJsonStrategy
121
+ self.persistence = Riagent::Persistence::RiakJsonStrategy.new(self)
122
+ when :riak_no_index
123
+ self.persistence = Riagent::Persistence::RiakNoIndexStrategy.new(self)
119
124
  end
120
125
  end
121
126
 
122
127
  # Load a document by key.
123
128
  def find(key)
124
129
  return nil if key.nil? or key.empty?
125
- doc = self.collection.find_by_key(key)
126
- self.from_rj_document(doc, persisted=true)
130
+ self.persistence.find(key)
127
131
  end
128
132
 
129
133
  # Return the first document that matches the query
130
134
  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)
135
+ unless self.persistence.allows_query?
136
+ raise NotImplementedError, "This collection type does not support querying"
137
137
  end
138
+ self.persistence.find_one(query)
138
139
  end
139
140
 
140
141
  def get_collection_type
141
142
  @collection_type ||= nil
142
143
  end
143
144
 
144
- def persistence_strategy
145
- @persistence_strategy ||= nil
145
+ def persistence
146
+ @persistence ||= nil
146
147
  end
147
148
 
148
- def persistence_strategy=(strategy)
149
- @persistence_strategy = strategy
149
+ def persistence=(persistence_strategy)
150
+ @persistence = persistence_strategy
150
151
  end
151
152
 
152
153
  # Return all documents that match the query
153
154
  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
155
+ unless self.persistence.allows_query?
156
+ raise NotImplementedError, "This collection type does not support querying"
162
157
  end
158
+ self.persistence.where(query)
163
159
  end
164
160
  end
165
161
  end
@@ -0,0 +1,37 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) "2014" Dmitri Zagidulin
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
+
23
+ module Riagent
24
+ module Persistence
25
+ # Riagent document persistence strategy
26
+ class PersistenceStrategy
27
+ attr_accessor :client
28
+ attr_accessor :collection_name
29
+ attr_accessor :model_class
30
+
31
+ def initialize(model_class)
32
+ self.model_class = model_class
33
+ self.collection_name = model_class.collection_name
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,5 +1,5 @@
1
- ## -------------------------------------------------------------------
2
- ##
1
+ ## -------------------------------------------------------------------
2
+ ##
3
3
  ## Copyright (c) "2014" Dmitri Zagidulin and Basho Technologies, Inc.
4
4
  ##
5
5
  ## This file is provided to you under the Apache License,
@@ -19,42 +19,101 @@
19
19
  ## -------------------------------------------------------------------
20
20
 
21
21
  require "riak_json"
22
- require "active_support/concern"
22
+ require "riagent/persistence/persistence_strategy"
23
23
 
24
24
  module Riagent
25
25
  module Persistence
26
- module RiakJsonStrategy
27
- extend ActiveSupport::Concern
26
+ class RiakJsonStrategy < PersistenceStrategy
27
+ attr_writer :collection
28
+
29
+ # Return all the documents in the collection
30
+ # @param [Integer] results_limit Number of results returned
31
+ # @return [Array|nil] of ActiveDocument instances
32
+ def all(results_limit=1000)
33
+ result = self.collection.all(results_limit)
34
+ if result.present?
35
+ result.documents.map do |doc|
36
+ self.from_rj_document(doc, persisted=true)
37
+ end
38
+ end
39
+ end
40
+
41
+ # @return [Boolean] Does this persistence strategy support querying?
42
+ def allows_query?
43
+ true
44
+ end
45
+
46
+ # @return [RiakJson::Client] RiakJson client for this persistence strategy (lazy initialize)
47
+ def client
48
+ @client ||= Riagent.riak_json_client # See lib/configuration.rb
49
+ end
50
+
51
+ # @return [RiakJson::Collection] instance for this persistence strategy (lazy initialize)
52
+ def collection
53
+ @collection ||= self.client.collection(self.collection_name)
54
+ end
55
+
56
+ # Fetch a document by key.
57
+ # @param [String] key
58
+ # @return [ActiveDocument|nil]
59
+ def find(key)
60
+ return nil if key.nil? or key.empty?
61
+ doc = self.collection.find_by_key(key)
62
+ self.from_rj_document(doc, persisted=true)
63
+ end
28
64
 
29
- module ClassMethods
30
- def client
31
- @client ||= Riagent.riak_json_client
65
+ # Return the first document that matches the query
66
+ # @param [String] query RiakJson query, in JSON string form
67
+ def find_one(query)
68
+ if query.kind_of? Hash
69
+ query = query.to_json
32
70
  end
33
-
34
- def client=(client)
35
- @client = client
71
+ doc = self.collection.find_one(query)
72
+ if doc.present?
73
+ self.from_rj_document(doc, persisted=true)
36
74
  end
37
-
38
- # Returns a RiakJson::Collection instance for this document
39
- def collection
40
- @collection ||= self.client.collection(self.collection_name)
75
+ end
76
+
77
+ # Converts from a RiakJson::Document instance to an instance of ActiveDocument
78
+ # @return [ActiveDocument|nil] ActiveDocument instance, or nil if the Document is nil
79
+ def from_rj_document(doc, persisted=false)
80
+ return nil if doc.nil?
81
+ active_doc_instance = self.model_class.instantiate(doc.attributes)
82
+ active_doc_instance.key = doc.key
83
+ if persisted
84
+ active_doc_instance.persist! # Mark as persisted / not new
41
85
  end
42
-
43
- # Sets the RiakJson::Collection instance for this document
44
- def collection=(collection_obj)
45
- @collection = collection_obj
86
+ active_doc_instance
87
+ end
88
+
89
+ # @param [RiakJson::ActiveDocument] doc Document to be inserted
90
+ # @return [Integer] Document key
91
+ def insert(doc)
92
+ self.collection.insert(doc)
93
+ end
94
+
95
+ # @param [RiakJson::ActiveDocument] doc Document to be deleted
96
+ def remove(doc)
97
+ self.collection.remove(doc)
98
+ end
99
+
100
+ # @param [RiakJson::ActiveDocument] doc Document to be updated
101
+ # @return [Integer] Document key
102
+ def update(doc)
103
+ self.collection.update(doc)
104
+ end
105
+
106
+ # Return all documents that match the query
107
+ # @param [String] query RiakJson query, in JSON string form
108
+ def where(query)
109
+ if query.kind_of? Hash
110
+ query = query.to_json
46
111
  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
112
+ result = self.collection.find_all(query)
113
+ if result.present?
114
+ result.documents.map do |doc|
115
+ self.from_rj_document(doc, persisted=true)
56
116
  end
57
- active_doc_instance
58
117
  end
59
118
  end
60
119
  end
@@ -0,0 +1,122 @@
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"
22
+ require "riagent/persistence/persistence_strategy"
23
+
24
+ module Riagent
25
+ module Persistence
26
+ class RiakNoIndexStrategy < PersistenceStrategy
27
+ attr_writer :bucket
28
+
29
+ # Return all the documents in the collection.
30
+ # Since this is a "no index" strategy, this can only be done via a streaming list keys
31
+ # @param [Integer] results_limit Number of results returned (currently ignored)
32
+ # @return [Array<Riagent::ActiveDocument>] List of ActiveDocument instances
33
+ def all(results_limit)
34
+ self.bucket.keys.inject([]) do |acc, k|
35
+ obj = self.find(k)
36
+ obj ? acc << obj : acc
37
+ end
38
+ end
39
+
40
+ # @return [Boolean] Does this persistence strategy support querying?
41
+ def allows_query?
42
+ false
43
+ end
44
+
45
+ # @return [Riak::Bucket] Riak bucket associated with this model/collection
46
+ def bucket
47
+ @bucket ||= self.client.bucket(self.collection_name)
48
+ end
49
+
50
+ # @return [Riak::Client] Riak client (lazy-initialized, cached in current Thread)
51
+ def client
52
+ @client ||= Riagent.riak_client # See lib/configuration.rb
53
+ end
54
+
55
+ # Fetch a document by key.
56
+ # @param [String] key
57
+ # @return [ActiveDocument|nil]
58
+ def find(key)
59
+ begin
60
+ result = self.bucket.get(key)
61
+ rescue Riak::FailedRequest => fr
62
+ if fr.not_found?
63
+ result = nil
64
+ else
65
+ raise fr
66
+ end
67
+ end
68
+ self.from_riak_object(result)
69
+ end
70
+
71
+ # Converts from a Riak::RObject instance to an instance of ActiveDocument
72
+ # @param [Riak::RObject] riak_object
73
+ # @param [Boolean] persisted Mark the document as persisted/not new?
74
+ # @return [ActiveDocument|nil] ActiveDocument instance, or nil if the Riak Object is nil
75
+ def from_riak_object(riak_object, persisted=true)
76
+ return nil if riak_object.nil?
77
+ active_doc_instance = self.model_class.from_json(riak_object.raw_data, riak_object.key)
78
+ if persisted
79
+ active_doc_instance.persist! # Mark as persisted / not new
80
+ end
81
+ active_doc_instance.source_object = riak_object
82
+ active_doc_instance
83
+ end
84
+
85
+ # @param [RiakJson::ActiveDocument] document Document to be inserted
86
+ # @return [Integer] Document key
87
+ def insert(document)
88
+ if document.key.present?
89
+ # Attempt to fetch existing object, just in case
90
+ riak_object = self.bucket.get_or_new(document.key)
91
+ else
92
+ riak_object = self.new_riak_object()
93
+ end
94
+ riak_object.raw_data = document.to_json_document
95
+ riak_object = riak_object.store
96
+ document.source_object = riak_object # store the riak object in document
97
+ document.key = riak_object.key
98
+ end
99
+
100
+ # @param [String|nil] Optional key
101
+ # @return [Riak::RObject] New Riak object instance for this model/collection
102
+ def new_riak_object(key=nil)
103
+ Riak::RObject.new(self.bucket, key).tap do |obj|
104
+ obj.content_type = "application/json"
105
+ end
106
+ end
107
+
108
+ # Deletes the riak object that stores the document
109
+ # @param [RiakJson::ActiveDocument] document Document to be deleted
110
+ def remove(document)
111
+ self.new_riak_object(document.key).delete
112
+ document.source_object = nil
113
+ end
114
+
115
+ # @param [RiakJson::ActiveDocument] document Document to be updated
116
+ # @return [Integer] Document key
117
+ def update(document)
118
+ self.insert(document)
119
+ end
120
+ end
121
+ end
122
+ end
@@ -52,7 +52,7 @@ module Riagent
52
52
  # SampleModel.save_solr_schema()
53
53
  # </code>
54
54
  def save_solr_schema
55
- self.collection.set_schema(self.schema)
55
+ self.persistence.collection.set_schema(self.schema)
56
56
  end
57
57
  end
58
58
  end
@@ -19,5 +19,5 @@
19
19
  ## -------------------------------------------------------------------
20
20
 
21
21
  module Riagent
22
- VERSION = "0.0.1"
22
+ VERSION = "0.0.2"
23
23
  end
@@ -0,0 +1,30 @@
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
+ class UserPreference
22
+ include Riagent::ActiveDocument
23
+
24
+ collection_type :riak_no_index # Persist to a plain Riak bucket (k/v only)
25
+
26
+ # Explicit attributes
27
+ # (key is an implied attribute, present in all ActiveDocument instances)
28
+ attribute :email_ok, Boolean, default: true
29
+ attribute :email_format, String, default: 'txt'
30
+ end
@@ -0,0 +1,52 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) "2014" Dmitri Zagidulin
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 'test_helper'
22
+
23
+ describe "RiakNoIndexStrategy persistence" do
24
+ it "can save an ActiveDocument to a Riak object" do
25
+ # First, save the object to Riak
26
+ user_pref = UserPreference.new email_format: 'html'
27
+ generated_key = user_pref.save
28
+ generated_key.wont_be_empty
29
+ assert user_pref.persisted?
30
+ user_pref.source_object.must_be_kind_of Riak::RObject
31
+
32
+ # Test all() / List Keys operation. (Obviously not recommended in production)
33
+ all_docs = UserPreference.all()
34
+ all_docs[0].must_be_kind_of UserPreference
35
+
36
+ # Now read the object back
37
+ fetched_pref = UserPreference.find(generated_key)
38
+ fetched_pref.must_be_kind_of UserPreference
39
+ fetched_pref.key.must_equal generated_key
40
+ fetched_pref.email_format.must_equal 'html'
41
+ fetched_pref.source_object.must_be_kind_of Riak::RObject
42
+
43
+ # Update the object
44
+ fetched_pref.update(email_format: 'pdf')
45
+ updated_pref = fetched_pref = UserPreference.find(generated_key)
46
+ updated_pref.email_format.must_equal 'pdf'
47
+
48
+ # Delete the object (clean up)
49
+ fetched_pref.destroy
50
+ assert fetched_pref.destroyed?
51
+ end
52
+ end
data/test/test_helper.rb CHANGED
@@ -24,10 +24,12 @@ require 'riagent'
24
24
  require 'examples/models/address_book'
25
25
  require 'examples/models/contact'
26
26
  require 'examples/models/user'
27
+ require 'examples/models/user_preference'
27
28
 
28
29
  # Set this to silence "[deprecated] I18n.enforce_available_locales will default to true in the future." warnings
29
30
  I18n.config.enforce_available_locales = true
30
31
 
31
32
  # Load config file and set up the relevant clients for integration testing
33
+ Riak.disable_list_keys_warnings = true
32
34
  Riagent.load_config_file('test/config/riak.yml')
33
35
  Riagent.init_clients(:test) # Set up the client for the test environment
@@ -23,7 +23,7 @@ require 'active_model/lint'
23
23
 
24
24
  # Runs the ActiveModel::Lint test suite, to make sure a model fits the ActiveModel API
25
25
  # See http://yehudakatz.com/2010/01/10/activemodel-make-any-ruby-object-feel-like-activerecord/
26
- class ActiveModelLintTest < MiniTest::Test
26
+ class ActiveModelLintTest < Minitest::Unit::TestCase
27
27
  include ActiveModel::Lint::Tests
28
28
 
29
29
  def setup
@@ -63,15 +63,15 @@ describe "Riagent::Document has_one association" do
63
63
  mock_loaded_address_book = AddressBook.new
64
64
  mock_loaded_address_book.key = 'test-book-123'
65
65
 
66
- AddressBook.collection = MiniTest::Mock.new
67
- AddressBook.collection.expect :find_by_key, mock_loaded_address_book, ['test-book-123']
66
+ AddressBook.persistence = MiniTest::Mock.new
67
+ AddressBook.persistence.expect :find, mock_loaded_address_book, ['test-book-123']
68
68
 
69
69
  # Calling user.address_book should lazy-load via the target collection.find_by_key()
70
70
  user.address_book
71
- AddressBook.collection.verify
71
+ AddressBook.persistence.verify
72
72
 
73
73
  # Reset
74
- AddressBook.collection = nil
74
+ AddressBook.persistence = nil
75
75
  end
76
76
 
77
77
  it "adds a build_<target> method" do
@@ -28,10 +28,18 @@ describe "Riagent" do
28
28
  Riagent.must_respond_to :init_clients
29
29
  Riagent.must_respond_to :init_riak_json_client
30
30
  Riagent.must_respond_to :riak_json_client
31
+ Riagent.must_respond_to :init_riak_client
32
+ Riagent.must_respond_to :riak_client
31
33
  end
32
34
 
33
35
  it "initializes a RiakJson client" do
34
36
  # This should have been initialized from config file in test_helper.rb
35
37
  Riagent.riak_json_client.must_be_kind_of RiakJson::Client
36
38
  end
39
+
40
+ it "initializes a Riak ruby client" do
41
+ # This should have been initialized from config file in test_helper.rb
42
+ Riagent.riak_client.must_be_kind_of Riak::Client
43
+ Riagent.riak_client.protocol.must_equal 'pbc'
44
+ end
37
45
  end
@@ -21,43 +21,66 @@
21
21
  require 'test_helper'
22
22
 
23
23
  describe "a Riagent::ActiveDocument that persists to RiakJson" do
24
+ it "#model persistence instance methods" do
25
+ user = User.new
26
+
27
+ # Adding the line +collection_type :riak_json+ to a model
28
+ # exposes the usual array of persistence methods
29
+ user.must_respond_to :save
30
+ user.must_respond_to :save!
31
+ user.must_respond_to :update
32
+ user.must_respond_to :update_attributes # alias for update()
33
+ user.must_respond_to :update!
34
+ user.must_respond_to :destroy
35
+ end
36
+
37
+ it "#model persistence class methods" do
38
+ User.must_respond_to :all
39
+ User.must_respond_to :find
40
+ User.must_respond_to :find_one
41
+ User.must_respond_to :where
42
+ end
43
+
24
44
  it "saves via collection.insert()" do
25
45
  user = User.new
26
- User.collection = MiniTest::Mock.new
27
- User.collection.expect :insert, nil, [user]
46
+ User.persistence.collection = MiniTest::Mock.new
47
+ User.persistence.collection.expect :insert, nil, [user]
28
48
 
29
49
  # Calling model.save() should result in a collection.insert() call
30
50
  user.save({:validate => false})
31
- User.collection.verify
51
+ User.persistence.collection.verify
32
52
 
33
53
  # Reset
34
- User.collection = nil
54
+ User.persistence.collection = nil
35
55
  end
36
56
 
37
57
  it "updates via collection.update()" do
38
58
  user = User.new username: 'TestUserInitial'
39
- User.collection = MiniTest::Mock.new
40
- User.collection.expect :insert, nil, [user]
59
+ user.persist! # Updates only make sense for a persisted document
60
+ User.persistence.collection = MiniTest::Mock.new
61
+ User.persistence.collection.expect :update, nil, [user]
41
62
 
42
63
  # model.update() is implemented as a save() call (with updated attributes)
43
64
  user.update({ username: 'TestUserNewName'} )
44
- User.collection.verify
65
+ User.persistence.collection.verify
45
66
 
46
67
  # Reset
47
- User.collection = nil
68
+ User.persistence.collection = nil
48
69
  end
49
70
 
50
71
  it "destroys via collection.remove()" do
51
72
  user = User.new
52
- User.collection = MiniTest::Mock.new
53
- User.collection.expect :remove, nil, [user]
73
+ user.key = 'user123'
74
+ user.persist! # Remove can only be called on persisted objects that have a key
75
+ User.persistence.collection = MiniTest::Mock.new
76
+ User.persistence.collection.expect :remove, nil, [user]
54
77
 
55
78
  # Calling model.destroy() should result in a collection.remove() call
56
79
  user.destroy
57
- User.collection.verify
80
+ User.persistence.collection.verify
58
81
 
59
82
  # Reset
60
- User.collection = nil
83
+ User.persistence.collection = nil
61
84
  end
62
85
 
63
86
  it "returns nil when doing a find() for nil or empty key" do
@@ -67,52 +90,52 @@ describe "a Riagent::ActiveDocument that persists to RiakJson" do
67
90
 
68
91
  it "performs a find() via collection.find_by_key()" do
69
92
  test_key = 'user123'
70
- User.collection = MiniTest::Mock.new
71
- User.collection.expect :find_by_key, nil, [test_key]
93
+ User.persistence.collection = MiniTest::Mock.new
94
+ User.persistence.collection.expect :find_by_key, nil, [test_key]
72
95
 
73
96
  # Calling Model class find() should result in a collection.find_by_key()
74
97
  User.find(test_key)
75
- User.collection.verify
98
+ User.persistence.collection.verify
99
+
100
+ # Reset
101
+ User.persistence.collection = nil
102
+ end
103
+
104
+ it "performs an all() listing via collection.all()" do
105
+ User.persistence.collection = MiniTest::Mock.new
106
+ User.persistence.collection.expect :all, [], [1000] # default results limit of 1000
107
+
108
+ # Calling Model class where() should result in a collection.all()
109
+ User.all()
110
+ User.persistence.collection.verify
76
111
 
77
112
  # Reset
78
- User.collection = nil
113
+ User.persistence.collection = nil
79
114
  end
80
115
 
81
116
  it "performs a where() via collection.find_all()" do
82
- User.collection = MiniTest::Mock.new
117
+ User.persistence.collection = MiniTest::Mock.new
83
118
  query = { country: 'USA' }
84
- User.collection.expect :find_all, [], [query.to_json]
119
+ User.persistence.collection.expect :find_all, [], [query.to_json]
85
120
 
86
121
  # Calling Model class where() should result in a collection.find_all()
87
122
  User.where(query)
88
- User.collection.verify
123
+ User.persistence.collection.verify
89
124
 
90
125
  # Reset
91
- User.collection = nil
126
+ User.persistence.collection = nil
92
127
  end
93
128
 
94
129
  it "performs a find_one() via collection.find_one()" do
95
- User.collection = MiniTest::Mock.new
130
+ User.persistence.collection = MiniTest::Mock.new
96
131
  query = { username: 'TestUser' }
97
- User.collection.expect :find_one, [], [query.to_json]
132
+ User.persistence.collection.expect :find_one, [], [query.to_json]
98
133
 
99
134
  # Calling Model class find_one() should result in a collection.find_one()
100
135
  User.find_one(query)
101
- User.collection.verify
102
-
103
- # Reset
104
- User.collection = nil
105
- end
106
-
107
- it "performs an all_for_field() via collection.find_all()" do
108
- User.collection = MiniTest::Mock.new
109
- User.collection.expect :find_all, [], [String]
110
-
111
- # Calling Model class all_for_field() should result in a collection.find_all()
112
- User.all_for_field(:username)
113
- User.collection.verify
136
+ User.persistence.collection.verify
114
137
 
115
138
  # Reset
116
- User.collection = nil
139
+ User.persistence.collection = nil
117
140
  end
118
141
  end
@@ -0,0 +1,41 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) "2014" Dmitri Zagidulin
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 'test_helper'
22
+
23
+ describe "a Riagent::ActiveDocument that persists via RiakNoIndex strategy" do
24
+ it "#model persistence instance methods" do
25
+ user_pref = UserPreference.new
26
+
27
+ # Adding the line +collection_type :riak_no_index+ to a model
28
+ # exposes the usual array of persistence methods
29
+ user_pref.must_respond_to :save
30
+ user_pref.must_respond_to :save!
31
+ user_pref.must_respond_to :update
32
+ user_pref.must_respond_to :update_attributes # alias for update()
33
+ user_pref.must_respond_to :update!
34
+ user_pref.must_respond_to :destroy
35
+ end
36
+
37
+ it "#model persistence class methods" do
38
+ UserPreference.must_respond_to :all
39
+ UserPreference.must_respond_to :find
40
+ end
41
+ end
@@ -1,5 +1,5 @@
1
- ## -------------------------------------------------------------------
2
- ##
1
+ ## -------------------------------------------------------------------
2
+ ##
3
3
  ## Copyright (c) "2014" Dmitri Zagidulin and Basho Technologies, Inc.
4
4
  ##
5
5
  ## This file is provided to you under the Apache License,
@@ -21,37 +21,40 @@
21
21
  require 'test_helper'
22
22
 
23
23
  describe "a Riagent::ActiveDocument has Persistence options" do
24
- context "via collection_type :riak_json" do
25
- it "#model class methods" do
26
- # Adding the line +collection_type :riak_json+ to a model
27
- # means that it will be persisted to a RiakJson::Collection
28
- User.get_collection_type.must_equal :riak_json
29
- User.persistence_strategy.must_equal :riak_json
30
-
31
- # It also grants access to a RiakJson::Client instance, to the model class
32
- User.client.must_be_kind_of RiakJson::Client
33
-
34
- User.collection.must_be_kind_of RiakJson::Collection
35
- User.collection_name.must_equal 'users'
36
- end
37
-
38
- it "#model persistence instance methods" do
39
- user = User.new
40
-
41
- # Adding the line +collection_type :riak_json+ to a model
42
- # exposes the usual array of persistence methods
43
- user.must_respond_to :save
44
- user.must_respond_to :save!
45
- user.must_respond_to :update
46
- user.must_respond_to :update_attributes # alias for update()
47
- user.must_respond_to :update!
48
- user.must_respond_to :destroy
49
- end
50
-
51
- it "#model persistence class methods" do
52
- User.must_respond_to :find
53
- User.must_respond_to :find_one
54
- User.must_respond_to :where
55
- end
24
+ it "can only persist to valid collection types" do
25
+ lambda { User.collection_type :invalid }.must_raise ArgumentError
26
+ end
27
+
28
+ it "#:riak_json collection_type" do
29
+ # Adding the line +collection_type :riak_json+ to a model
30
+ # means that it will be persisted to a RiakJson::Collection
31
+ User.get_collection_type.must_equal :riak_json
32
+ User.persistence.must_be_kind_of Riagent::Persistence::RiakJsonStrategy
33
+
34
+ # It also grants access to a RiakJson::Client instance, to the model class
35
+ User.persistence.client.must_be_kind_of RiakJson::Client
36
+
37
+ User.persistence.collection.must_be_kind_of RiakJson::Collection
38
+ User.persistence.collection_name.must_equal 'users'
39
+
40
+ # Check to see if the RiakJson persistence strategy supports querying
41
+ assert User.persistence.allows_query?
42
+ end
43
+
44
+ it "#:riak_no_index collection type" do
45
+ # Adding the line +collection_type :riak_no_index+ to a model
46
+ # means that it will be persisted as a Riak object with no indices (k/v operations only)
47
+ UserPreference.get_collection_type.must_equal :riak_no_index
48
+ UserPreference.persistence.must_be_kind_of Riagent::Persistence::RiakNoIndexStrategy
49
+
50
+ # It also grants access to a RiakJson::Client instance, to the model class
51
+ UserPreference.persistence.client.must_be_kind_of Riak::Client
52
+
53
+ UserPreference.persistence.collection_name.must_equal 'user_preferences'
54
+ UserPreference.persistence.bucket.must_be_kind_of Riak::Bucket
55
+
56
+ refute UserPreference.persistence.allows_query?, "RiakNoIndex strategy does not allow querying"
57
+ lambda { UserPreference.where({}) }.must_raise NotImplementedError, "RiakNoIndex strategy does not support querying"
58
+ lambda { UserPreference.find_one({}) }.must_raise NotImplementedError, "RiakNoIndex strategy does not support querying"
56
59
  end
57
60
  end
@@ -16,11 +16,14 @@ describe "an Active Document" do
16
16
 
17
17
  it "can save the Solr indexing schema to RiakJson" do
18
18
  schema = User.schema
19
- User.collection = MiniTest::Mock.new
19
+ User.persistence.collection = MiniTest::Mock.new
20
20
 
21
21
  # Ensure that calling User.save_solr_schema() results in a call to collection.set_schema()
22
- User.collection.expect :set_schema, nil, [RiakJson::CollectionSchema]
22
+ User.persistence.collection.expect :set_schema, nil, [RiakJson::CollectionSchema]
23
23
  User.save_solr_schema
24
- User.collection.verify
24
+ User.persistence.collection.verify
25
+
26
+ # Reset
27
+ User.persistence.collection = nil
25
28
  end
26
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riagent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitri Zagidulin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-01 00:00:00.000000000 Z
11
+ date: 2014-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: riak_json
@@ -159,7 +159,9 @@ files:
159
159
  - lib/riagent/conversion.rb
160
160
  - lib/riagent/errors.rb
161
161
  - lib/riagent/persistence.rb
162
+ - lib/riagent/persistence/persistence_strategy.rb
162
163
  - lib/riagent/persistence/riak_json_strategy.rb
164
+ - lib/riagent/persistence/riak_no_index_strategy.rb
163
165
  - lib/riagent/railtie.rb
164
166
  - lib/riagent/search_schema.rb
165
167
  - lib/riagent/version.rb
@@ -169,7 +171,9 @@ files:
169
171
  - test/examples/models/blog_post.rb
170
172
  - test/examples/models/contact.rb
171
173
  - test/examples/models/user.rb
172
- - test/integration/persistence_integration_test.rb
174
+ - test/examples/models/user_preference.rb
175
+ - test/integration/persistence_riak_json_integration_test.rb
176
+ - test/integration/persistence_riak_no_index_integration_test.rb
173
177
  - test/seeds.rb
174
178
  - test/test_helper.rb
175
179
  - test/unit/active_document_test.rb
@@ -179,6 +183,7 @@ files:
179
183
  - test/unit/config_test.rb
180
184
  - test/unit/embedded_test.rb
181
185
  - test/unit/persistence_riak_json_test.rb
186
+ - test/unit/persistence_riak_no_index_test.rb
182
187
  - test/unit/persistence_test.rb
183
188
  - test/unit/search_schema_test.rb
184
189
  - test/unit/validation_test.rb
@@ -212,7 +217,9 @@ test_files:
212
217
  - test/examples/models/blog_post.rb
213
218
  - test/examples/models/contact.rb
214
219
  - test/examples/models/user.rb
215
- - test/integration/persistence_integration_test.rb
220
+ - test/examples/models/user_preference.rb
221
+ - test/integration/persistence_riak_json_integration_test.rb
222
+ - test/integration/persistence_riak_no_index_integration_test.rb
216
223
  - test/seeds.rb
217
224
  - test/test_helper.rb
218
225
  - test/unit/active_document_test.rb
@@ -222,6 +229,7 @@ test_files:
222
229
  - test/unit/config_test.rb
223
230
  - test/unit/embedded_test.rb
224
231
  - test/unit/persistence_riak_json_test.rb
232
+ - test/unit/persistence_riak_no_index_test.rb
225
233
  - test/unit/persistence_test.rb
226
234
  - test/unit/search_schema_test.rb
227
235
  - test/unit/validation_test.rb