zermelo 1.0.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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +10 -0
  4. data/.travis.yml +27 -0
  5. data/Gemfile +20 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +512 -0
  8. data/Rakefile +1 -0
  9. data/lib/zermelo/associations/association_data.rb +24 -0
  10. data/lib/zermelo/associations/belongs_to.rb +115 -0
  11. data/lib/zermelo/associations/class_methods.rb +244 -0
  12. data/lib/zermelo/associations/has_and_belongs_to_many.rb +128 -0
  13. data/lib/zermelo/associations/has_many.rb +120 -0
  14. data/lib/zermelo/associations/has_one.rb +109 -0
  15. data/lib/zermelo/associations/has_sorted_set.rb +124 -0
  16. data/lib/zermelo/associations/index.rb +50 -0
  17. data/lib/zermelo/associations/index_data.rb +18 -0
  18. data/lib/zermelo/associations/unique_index.rb +44 -0
  19. data/lib/zermelo/backends/base.rb +115 -0
  20. data/lib/zermelo/backends/influxdb_backend.rb +178 -0
  21. data/lib/zermelo/backends/redis_backend.rb +281 -0
  22. data/lib/zermelo/filters/base.rb +235 -0
  23. data/lib/zermelo/filters/influxdb_filter.rb +162 -0
  24. data/lib/zermelo/filters/redis_filter.rb +558 -0
  25. data/lib/zermelo/filters/steps/base_step.rb +22 -0
  26. data/lib/zermelo/filters/steps/diff_range_step.rb +17 -0
  27. data/lib/zermelo/filters/steps/diff_step.rb +17 -0
  28. data/lib/zermelo/filters/steps/intersect_range_step.rb +17 -0
  29. data/lib/zermelo/filters/steps/intersect_step.rb +17 -0
  30. data/lib/zermelo/filters/steps/limit_step.rb +17 -0
  31. data/lib/zermelo/filters/steps/offset_step.rb +17 -0
  32. data/lib/zermelo/filters/steps/sort_step.rb +17 -0
  33. data/lib/zermelo/filters/steps/union_range_step.rb +17 -0
  34. data/lib/zermelo/filters/steps/union_step.rb +17 -0
  35. data/lib/zermelo/locks/no_lock.rb +16 -0
  36. data/lib/zermelo/locks/redis_lock.rb +221 -0
  37. data/lib/zermelo/records/base.rb +62 -0
  38. data/lib/zermelo/records/class_methods.rb +127 -0
  39. data/lib/zermelo/records/collection.rb +14 -0
  40. data/lib/zermelo/records/errors.rb +24 -0
  41. data/lib/zermelo/records/influxdb_record.rb +35 -0
  42. data/lib/zermelo/records/instance_methods.rb +224 -0
  43. data/lib/zermelo/records/key.rb +19 -0
  44. data/lib/zermelo/records/redis_record.rb +27 -0
  45. data/lib/zermelo/records/type_validator.rb +20 -0
  46. data/lib/zermelo/version.rb +3 -0
  47. data/lib/zermelo.rb +102 -0
  48. data/spec/lib/zermelo/associations/belongs_to_spec.rb +6 -0
  49. data/spec/lib/zermelo/associations/has_many_spec.rb +6 -0
  50. data/spec/lib/zermelo/associations/has_one_spec.rb +6 -0
  51. data/spec/lib/zermelo/associations/has_sorted_set.spec.rb +6 -0
  52. data/spec/lib/zermelo/associations/index_spec.rb +6 -0
  53. data/spec/lib/zermelo/associations/unique_index_spec.rb +6 -0
  54. data/spec/lib/zermelo/backends/influxdb_backend_spec.rb +0 -0
  55. data/spec/lib/zermelo/backends/moneta_backend_spec.rb +0 -0
  56. data/spec/lib/zermelo/filters/influxdb_filter_spec.rb +0 -0
  57. data/spec/lib/zermelo/filters/redis_filter_spec.rb +0 -0
  58. data/spec/lib/zermelo/locks/redis_lock_spec.rb +170 -0
  59. data/spec/lib/zermelo/records/influxdb_record_spec.rb +258 -0
  60. data/spec/lib/zermelo/records/key_spec.rb +6 -0
  61. data/spec/lib/zermelo/records/redis_record_spec.rb +1426 -0
  62. data/spec/lib/zermelo/records/type_validator_spec.rb +6 -0
  63. data/spec/lib/zermelo/version_spec.rb +6 -0
  64. data/spec/lib/zermelo_spec.rb +6 -0
  65. data/spec/spec_helper.rb +67 -0
  66. data/spec/support/profile_all_formatter.rb +44 -0
  67. data/spec/support/uncolored_doc_formatter.rb +74 -0
  68. data/zermelo.gemspec +30 -0
  69. metadata +174 -0
