corm 0.0.14 → 0.0.15
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/lib/corm/model.rb +156 -130
- metadata +8 -2
data/lib/corm/model.rb
CHANGED
@@ -4,50 +4,46 @@ require 'cassandra'
|
|
4
4
|
require 'multi_json'
|
5
5
|
require 'set'
|
6
6
|
|
7
|
-
|
8
7
|
module Corm
|
9
|
-
|
10
8
|
class Model
|
11
9
|
include Enumerable
|
12
10
|
|
13
|
-
|
11
|
+
@cluster = nil
|
14
12
|
|
15
|
-
def self.configure
|
16
|
-
|
13
|
+
def self.configure(opts = {})
|
14
|
+
@cluster = Cassandra.cluster(opts)
|
17
15
|
end
|
18
16
|
|
19
17
|
def self.cluster
|
20
|
-
|
18
|
+
@cluster
|
21
19
|
end
|
22
20
|
|
23
|
-
def self.execute
|
21
|
+
def self.execute(*args)
|
24
22
|
session.execute(*args)
|
25
23
|
end
|
26
24
|
|
27
|
-
def self.field
|
28
|
-
|
25
|
+
def self.field(name, type, pkey = false)
|
29
26
|
fields[name.to_s.downcase] = type.to_s.downcase
|
30
|
-
|
31
27
|
primary_key name.to_s.downcase if pkey
|
32
28
|
|
33
29
|
send :define_method, name.to_s.downcase do
|
34
|
-
type =
|
30
|
+
type = fields[name.to_s.downcase].to_s.downcase
|
35
31
|
value = record[name.to_s.downcase]
|
36
32
|
if type == 'json'
|
37
33
|
value.nil? ? nil : MultiJson.decode(value)
|
38
34
|
elsif type.start_with?('list') && type['json']
|
39
|
-
value.nil? ? [] : value.map{|s| MultiJson.decode
|
35
|
+
value.nil? ? [] : value.map { |s| MultiJson.decode(s) }
|
40
36
|
elsif type.start_with?('list')
|
41
37
|
value.nil? ? [] : value
|
42
38
|
elsif type.start_with?('set') && type['json']
|
43
|
-
Set.new(value.nil? ? [] : value.map{|s| MultiJson.decode
|
39
|
+
Set.new(value.nil? ? [] : value.map { |s| MultiJson.decode(s) })
|
44
40
|
elsif type.start_with?('set')
|
45
41
|
Set.new(value.to_a)
|
46
42
|
elsif type.start_with?('map') && type['json']
|
47
43
|
hash = {}
|
48
44
|
(value || {}).each do |k, v|
|
49
|
-
k = MultiJson.decode
|
50
|
-
v = MultiJson.decode
|
45
|
+
k = MultiJson.decode(k) if type['json,'] || type['json ,']
|
46
|
+
v = MultiJson.decode(v) if type[', json'] || type[',json']
|
51
47
|
hash[k] = v
|
52
48
|
end
|
53
49
|
hash
|
@@ -59,211 +55,241 @@ module Corm
|
|
59
55
|
end
|
60
56
|
|
61
57
|
send :define_method, '[]' do |field|
|
62
|
-
send
|
58
|
+
send(field.to_s.downcase)
|
63
59
|
end
|
64
60
|
|
65
61
|
send :define_method, "#{name.to_s.downcase}=" do |value|
|
66
|
-
type =
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
62
|
+
type = fields[name.to_s.downcase].to_s.downcase
|
63
|
+
val = if type == 'json'
|
64
|
+
value.to_s.empty? ? nil : MultiJson.encode(value)
|
65
|
+
elsif type.start_with?('list') && type['json']
|
66
|
+
value.to_a.empty? ? [] : value.map { |s| MultiJson.encode(s) }
|
67
|
+
elsif type.start_with?('list')
|
68
|
+
value.nil? ? [] : value
|
69
|
+
elsif type.start_with?('set') && type['json']
|
70
|
+
Set.new(value.nil? ? [] : value.map { |s| MultiJson.encode(s) })
|
71
|
+
elsif type.start_with?('set')
|
72
|
+
Set.new(value.to_a)
|
73
|
+
elsif type.start_with?('map') && type['json']
|
74
|
+
hash = {}
|
75
|
+
(value || {}).each do |k, v|
|
76
|
+
k = MultiJson.encode(k) if type['json,'] || type['json ,']
|
77
|
+
v = MultiJson.encode(v) if type[', json'] || type[',json']
|
78
|
+
hash[k] = v
|
79
|
+
end
|
80
|
+
hash
|
81
|
+
elsif type.start_with?('map')
|
82
|
+
value.nil? ? {} : value
|
83
|
+
elsif type == ('timestamp')
|
84
|
+
if value.is_a?(Fixnum)
|
85
|
+
Time.at(value)
|
86
|
+
elsif value.is_a?(String)
|
87
|
+
Time.parse(value)
|
88
|
+
else
|
89
|
+
value
|
90
|
+
end
|
91
|
+
else
|
92
|
+
value
|
93
|
+
end
|
94
|
+
record[name.to_s.downcase] = val
|
98
95
|
end
|
99
96
|
|
100
97
|
send :define_method, '[]=' do |field, value|
|
101
|
-
send
|
98
|
+
send("#{field.to_s.downcase}=", value)
|
102
99
|
end
|
103
100
|
|
104
101
|
nil
|
105
102
|
end
|
106
103
|
|
107
104
|
def to_h
|
108
|
-
Hash[
|
105
|
+
Hash[collect { |k, v| [k, v] }]
|
109
106
|
end
|
107
|
+
|
110
108
|
alias_method :to_hash, :to_h
|
111
109
|
|
112
110
|
def to_json
|
113
|
-
res =
|
111
|
+
res = to_h
|
114
112
|
fields.each do |k, t|
|
115
|
-
if t.start_with?(
|
116
|
-
res[k.to_sym] = res[k.to_sym].to_a
|
117
|
-
end
|
113
|
+
res[k.to_sym] = res[k.to_sym].to_a if t.start_with?('set')
|
118
114
|
end
|
119
115
|
MultiJson.encode(res)
|
120
116
|
end
|
121
117
|
|
122
|
-
def each
|
118
|
+
def each(&block)
|
123
119
|
return enum_for(:each) unless block_given?
|
124
|
-
fields.keys.each {|k| block.call([k.to_sym,
|
120
|
+
fields.keys.each { |k| block.call([k.to_sym, send(k.to_sym)]) }
|
125
121
|
end
|
126
122
|
|
127
123
|
def self.fields
|
128
|
-
class_variable_set
|
129
|
-
|
124
|
+
class_variable_set(
|
125
|
+
:@@fields,
|
126
|
+
{}
|
127
|
+
) unless class_variable_defined?(:@@fields)
|
128
|
+
class_variable_get(:@@fields)
|
130
129
|
end
|
131
130
|
|
132
131
|
def self.count
|
133
132
|
if statements['count'].nil?
|
134
|
-
statements['count'] = session.prepare(
|
133
|
+
statements['count'] = session.prepare(
|
134
|
+
"SELECT COUNT(*) FROM #{[keyspace, table].compact.join '.'};"
|
135
|
+
)
|
135
136
|
end
|
136
137
|
execute(statements['count']).first['count'].to_i
|
137
138
|
end
|
138
139
|
|
139
|
-
def self.get
|
140
|
+
def self.get(relations)
|
140
141
|
if statements['get'].nil?
|
141
|
-
fields = primary_key.flatten.map{ |key| "#{key} = ?" }.join ' AND '
|
142
|
+
fields = primary_key.flatten.map { |key| "#{key} = ?" }.join ' AND '
|
142
143
|
statement = "SELECT * FROM #{keyspace}.#{table} WHERE #{fields} LIMIT 1;"
|
143
144
|
statements['get'] = session.prepare statement
|
144
145
|
end
|
145
|
-
values = primary_key.flatten.map
|
146
|
-
|
147
|
-
|
146
|
+
values = primary_key.flatten.map do |key|
|
147
|
+
relations[key.to_s] || relations[key.to_sym]
|
148
|
+
end
|
149
|
+
cassandra_record_ = execute(statements['get'], arguments: values).first
|
150
|
+
cassandra_record_ ? new(_cassandra_record: cassandra_record_) : nil
|
148
151
|
end
|
149
152
|
|
150
|
-
def self.keyspace
|
151
|
-
class_variable_set
|
152
|
-
class_variable_get
|
153
|
+
def self.keyspace(name = nil)
|
154
|
+
class_variable_set(:@@keyspace, name.to_s) unless name.nil?
|
155
|
+
class_variable_get(:@@keyspace)
|
153
156
|
end
|
154
157
|
|
155
|
-
def self.keyspace!(opts={})
|
156
|
-
replication = opts[:replication] ||
|
158
|
+
def self.keyspace!(opts = {})
|
159
|
+
replication = opts[:replication] ||
|
160
|
+
"{'class': 'SimpleStrategy', 'replication_factor': '1'}"
|
157
161
|
durable_writes = opts[:durable_writes].nil? ? true : opts[:durable_writes]
|
158
|
-
if_not_exists =
|
159
|
-
|
160
|
-
|
162
|
+
if_not_exists = opts[:if_not_exists] ? 'IF NOT EXISTS' : ''
|
163
|
+
cluster.connect.execute(
|
164
|
+
"CREATE KEYSPACE #{if_not_exists} #{keyspace} WITH replication = #{replication} AND durable_writes = #{durable_writes};"
|
165
|
+
)
|
161
166
|
end
|
162
167
|
|
163
|
-
def self.primary_key
|
164
|
-
class_variable_set
|
165
|
-
|
168
|
+
def self.primary_key(partition_key = nil, *cols)
|
169
|
+
class_variable_set(
|
170
|
+
:@@primary_key,
|
171
|
+
[Array(partition_key), cols]
|
172
|
+
) unless partition_key.nil?
|
173
|
+
class_variable_get(:@@primary_key)
|
166
174
|
end
|
167
175
|
|
168
|
-
def self.properties
|
169
|
-
class_variable_set
|
170
|
-
|
176
|
+
def self.properties(*args)
|
177
|
+
class_variable_set(
|
178
|
+
:@@properties,
|
179
|
+
args
|
180
|
+
) unless class_variable_defined?(:@@properties)
|
181
|
+
class_variable_get(:@@properties)
|
171
182
|
end
|
172
183
|
|
173
184
|
def self.session
|
174
|
-
class_variable_set
|
185
|
+
class_variable_set(
|
186
|
+
:@@session,
|
187
|
+
cluster.connect(keyspace)
|
188
|
+
) unless class_variable_defined?(:@@session)
|
175
189
|
class_variable_get :@@session
|
176
190
|
end
|
177
191
|
|
178
192
|
def self.statements
|
179
|
-
class_variable_set
|
180
|
-
|
193
|
+
class_variable_set(
|
194
|
+
:@@statements,
|
195
|
+
{}
|
196
|
+
) unless class_variable_defined?(:@@statements)
|
197
|
+
class_variable_get(:@@statements)
|
181
198
|
end
|
182
199
|
|
183
|
-
def self.table
|
184
|
-
class_variable_set
|
185
|
-
class_variable_get
|
200
|
+
def self.table(name = nil)
|
201
|
+
class_variable_set(:@@table, name) unless name.nil?
|
202
|
+
class_variable_get(:@@table)
|
186
203
|
end
|
187
204
|
|
188
|
-
def self.table!(opts={})
|
189
|
-
if_not_exists =
|
190
|
-
table_ = [keyspace, table].compact.join
|
205
|
+
def self.table!(opts = {})
|
206
|
+
if_not_exists = opts[:if_not_exists] ? 'IF NOT EXISTS' : ''
|
207
|
+
table_ = [keyspace, table].compact.join('.')
|
191
208
|
pkey = []
|
192
209
|
partition_key = primary_key[0].join(',')
|
193
|
-
pkey << (
|
210
|
+
pkey << (
|
211
|
+
primary_key[0].count > 1 ? "(#{partition_key})" : partition_key
|
212
|
+
) unless primary_key[0].to_a.empty?
|
194
213
|
pkey << primary_key[1].join(',') unless primary_key[1].to_a.empty?
|
195
|
-
pkey = pkey.join
|
196
|
-
fields_ = fields.to_a.map{ |
|
214
|
+
pkey = pkey.join(',')
|
215
|
+
fields_ = fields.to_a.map { |a| a.join(' ') }.concat(["PRIMARY KEY (#{pkey})"]).join(', ')
|
197
216
|
definition = "CREATE TABLE #{if_not_exists} #{table_} (#{fields_})".downcase.gsub('json', 'text')
|
198
217
|
definition = properties.to_a.empty? ? "#{definition};" : "#{definition} WITH #{properties.to_a.join ' AND '};"
|
199
|
-
execute
|
218
|
+
execute(definition)
|
200
219
|
end
|
201
220
|
|
202
221
|
def self.truncate!
|
203
|
-
execute
|
222
|
+
execute("TRUNCATE #{[keyspace, table].compact.join '.'};")
|
204
223
|
end
|
205
224
|
|
206
|
-
def initialize
|
207
|
-
@record = opts.delete(:_cassandra_record) ||
|
208
|
-
|
225
|
+
def initialize(opts = {})
|
226
|
+
@record = opts.delete(:_cassandra_record) ||
|
227
|
+
opts.delete('_cassandra_record')
|
228
|
+
@opts = opts
|
229
|
+
opts.each { |k, v| send("#{k}=", v) } if @record.nil?
|
209
230
|
end
|
210
231
|
|
211
232
|
def delete
|
212
233
|
if statements['delete'].nil?
|
213
|
-
pks = primary_key.flatten.map{ |key| "#{key} = ?" }.join
|
234
|
+
pks = primary_key.flatten.map { |key| "#{key} = ?" }.join(' AND ')
|
214
235
|
statement = "DELETE FROM #{keyspace}.#{table} WHERE #{pks};"
|
215
|
-
statements['delete'] = session.prepare
|
236
|
+
statements['delete'] = session.prepare(statement)
|
216
237
|
end
|
217
|
-
values = primary_key.flatten.map
|
218
|
-
|
238
|
+
values = primary_key.flatten.map do |key|
|
239
|
+
record[key.to_s] || record[key.to_sym]
|
240
|
+
end
|
241
|
+
execute(statements['delete'], arguments: values)
|
219
242
|
nil
|
220
243
|
end
|
221
244
|
|
222
245
|
def record
|
223
246
|
@record ||= {}
|
224
|
-
@record
|
225
247
|
end
|
226
248
|
|
227
|
-
def save
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
249
|
+
def save(exclude_nil_values = false, use_raw_values = false)
|
250
|
+
keys = fields.keys.map do |k|
|
251
|
+
value = use_raw_values ? (opts[k.to_s] || opts[k.to_sym]) : record[k]
|
252
|
+
exclude_nil_values && value.nil? ? nil : k
|
253
|
+
end.compact
|
254
|
+
execute(
|
255
|
+
session.prepare(
|
256
|
+
"INSERT INTO #{keyspace}.#{table} (#{keys.join(',')}) VALUES (#{keys.map { '?' }.join(',')});"
|
257
|
+
),
|
258
|
+
arguments: keys.map do |k|
|
259
|
+
use_raw_values ? (opts[k.to_s] || opts[k.to_sym]) : record[k]
|
260
|
+
end
|
261
|
+
)
|
234
262
|
nil
|
235
263
|
end
|
236
264
|
|
237
265
|
protected
|
238
266
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
def keyspace
|
244
|
-
self.class.keyspace
|
245
|
-
end
|
267
|
+
def execute(*args)
|
268
|
+
self.class.execute(*args)
|
269
|
+
end
|
246
270
|
|
247
|
-
|
248
|
-
|
249
|
-
|
271
|
+
def keyspace
|
272
|
+
self.class.keyspace
|
273
|
+
end
|
250
274
|
|
251
|
-
|
252
|
-
|
253
|
-
|
275
|
+
def fields
|
276
|
+
self.class.fields
|
277
|
+
end
|
254
278
|
|
255
|
-
|
256
|
-
|
257
|
-
|
279
|
+
def primary_key
|
280
|
+
self.class.primary_key
|
281
|
+
end
|
258
282
|
|
259
|
-
|
260
|
-
|
261
|
-
|
283
|
+
def session
|
284
|
+
self.class.session
|
285
|
+
end
|
262
286
|
|
263
|
-
|
264
|
-
|
265
|
-
|
287
|
+
def statements
|
288
|
+
self.class.statements
|
289
|
+
end
|
266
290
|
|
291
|
+
def table
|
292
|
+
self.class.table
|
293
|
+
end
|
267
294
|
end
|
268
|
-
|
269
295
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: corm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.15
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-05-
|
12
|
+
date: 2015-05-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cassandra-driver
|
@@ -92,12 +92,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
92
|
- - ! '>='
|
93
93
|
- !ruby/object:Gem::Version
|
94
94
|
version: '0'
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
hash: 1788455227791156399
|
95
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
99
|
none: false
|
97
100
|
requirements:
|
98
101
|
- - ! '>='
|
99
102
|
- !ruby/object:Gem::Version
|
100
103
|
version: '0'
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
hash: 1788455227791156399
|
101
107
|
requirements: []
|
102
108
|
rubyforge_project:
|
103
109
|
rubygems_version: 1.8.23.2
|