right_support 1.1.2 → 1.2.0
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.
- data/README.rdoc +38 -14
- data/lib/right_support.rb +1 -1
- data/lib/right_support/crypto/signed_hash.rb +11 -2
- data/lib/right_support/db.rb +1 -3
- data/lib/right_support/db/cassandra_model.rb +299 -18
- data/lib/right_support/log.rb +4 -0
- data/lib/right_support/log/exception_logger.rb +86 -0
- data/lib/right_support/log/filter_logger.rb +75 -0
- data/lib/right_support/log/mixin.rb +104 -0
- data/lib/right_support/log/multiplexer.rb +93 -0
- data/lib/right_support/log/null_logger.rb +76 -0
- data/lib/right_support/net.rb +5 -3
- data/lib/right_support/net/balancing/health_check.rb +40 -23
- data/lib/right_support/net/request_balancer.rb +19 -32
- data/lib/right_support/rack.rb +2 -3
- data/lib/right_support/rack/custom_logger.rb +29 -8
- data/lib/right_support/rack/request_logger.rb +113 -0
- data/lib/right_support/ruby.rb +4 -3
- data/lib/right_support/ruby/easy_singleton.rb +24 -0
- data/lib/right_support/ruby/object_extensions.rb +18 -2
- data/lib/right_support/ruby/string_extensions.rb +120 -0
- data/lib/right_support/stats.rb +34 -0
- data/lib/right_support/stats/activity.rb +206 -0
- data/lib/right_support/stats/exceptions.rb +96 -0
- data/lib/right_support/stats/helpers.rb +438 -0
- data/lib/right_support/validation.rb +2 -4
- data/right_support.gemspec +3 -5
- metadata +18 -20
data/README.rdoc
CHANGED
@@ -24,11 +24,22 @@ or where the log entries go.
|
|
24
24
|
my_logger = MyAwesomeLogger.new
|
25
25
|
use RightSupport::Rack::CustomLogger, Logger::INFO, my_logger
|
26
26
|
|
27
|
-
|
27
|
+
=== String Manipulation
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
StringExtensions contains String#camelize, which is only defined if the
|
30
|
+
ActiveSupport gem cannot be loaded. It also has some RightScale-specific
|
31
|
+
methods:
|
32
|
+
* String#snake_case
|
33
|
+
* String#to_const
|
34
|
+
* String#to_const_path
|
35
|
+
|
36
|
+
Net::StringEncoder applies and removes URL-escape, base64 and other encodings.
|
37
|
+
|
38
|
+
=== Input Validation
|
39
|
+
|
40
|
+
Validation contains several format-checkers that can be used to validate your
|
41
|
+
web app's models before saving, check for preconditions in your controllers,
|
42
|
+
and so forth.
|
32
43
|
|
33
44
|
You can use it as a mixin by including the appropriate child module of
|
34
45
|
RightSupport::Validation.
|
@@ -48,10 +59,10 @@ but does not pollute the dispatch table of your application classes.
|
|
48
59
|
the_key = STDIN.read
|
49
60
|
raise ArgumentError unless RightSupport::Validation.ssh_public_key?(the_key)
|
50
61
|
|
51
|
-
|
62
|
+
=== Client-Side Load Balancer
|
52
63
|
|
53
|
-
|
54
|
-
|
64
|
+
RequestBalancer randomly chooses endpoints for a network request, which lets
|
65
|
+
you perform easy client-side load balancing:
|
55
66
|
|
56
67
|
include RightSupport::Net
|
57
68
|
|
@@ -61,19 +72,17 @@ which lets you perform easy client-side load balancing:
|
|
61
72
|
end
|
62
73
|
|
63
74
|
The balancer will keep trying requests until one of them succeeds without throwing
|
64
|
-
any exceptions. (NB: a nil return value counts as success!!)
|
65
|
-
certain class of exception is "fatal," then that exception will cause REST to re-
|
66
|
-
raise immediately
|
75
|
+
any exceptions. (NB: a nil return value counts as success!!)
|
67
76
|
|
68
|
-
|
77
|
+
=== HTTP Client
|
69
78
|
|
70
79
|
We provide a very thin wrapper around the rest-client gem that enables simple but
|
71
80
|
robust rest requests with a timeout, headers, etc.
|
72
81
|
|
73
|
-
|
74
|
-
|
82
|
+
HTTPClient is interface-compatible with the RestClient module, but allows an
|
83
|
+
optional timeout to be specified as an extra parameter.
|
75
84
|
|
76
|
-
# Create a wrapper
|
85
|
+
# Create a wrapper object
|
77
86
|
@client = RightSupport::Net::HTTPClient.new
|
78
87
|
|
79
88
|
# Default timeout is 5 seconds
|
@@ -82,3 +91,18 @@ module, but allows an optional timeout to be specified as an extra parameter.
|
|
82
91
|
# Make sure the HTTPClient request fails after 1 second so we can report an error
|
83
92
|
# and move on!
|
84
93
|
@client.get('http://localhost', {:headers => {'X-Hello'=>'hi!'}, :timeout => 1)}
|
94
|
+
|
95
|
+
=== Statistics Gathering
|
96
|
+
|
97
|
+
Profile your compute-heavy and network activities using a Stats::Activity counter.
|
98
|
+
|
99
|
+
stats = RightSupport::Stats::Activity.new
|
100
|
+
|
101
|
+
puts 'enter 5 lines:'
|
102
|
+
5.times do
|
103
|
+
stats.update(:read_input)
|
104
|
+
line = STDIN.readline
|
105
|
+
stats.finish
|
106
|
+
end
|
107
|
+
|
108
|
+
puts "Only %.1f lines/sec? You are a slow typist!" % [stats.avg_rate]
|
data/lib/right_support.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
# Namespaces for RightSupport
|
2
1
|
require 'right_support/ruby'
|
3
2
|
require 'right_support/crypto'
|
4
3
|
require 'right_support/db'
|
5
4
|
require 'right_support/log'
|
6
5
|
require 'right_support/net'
|
7
6
|
require 'right_support/rack'
|
7
|
+
require 'right_support/stats'
|
8
8
|
require 'right_support/validation'
|
@@ -1,10 +1,19 @@
|
|
1
|
-
require '
|
1
|
+
require 'digest/sha1'
|
2
2
|
|
3
3
|
module RightSupport::Crypto
|
4
4
|
class SignedHash
|
5
|
+
|
6
|
+
if require_succeeds?('yajl')
|
7
|
+
DefaultEncoding = ::Yajl
|
8
|
+
elsif require_succeeds?('json')
|
9
|
+
DefaultEncoding = ::JSON
|
10
|
+
else
|
11
|
+
DefaultEncoding = nil
|
12
|
+
end unless defined?(DefaultEncoding)
|
13
|
+
|
5
14
|
DEFAULT_OPTIONS = {
|
6
15
|
:digest => Digest::SHA1,
|
7
|
-
:encoding =>
|
16
|
+
:encoding => DefaultEncoding
|
8
17
|
}
|
9
18
|
|
10
19
|
def initialize(hash={}, options={})
|
data/lib/right_support/db.rb
CHANGED
@@ -1,8 +1,94 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
begin
|
24
|
+
require 'cassandra/0.8'
|
25
|
+
|
26
|
+
class Cassandra
|
27
|
+
module Protocol
|
28
|
+
# Monkey patch _get_indexed_slices so that it accepts list of columns when doing indexed
|
29
|
+
# slice, otherwise not able to get specific columns using secondary index lookup
|
30
|
+
def _get_indexed_slices(column_family, index_clause, columns, count, start, finish, reversed, consistency)
|
31
|
+
column_parent = CassandraThrift::ColumnParent.new(:column_family => column_family)
|
32
|
+
if columns
|
33
|
+
predicate = CassandraThrift::SlicePredicate.new(:column_names => [columns].flatten)
|
34
|
+
else
|
35
|
+
predicate = CassandraThrift::SlicePredicate.new(:slice_range =>
|
36
|
+
CassandraThrift::SliceRange.new(
|
37
|
+
:reversed => reversed,
|
38
|
+
:count => count,
|
39
|
+
:start => start,
|
40
|
+
:finish => finish))
|
41
|
+
end
|
42
|
+
client.get_indexed_slices(column_parent, index_clause, predicate, consistency)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Monkey patch get_indexed_slices so that it returns OrderedHash, otherwise cannot determine
|
47
|
+
# next start key when getting in chunks
|
48
|
+
def get_indexed_slices(column_family, index_clause, *columns_and_options)
|
49
|
+
return false if Cassandra.VERSION.to_f < 0.7
|
50
|
+
|
51
|
+
column_family, columns, _, options =
|
52
|
+
extract_and_validate_params(column_family, [], columns_and_options, READ_DEFAULTS.merge(:key_count => 100, :key_start => ""))
|
53
|
+
|
54
|
+
if index_clause.class != CassandraThrift::IndexClause
|
55
|
+
index_expressions = index_clause.collect do |expression|
|
56
|
+
create_index_expression(expression[:column_name], expression[:value], expression[:comparison])
|
57
|
+
end
|
58
|
+
|
59
|
+
index_clause = create_index_clause(index_expressions, options[:key_start], options[:key_count])
|
60
|
+
end
|
61
|
+
|
62
|
+
key_slices = _get_indexed_slices(column_family, index_clause, columns, options[:count], options[:start],
|
63
|
+
options[:finish], options[:reversed], options[:consistency])
|
64
|
+
|
65
|
+
key_slices.inject(OrderedHash.new){|h, key_slice| h[key_slice.key] = key_slice.columns; h}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
rescue LoadError => e
|
70
|
+
# Make sure we're dealing with a legitimate missing-file LoadError
|
71
|
+
raise e unless e.message =~ /^no such file to load/
|
72
|
+
# Missing 'cassandra/0.8' indicates that the cassandra gem is not installed; we can ignore this
|
73
|
+
end
|
74
|
+
|
1
75
|
module RightSupport::DB
|
76
|
+
|
77
|
+
# Base class for a column family in a keyspace
|
78
|
+
# Used to access data persisted in Cassandra
|
79
|
+
# Provides wrappers for Cassandra client methods
|
2
80
|
class CassandraModel
|
81
|
+
|
82
|
+
# Default timeout for client connection to Cassandra server
|
3
83
|
DEFAULT_TIMEOUT = 10
|
84
|
+
|
85
|
+
# Default maximum number of rows to retrieve in one chunk
|
86
|
+
DEFAULT_COUNT = 1000
|
87
|
+
|
88
|
+
# Wrappers for Cassandra client
|
4
89
|
class << self
|
5
|
-
|
90
|
+
|
91
|
+
@@logger = nil
|
6
92
|
@@conn = nil
|
7
93
|
|
8
94
|
attr_accessor :column_family
|
@@ -17,17 +103,22 @@ module RightSupport::DB
|
|
17
103
|
end
|
18
104
|
|
19
105
|
def logger=(l)
|
20
|
-
@@logger=l
|
106
|
+
@@logger = l
|
21
107
|
end
|
22
108
|
|
23
109
|
def logger
|
24
110
|
@@logger
|
25
111
|
end
|
26
|
-
|
112
|
+
|
27
113
|
def keyspace
|
28
114
|
@keyspace + "_" + (ENV['RACK_ENV'] || 'development')
|
29
115
|
end
|
30
116
|
|
117
|
+
# Client connected to Cassandra server
|
118
|
+
# Create connection if does not already exist
|
119
|
+
#
|
120
|
+
# === Return
|
121
|
+
# (Cassandra):: Client connected to server
|
31
122
|
def conn
|
32
123
|
return @@conn if @@conn
|
33
124
|
|
@@ -37,19 +128,49 @@ module RightSupport::DB
|
|
37
128
|
@@conn
|
38
129
|
end
|
39
130
|
|
40
|
-
|
41
|
-
|
131
|
+
# Get row(s) for specified key(s)
|
132
|
+
# Unless :count is specified, a maximum of 100 columns are retrieved
|
133
|
+
#
|
134
|
+
# === Parameters
|
135
|
+
# k(String|Array):: Individual primary key or list of keys on which to match
|
136
|
+
# opt(Hash):: Request options including :consistency and for column level
|
137
|
+
# control :count, :start, :finish, :reversed
|
138
|
+
#
|
139
|
+
# === Return
|
140
|
+
# (Object|nil):: Individual row, or nil if not found, or ordered hash of rows
|
141
|
+
def all(k, opt = {})
|
142
|
+
real_get(k, opt)
|
42
143
|
end
|
43
144
|
|
44
|
-
|
45
|
-
|
145
|
+
# Get row for specified primary key and convert into object of given class
|
146
|
+
# Unless :count is specified, a maximum of 100 columns are retrieved
|
147
|
+
#
|
148
|
+
# === Parameters
|
149
|
+
# key(String):: Primary key on which to match
|
150
|
+
# opt(Hash):: Request options including :consistency and for column level
|
151
|
+
# control :count, :start, :finish, :reversed
|
152
|
+
#
|
153
|
+
# === Return
|
154
|
+
# (CassandraModel|nil):: Instantiated object of given class, or nil if not found
|
155
|
+
def get(key, opt = {})
|
156
|
+
if (attrs = real_get(key, opt)).empty?
|
46
157
|
nil
|
47
158
|
else
|
48
|
-
new(key,
|
159
|
+
new(key, attrs)
|
49
160
|
end
|
50
161
|
end
|
51
162
|
|
52
|
-
|
163
|
+
# Get raw row(s) for specified primary key(s)
|
164
|
+
# Unless :count is specified, a maximum of 100 columns are retrieved
|
165
|
+
#
|
166
|
+
# === Parameters
|
167
|
+
# k(String|Array):: Individual primary key or list of keys on which to match
|
168
|
+
# opt(Hash):: Request options including :consistency and for column level
|
169
|
+
# control :count, :start, :finish, :reversed
|
170
|
+
#
|
171
|
+
# === Return
|
172
|
+
# (Cassandra::OrderedHash):: Individual row or OrderedHash of rows
|
173
|
+
def real_get(k, opt = {})
|
53
174
|
if k.is_a?(Array)
|
54
175
|
do_op(:multi_get, column_family, k, opt)
|
55
176
|
else
|
@@ -57,19 +178,132 @@ module RightSupport::DB
|
|
57
178
|
end
|
58
179
|
end
|
59
180
|
|
60
|
-
|
61
|
-
|
181
|
+
# Get all rows for specified secondary key
|
182
|
+
#
|
183
|
+
# === Parameters
|
184
|
+
# index(String):: Name of secondary index
|
185
|
+
# key(String):: Index value that each selected row is required to match
|
186
|
+
# columns(Array|nil):: Names of columns to be retrieved, defaults to all
|
187
|
+
# opt(Hash):: Request options with only :consistency used
|
188
|
+
#
|
189
|
+
# === Return
|
190
|
+
# (Array):: Rows retrieved with each member being an instantiated object of the
|
191
|
+
# given class as value, but object only contains values for the columns retrieved
|
192
|
+
def get_indexed(index, key, columns = nil, opt = {})
|
193
|
+
if rows = real_get_indexed(index, key, columns, opt)
|
194
|
+
rows.map do |key, columns|
|
195
|
+
attrs = columns.inject({}) { |a, c| a[c.column.name] = c.column.value; a }
|
196
|
+
new(key, attrs)
|
197
|
+
end
|
198
|
+
else
|
199
|
+
[]
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Get all raw rows for specified secondary key
|
204
|
+
#
|
205
|
+
# === Parameters
|
206
|
+
# index(String):: Name of secondary index
|
207
|
+
# key(String):: Index value that each selected row is required to match
|
208
|
+
# columns(Array|nil):: Names of columns to be retrieved, defaults to all
|
209
|
+
# opt(Hash):: Request options with only :consistency used
|
210
|
+
#
|
211
|
+
# === Return
|
212
|
+
# (Hash):: Rows retrieved with primary key as key and value being an array
|
213
|
+
# of CassandraThrift::ColumnOrSuperColumn with attributes :name, :timestamp,
|
214
|
+
# and :value
|
215
|
+
def real_get_indexed(index, key, columns = nil, opt = {})
|
216
|
+
rows = {}
|
217
|
+
start = ""
|
218
|
+
count = DEFAULT_COUNT
|
219
|
+
expr = do_op(:create_idx_expr, index, key, "EQ")
|
220
|
+
opt = opt[:consistency] ? {:consistency => opt[:consistency]} : {}
|
221
|
+
while true
|
222
|
+
clause = do_op(:create_idx_clause, [expr], start, count)
|
223
|
+
chunk = do_op(:get_indexed_slices, column_family, clause, columns, opt)
|
224
|
+
rows.merge!(chunk)
|
225
|
+
if chunk.size == count
|
226
|
+
# Assume there are more chunks, use last key as start of next get
|
227
|
+
start = chunk.keys.last
|
228
|
+
else
|
229
|
+
# This must be the last chunk
|
230
|
+
break
|
231
|
+
end
|
232
|
+
end
|
233
|
+
rows
|
234
|
+
end
|
235
|
+
|
236
|
+
# Get specific columns in row with specified key
|
237
|
+
#
|
238
|
+
# === Parameters
|
239
|
+
# key(String):: Primary key on which to match
|
240
|
+
# columns(Array):: Names of columns to be retrieved
|
241
|
+
# opt(Hash):: Request options such as :consistency
|
242
|
+
#
|
243
|
+
# === Return
|
244
|
+
# (Array):: Values of selected columns in the order specified
|
245
|
+
def get_columns(key, columns, opt = {})
|
246
|
+
do_op(:get_columns, column_family, key, columns, sub_columns = nil, opt)
|
247
|
+
end
|
248
|
+
|
249
|
+
# Insert a row for a key
|
250
|
+
#
|
251
|
+
# === Parameters
|
252
|
+
# key(String):: Primary key for value
|
253
|
+
# values(Hash):: Values to be stored
|
254
|
+
# opt(Hash):: Request options such as :consistency
|
255
|
+
#
|
256
|
+
# === Return
|
257
|
+
# (Array):: Mutation map and consistency level
|
258
|
+
def insert(key, values, opt={})
|
259
|
+
do_op(:insert, column_family, key, values, opt)
|
62
260
|
end
|
63
261
|
|
262
|
+
# Delete row or columns of row
|
263
|
+
#
|
264
|
+
# === Parameters
|
265
|
+
# args(Array):: Key, columns, options
|
266
|
+
#
|
267
|
+
# === Return
|
268
|
+
# (Array):: Mutation map and consistency level
|
64
269
|
def remove(*args)
|
65
270
|
do_op(:remove, column_family, *args)
|
66
271
|
end
|
67
272
|
|
68
|
-
|
273
|
+
# Open a batch operation and yield self
|
274
|
+
# Inserts and deletes are queued until the block closes,
|
275
|
+
# and then sent atomically to the server
|
276
|
+
# Supports :consistency option, which overrides that set
|
277
|
+
# in individual commands
|
278
|
+
#
|
279
|
+
# === Parameters
|
280
|
+
# args(Array):: Batch options such as :consistency
|
281
|
+
#
|
282
|
+
# === Block
|
283
|
+
# Required block making Cassandra requests
|
284
|
+
#
|
285
|
+
# === Returns
|
286
|
+
# (Array):: Mutation map and consistency level
|
287
|
+
#
|
288
|
+
# === Raise
|
289
|
+
# Exception:: If block not specified
|
290
|
+
def batch(*args, &block)
|
69
291
|
raise "Block required!" unless block_given?
|
70
|
-
do_op(:batch
|
292
|
+
do_op(:batch, *args, &block)
|
71
293
|
end
|
72
|
-
|
294
|
+
|
295
|
+
# Execute Cassandra request
|
296
|
+
# Automatically reconnect and retry if IOError encountered
|
297
|
+
#
|
298
|
+
# === Parameters
|
299
|
+
# meth(Symbol):: Method to be executed
|
300
|
+
# args(Array):: Method arguments
|
301
|
+
#
|
302
|
+
# === Block
|
303
|
+
# Block if any to be executed by method
|
304
|
+
#
|
305
|
+
# === Return
|
306
|
+
# (Object):: Value returned by executed method
|
73
307
|
def do_op(meth, *args, &block)
|
74
308
|
conn.send(meth, *args, &block)
|
75
309
|
rescue IOError
|
@@ -77,12 +311,21 @@ module RightSupport::DB
|
|
77
311
|
retry
|
78
312
|
end
|
79
313
|
|
314
|
+
# Reconnect to Cassandra server
|
315
|
+
#
|
316
|
+
# === Return
|
317
|
+
# true:: Always return true
|
80
318
|
def reconnect
|
81
319
|
config = @@config[ENV["RACK_ENV"]]
|
82
|
-
@@conn = Cassandra.new(keyspace, config["server"],{:timeout => RightSupport::CassandraModel::DEFAULT_TIMEOUT})
|
320
|
+
@@conn = Cassandra.new(keyspace, config["server"], {:timeout => RightSupport::DB::CassandraModel::DEFAULT_TIMEOUT})
|
83
321
|
@@conn.disable_node_auto_discovery!
|
322
|
+
true
|
84
323
|
end
|
85
324
|
|
325
|
+
# Cassandra ring for given keyspace
|
326
|
+
#
|
327
|
+
# === Return
|
328
|
+
# (Array):: Members of ring
|
86
329
|
def ring
|
87
330
|
conn.ring
|
88
331
|
end
|
@@ -90,25 +333,50 @@ module RightSupport::DB
|
|
90
333
|
|
91
334
|
attr_accessor :key, :attributes
|
92
335
|
|
93
|
-
|
336
|
+
# Create column family object
|
337
|
+
#
|
338
|
+
# === Parameters
|
339
|
+
# key(String):: Primary key for object
|
340
|
+
# attrs(Hash):: Attributes for object which form Cassandra row
|
341
|
+
# with column name as key and column value as value
|
342
|
+
def initialize(key, attrs = {})
|
94
343
|
self.key = key
|
95
344
|
self.attributes = attrs
|
96
345
|
end
|
97
346
|
|
347
|
+
# Store object in Cassandra
|
348
|
+
#
|
349
|
+
# === Return
|
350
|
+
# true:: Always return true
|
98
351
|
def save
|
99
352
|
self.class.insert(key, attributes)
|
100
353
|
true
|
101
354
|
end
|
102
355
|
|
356
|
+
# Load object from Cassandra without modifying this object
|
357
|
+
#
|
358
|
+
# === Return
|
359
|
+
# (CassandraModel):: Object as stored in Cassandra
|
103
360
|
def reload
|
104
361
|
self.class.get(key)
|
105
362
|
end
|
106
363
|
|
364
|
+
# Reload object value from Cassandra and update this object
|
365
|
+
#
|
366
|
+
# === Return
|
367
|
+
# (CassandraModel):: This object after reload from Cassandra
|
107
368
|
def reload!
|
108
369
|
self.attributes = self.class.real_get(key)
|
109
370
|
self
|
110
371
|
end
|
111
372
|
|
373
|
+
# Column value
|
374
|
+
#
|
375
|
+
# === Parameters
|
376
|
+
# key(String|Integer):: Column name or key
|
377
|
+
#
|
378
|
+
# === Return
|
379
|
+
# (Object|nil):: Column value, or nil if not found
|
112
380
|
def [](key)
|
113
381
|
ret = attributes[key]
|
114
382
|
return ret if ret
|
@@ -117,13 +385,26 @@ module RightSupport::DB
|
|
117
385
|
end
|
118
386
|
end
|
119
387
|
|
388
|
+
# Store new column value
|
389
|
+
#
|
390
|
+
# === Parameters
|
391
|
+
# key(String|Integer):: Column name or key
|
392
|
+
# value(Object):: Value to be stored
|
393
|
+
#
|
394
|
+
# === Return
|
395
|
+
# (Object):: Value stored
|
120
396
|
def []=(key, value)
|
121
397
|
attributes[key] = value
|
122
398
|
end
|
123
399
|
|
400
|
+
# Delete object from Cassandra
|
401
|
+
#
|
402
|
+
# === Return
|
403
|
+
# true:: Always return true
|
124
404
|
def destroy
|
125
405
|
self.class.remove(key)
|
126
406
|
end
|
127
407
|
|
128
|
-
end
|
129
|
-
|
408
|
+
end # CassandraModel
|
409
|
+
|
410
|
+
end # RightSupport::DB
|