@@ -0,0 +1,258 @@
1
+ require 'spec_helper'
2
+ require 'zermelo/records/influxdb_record'
3
+
4
+ describe Zermelo::Records::InfluxDBRecord, :influxdb => true do
5
+
6
+ module Zermelo
7
+ class InfluxDBExample
8
+ include Zermelo::Records::InfluxDBRecord
9
+
10
+ define_attributes :name => :string,
11
+ :email => :string,
12
+ :active => :boolean
13
+
14
+ validates :name, :presence => true
15
+
16
+ has_many :children, :class_name => 'Zermelo::InfluxDBExampleChild'
17
+
18
+ end
19
+
20
+ class InfluxDBExampleChild
21
+ include Zermelo::Records::InfluxDBRecord
22
+
23
+ define_attributes :name => :string,
24
+ :important => :boolean
25
+
26
+ belongs_to :example, :class_name => 'Zermelo::InfluxDBExample', :inverse_of => :children
27
+
28
+ validates :name, :presence => true
29
+ end
30
+ end
31
+
32
+ def create_example(attrs = {})
33
+ Zermelo.influxdb.write_point("influx_db_example/#{attrs[:id]}", attrs)
34
+ end
35
+
36
+ let(:influxdb) { Zermelo.influxdb }
37
+
38
+ it "is invalid without a name" do
39
+ example = Zermelo::InfluxDBExample.new(:id => '1',
40
+ :email => 'jsmith@example.com', :active => true)
41
+ expect(example).not_to be_valid
42
+
43
+ errs = example.errors
44
+ expect(errs).not_to be_nil
45
+ expect(errs[:name]).to eq(["can't be blank"])
46
+ end
47
+
48
+ it "adds a record's attributes to influxdb" do
49
+ begin
50
+ data = Zermelo.influxdb.query("select * from /influx_db_example\\/1/")['influx_db_example/1']
51
+ expect(data).to be_nil
52
+ rescue InfluxDB::Error => ide
53
+ # only happens occasionally, with an empty time series by that name
54
+ raise unless /^Couldn't look up columns$/ === ide.message
55
+ end
56
+
57
+ example = Zermelo::InfluxDBExample.new(:id => '1', :name => 'John Smith',
58
+ :email => 'jsmith@example.com', :active => true)
59
+ expect(example).to be_valid
60
+ expect(example.save).to be_truthy
61
+
62
+ data = Zermelo.influxdb.query("select * from /influx_db_example\\/1/")['influx_db_example/1']
63
+ expect(data).to be_an(Array)
64
+ expect(data.size).to eql(1)
65
+ record = data.first
66
+ expect(record).to be_a(Hash)
67
+ # FIXME boolean is stringified as redis needs it to be like that --
68
+ # should probably make this backend-dependent
69
+ expect(record).to include("name"=>"John Smith",
70
+ "email"=>"jsmith@example.com", "active"=>"true", "id"=>"1")
71
+ end
72
+
73
+ it "finds a record by id in influxdb" do
74
+ create_example(:id => '1', :name => 'Jane Doe', :email => 'jdoe@example.com',
75
+ :active => 'true')
76
+
77
+ example = Zermelo::InfluxDBExample.find_by_id('1')
78
+ expect(example).not_to be_nil
79
+
80
+ expect(example).to respond_to(:name)
81
+ expect(example.name).to eql('Jane Doe')
82
+ expect(example).to respond_to(:email)
83
+ expect(example.email).to eql('jdoe@example.com')
84
+ expect(example).to respond_to(:active)
85
+ expect(example.active).to be true
86
+ end
87
+
88
+ it "can update a value in influxdb" do
89
+ create_example(:id => '1', :name => 'Jane Doe', :email => 'jdoe@example.com',
90
+ :active => 'true')
91
+
92
+ example = Zermelo::InfluxDBExample.find_by_id('1')
93
+ expect(example).not_to be_nil
94
+
95
+ example.name = 'John Smith'
96
+ example.save
97
+
98
+ other_example = Zermelo::InfluxDBExample.find_by_id('1')
99
+ expect(other_example).not_to be_nil
100
+ expect(other_example.name).to eq('John Smith')
101
+ end
102
+
103
+ it "destroys a single record from influxdb" do
104
+ create_example(:id => '1', :name => 'Jane Doe', :email => 'jdoe@example.com',
105
+ :active => 'true')
106
+
107
+ example = Zermelo::InfluxDBExample.find_by_id('1')
108
+ example.destroy
109
+ example_chk = Zermelo::InfluxDBExample.find_by_id('1')
110
+ expect(example_chk).to be_nil
111
+ end
112
+
113
+ it "resets changed state on refresh" do
114
+ create_example(:id => '1', :name => 'Jane Doe', :email => 'jdoe@example.com',
115
+ :active => 'true')
116
+ example = Zermelo::InfluxDBExample.find_by_id('1')
117
+
118
+ example.name = "King Henry VIII"
119
+ expect(example.changed).to include('name')
120
+ expect(example.changes).to eq({'name' => ['Jane Doe', 'King Henry VIII']})
121
+
122
+ example.refresh
123
+ expect(example.changed).to be_empty
124
+ expect(example.changes).to be_empty
125
+ end
126
+
127
+ context 'filters' do
128
+
129
+ it "returns all record ids" do
130
+ create_example(:id => '1', :name => 'Jane Doe', :email => 'jdoe@example.com',
131
+ :active => 'true')
132
+ create_example(:id => '2', :name => 'John Smith',
133
+ :email => 'jsmith@example.com', :active => 'false')
134
+
135
+ examples = Zermelo::InfluxDBExample.ids
136
+ expect(examples).not_to be_nil
137
+ expect(examples).to be_an(Array)
138
+ expect(examples.size).to eq(2)
139
+ expect(examples).to contain_exactly('2', '1')
140
+ end
141
+
142
+ it "returns a count of records" do
143
+ create_example(:id => '1', :name => 'Jane Doe', :email => 'jdoe@example.com',
144
+ :active => 'true')
145
+ create_example(:id => '2', :name => 'John Smith',
146
+ :email => 'jsmith@example.com', :active => 'false')
147
+
148
+ example_count = Zermelo::InfluxDBExample.count
149
+ expect(example_count).not_to be_nil
150
+ expect(example_count).to be_an(Integer)
151
+ expect(example_count).to eq(2)
152
+ end
153
+
154
+ it "returns all records" do
155
+ create_example(:id => '1', :name => 'Jane Doe', :email => 'jdoe@example.com',
156
+ :active => 'true')
157
+ create_example(:id => '2', :name => 'John Smith',
158
+ :email => 'jsmith@example.com', :active => 'false')
159
+
160
+ examples = Zermelo::InfluxDBExample.all
161
+ expect(examples).not_to be_nil
162
+ expect(examples).to be_an(Array)
163
+ expect(examples.size).to eq(2)
164
+ expect(examples.map(&:id)).to contain_exactly('2', '1')
165
+ end
166
+
167
+ it "filters all class records by attribute values" do
168
+ create_example(:id => '1', :name => 'Jane Doe', :email => 'jdoe@example.com',
169
+ :active => 'true')
170
+ create_example(:id => '2', :name => 'John Smith',
171
+ :email => 'jsmith@example.com', :active => 'false')
172
+
173
+ example = Zermelo::InfluxDBExample.intersect(:active => true).all
174
+ expect(example).not_to be_nil
175
+ expect(example).to be_an(Array)
176
+ expect(example.size).to eq(1)
177
+ expect(example.map(&:id)).to eq(['1'])
178
+ end
179
+
180
+ it "chains two intersect filters together" do
181
+ create_example(:id => '1', :name => 'Jane Doe', :email => 'jdoe@example.com',
182
+ :active => 'true')
183
+ create_example(:id => '2', :name => 'John Smith',
184
+ :email => 'jsmith@example.com', :active => 'false')
185
+ create_example(:id => '3', :name => 'Fred Bloggs',
186
+ :email => 'fbloggs@example.com', :active => 'true')
187
+
188
+ example = Zermelo::InfluxDBExample.intersect(:active => true).
189
+ intersect(:name => 'Jane Doe').all
190
+ expect(example).not_to be_nil
191
+ expect(example).to be_an(Array)
192
+ expect(example.size).to eq(1)
193
+ expect(example.map(&:id)).to eq(['1'])
194
+ end
195
+
196
+ it "chains an intersect and a union filter together" do
197
+ create_example(:id => '1', :name => 'Jane Doe', :email => 'jdoe@example.com',
198
+ :active => 'true')
199
+ create_example(:id => '2', :name => 'John Smith',
200
+ :email => 'jsmith@example.com', :active => 'false')
201
+ create_example(:id => '3', :name => 'Fred Bloggs',
202
+ :email => 'fbloggs@example.com', :active => 'false')
203
+
204
+ example = Zermelo::InfluxDBExample.intersect(:active => true).union(:name => 'Fred Bloggs').all
205
+ expect(example).not_to be_nil
206
+ expect(example).to be_an(Array)
207
+ expect(example.size).to eq(2)
208
+ expect(example.map(&:id)).to contain_exactly('3', '1')
209
+ end
210
+
211
+ it "chains an intersect and a diff filter together" do
212
+ create_example(:id => '1', :name => 'Jane Doe', :email => 'jdoe@example.com',
213
+ :active => 'true')
214
+ create_example(:id => '2', :name => 'John Smith',
215
+ :email => 'jsmith@example.com', :active => 'false')
216
+ create_example(:id => '3', :name => 'Fred Bloggs',
217
+ :email => 'fbloggs@example.com', :active => 'false')
218
+
219
+ example = Zermelo::InfluxDBExample.intersect(:active => false).diff(:name => 'Fred Bloggs').all
220
+ expect(example).not_to be_nil
221
+ expect(example).to be_an(Array)
222
+ expect(example.size).to eq(1)
223
+ expect(example.map(&:id)).to eq(['2'])
224
+ end
225
+
226
+ end
227
+
228
+ context 'has_many association' do
229
+
230
+ # def create_child(attrs = {})
231
+ # Zermelo.influxdb.write_point('influx_db_example_child', attrs)
232
+ # end
233
+
234
+ it "sets a parent/child has_many relationship between two records in influxdb" do
235
+ create_example(:id => '8', :name => 'John Jones',
236
+ :email => 'jjones@example.com', :active => 'true')
237
+
238
+ child = Zermelo::InfluxDBExampleChild.new(:id => '3', :name => 'Abel Tasman')
239
+ expect(child.save).to be_truthy
240
+
241
+ example = Zermelo::InfluxDBExample.find_by_id('8')
242
+
243
+ children = example.children.all
244
+
245
+ expect(children).to be_an(Array)
246
+ expect(children).to be_empty
247
+
248
+ example.children << child
249
+
250
+ children = example.children.all
251
+
252
+ expect(children).to be_an(Array)
253
+ expect(children.size).to eq(1)
254
+ end
255
+
256
+ end
257
+
258
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'zermelo/records/key'
3
+
4
+ describe Zermelo::Records::Key do
5
+
6
+ end