post_json 1.0.6 → 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +48 -1
- data/lib/post_json.rb +1 -0
- data/lib/post_json/base.rb +1 -0
- data/lib/post_json/concerns/copyable.rb +36 -0
- data/lib/post_json/concerns/finder_methods.rb +21 -4
- data/lib/post_json/concerns/settings_methods.rb +8 -0
- data/lib/post_json/query_translator.rb +4 -0
- data/lib/post_json/version.rb +1 -1
- data/spec/models/base_spec.rb +44 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f25ad4b6cb31d0b679bfa6c41d8b5533c3c69a8
|
4
|
+
data.tar.gz: 25b074ed6292d61272a2b3bb08c021d32ca881af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9783c9e9b72e4d5f6fadd58718a25c3a13c29a1b6168997f1abbbb7511c21d5891badde842b51b70885b19a077d63d5595acc891a7e486f464eb9bf574d9667f
|
7
|
+
data.tar.gz: 71267eaa0731c1a4340ec28808fcbcd3961ccddb36b5525170bc3b85727fac0d9d78d22f96ae2133c82758462c6d1ec6af385472b8de03c3c7f53e4eacd3d327
|
data/README.md
CHANGED
@@ -135,7 +135,32 @@ find_by!, find_each, find_in_batches, first, first!, first_or_create, first_or_i
|
|
135
135
|
many?, offset, only, order, pluck, reorder, reverse_order, select, size, take, take!, to_a, to_sql, and where.
|
136
136
|
|
137
137
|
We also added `page(page, per_page)`, which translate into `offset((page-1)*per_page).limit(per_page)`.
|
138
|
+
|
139
|
+
|
140
|
+
## Performance
|
141
|
+
|
142
|
+
On a virtual machine running on a 3 year old laptop we created 100.000 documents:
|
143
|
+
|
144
|
+
test_model = PostJson::Collection["test"]
|
145
|
+
100000.times { test_model.create(content: SecureRandom.uuid) }
|
146
|
+
content = test_model.last.content
|
138
147
|
|
148
|
+
result = test_model.where(content: content).count
|
149
|
+
# Rails debug tells me the duration was 975.5ms
|
150
|
+
|
151
|
+
The duration was above 50ms as you can see.
|
152
|
+
|
153
|
+
PostJson has a feature called "Dynamic Index". It is enabled by default and works automatic behind the scene. It has now created an index on 'content'.
|
154
|
+
|
155
|
+
Now lets see how the performance will be on the second and future queries using 'content':
|
156
|
+
|
157
|
+
result = test_model.where(content: content).count
|
158
|
+
# Rails debug tells me the duration was 1.5ms
|
159
|
+
|
160
|
+
It shows PostgreSQL as a document database combined with indexing has great performance out of the box.
|
161
|
+
|
162
|
+
See the next section about "Dynamic Indexes" for details.
|
163
|
+
|
139
164
|
## Dynamic Indexes
|
140
165
|
|
141
166
|
Most applications do the same queries over and over again. This is why we think it is useful, if PostJson create indexes on slow queries.
|
@@ -171,7 +196,29 @@ You can adjust the settings:
|
|
171
196
|
|
172
197
|
You might already know this about User Interfaces, but it is usual considered good practice if auto-complete responses are served to the user within 100 milliseconds. Other results are usual okay within 500 milliseconds. So leave room for application processing and network delay.
|
173
198
|
|
174
|
-
Do not set create_dynamic_index_milliseconds_threshold too low as PostJson will try to create an index for every query performance. Like a threshold of 1 millisecond will be less than almost all
|
199
|
+
Do not set create_dynamic_index_milliseconds_threshold too low as PostJson will try to create an index for every query performance. Like a threshold of 1 millisecond will be less than the duration of almost all queries.
|
200
|
+
|
201
|
+
## Primary Keys
|
202
|
+
|
203
|
+
PostJson assign UUID as primary key (id):
|
204
|
+
|
205
|
+
me = Person.create(name: "Jacob")
|
206
|
+
puts me.id
|
207
|
+
# "297a2500-a456-459b-b3e9-e876f59602c2"
|
208
|
+
|
209
|
+
But you also set the primary key yourself:
|
210
|
+
|
211
|
+
john_doe = Person.create(id: "John Doe")
|
212
|
+
|
213
|
+
Notice the primary key is downcased when doing a query or finding records:
|
214
|
+
|
215
|
+
found = Person.where(id: "JOhN DoE").first
|
216
|
+
puts found
|
217
|
+
# {"id"=>"John Doe", "version"=>1, "created_at"=>"2013-10-22T10:42:26.190Z", "updated_at"=>"2013-10-22T10:42:26.190Z"}
|
218
|
+
|
219
|
+
found_again = Person.find("JOhN DoE")
|
220
|
+
puts found_again.attributes
|
221
|
+
# {"id"=>"John Doe", "version"=>1, "created_at"=>"2013-10-22T10:42:26.190Z", "updated_at"=>"2013-10-22T10:42:26.190Z"}
|
175
222
|
|
176
223
|
## The future
|
177
224
|
|
data/lib/post_json.rb
CHANGED
@@ -6,6 +6,7 @@ require 'post_json/concerns/query_methods'
|
|
6
6
|
require 'post_json/concerns/finder_methods'
|
7
7
|
require 'post_json/concerns/settings_methods'
|
8
8
|
require 'post_json/concerns/dynamic_index_methods'
|
9
|
+
require 'post_json/concerns/copyable'
|
9
10
|
require 'post_json/query_translator'
|
10
11
|
require 'post_json/base'
|
11
12
|
require 'post_json/model_settings'
|
data/lib/post_json/base.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
module PostJson
|
2
|
+
module Copyable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def copy(destination_collection_name)
|
7
|
+
destination = Collection[destination_collection_name]
|
8
|
+
if exists?
|
9
|
+
src_id = persisted_settings.id
|
10
|
+
|
11
|
+
if destination.persisted?
|
12
|
+
dest_id = destination.persisted_settings.id
|
13
|
+
query = original_all
|
14
|
+
query = query.joins("INNER JOIN #{table_name} as dest ON dest.id = #{table_name}.id")
|
15
|
+
query = query.where("dest.__doc__model_settings_id = '#{dest_id}'")
|
16
|
+
query = query.where("\"#{table_name}\".__doc__model_settings_id = '#{src_id}'")
|
17
|
+
query = query.where("dest.id = \"#{table_name}\".id")
|
18
|
+
conflicting_ids = query.pluck("dest.id").join(", ")
|
19
|
+
if conflicting_ids.present?
|
20
|
+
error_message = "Following primary keys (#{primary_key}) already exists in collection \"#{destination.collection_name}\": #{conflicting_ids}."
|
21
|
+
raise ActiveRecord::RecordNotUnique, error_message
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
dest_id = destination.persisted_settings.id
|
26
|
+
selectors = PostJson::Base.column_names.map { |s| s == "__doc__model_settings_id" ? "'#{dest_id}' as #{s}" : s }.join(", ")
|
27
|
+
condition = "__doc__model_settings_id = '#{src_id}'"
|
28
|
+
destination.transaction do
|
29
|
+
destination.connection.execute("INSERT INTO #{table_name} (SELECT #{selectors} FROM #{table_name} WHERE #{condition})")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
destination
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -37,7 +37,8 @@ module PostJson
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def destroy(id)
|
40
|
-
|
40
|
+
value = id ? id.to_s.downcase : nil
|
41
|
+
execute { |documents| documents.destroy(value) }
|
41
42
|
end
|
42
43
|
|
43
44
|
def destroy_all(conditions = nil)
|
@@ -62,7 +63,18 @@ module PostJson
|
|
62
63
|
end
|
63
64
|
|
64
65
|
def find(*args)
|
65
|
-
|
66
|
+
if args.length == 0
|
67
|
+
execute { |documents| documents.find }
|
68
|
+
elsif args.length == 1 && args[0].is_a?(Array)
|
69
|
+
ids = args[0].map{|id| id ? id.to_s.downcase : nil}
|
70
|
+
execute { |documents| documents.find(ids) }
|
71
|
+
elsif args.length == 1 && args[0].is_a?(Array) == false
|
72
|
+
id = args[0] ? args[0].to_s.downcase : nil
|
73
|
+
execute { |documents| documents.find(id) }
|
74
|
+
else
|
75
|
+
ids = args.map{|id| id ? id.to_s.downcase : nil}
|
76
|
+
execute { |documents| documents.find(ids) }
|
77
|
+
end
|
66
78
|
end
|
67
79
|
|
68
80
|
def find_by(*args)
|
@@ -214,8 +226,8 @@ module PostJson
|
|
214
226
|
|
215
227
|
def define_selector(attribute_name)
|
216
228
|
case attribute_name.to_s
|
217
|
-
when
|
218
|
-
"\"#{table_name}\"
|
229
|
+
when primary_key
|
230
|
+
"\"#{table_name}\".#{primary_key}"
|
219
231
|
else
|
220
232
|
"json_selector('#{attribute_name}', \"#{table_name}\".__doc__body)"
|
221
233
|
end
|
@@ -248,17 +260,22 @@ module PostJson
|
|
248
260
|
[:where, arguments]
|
249
261
|
when :where_equal
|
250
262
|
selector = define_selector(arguments[:attribute])
|
263
|
+
selector_is_primary_key = arguments[:attribute].to_s == primary_key
|
251
264
|
argument = arguments[:argument]
|
252
265
|
case argument
|
253
266
|
when Array
|
254
267
|
values = argument.map{|v| v ? v.to_s : nil}
|
268
|
+
values = values.map{|v| v.try(:downcase)} if selector_is_primary_key
|
255
269
|
[:where, "(#{selector} IN (?))", values]
|
256
270
|
when Range
|
257
271
|
first_value = argument.first ? argument.first.to_s : nil
|
272
|
+
first_value = first_value.try(:downcase) if selector_is_primary_key
|
258
273
|
last_value = argument.last ? argument.last.to_s : nil
|
274
|
+
last_value = last_value.try(:downcase) if selector_is_primary_key
|
259
275
|
[:where, "(#{selector} BETWEEN ? AND ?)", first_value, last_value]
|
260
276
|
else
|
261
277
|
value = argument ? argument.to_s : nil
|
278
|
+
value = value.try(:downcase) if selector_is_primary_key
|
262
279
|
[:where, "#{selector} = ?", value]
|
263
280
|
end
|
264
281
|
else
|
data/lib/post_json/version.rb
CHANGED
data/spec/models/base_spec.rb
CHANGED
@@ -48,8 +48,13 @@ describe "Base model" do
|
|
48
48
|
|
49
49
|
context "should downcase primary key" do
|
50
50
|
let(:new_id) { "abc" }
|
51
|
-
|
51
|
+
let(:model) { PostJson::Collection['Customer'] }
|
52
|
+
let!(:record) { model.create id: "#{new_id.upcase}" }
|
53
|
+
subject { record }
|
52
54
|
its(:id) { should == new_id }
|
55
|
+
it { model.exists?(id: "#{new_id.upcase}").should be_true }
|
56
|
+
it { model.where(id: "#{new_id.upcase}").count.should == 1 }
|
57
|
+
it { model.find("#{new_id.upcase}").id.should == new_id }
|
53
58
|
end
|
54
59
|
|
55
60
|
context "should now allow change of primary key" do
|
@@ -390,4 +395,42 @@ describe "Base model" do
|
|
390
395
|
it { subject["updated_at"].should == document.updated_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ') }
|
391
396
|
it { subject["version"].should == document.version }
|
392
397
|
end
|
398
|
+
|
399
|
+
context "copy" do
|
400
|
+
let(:orig_model) { PostJson::Collection["Originals"] }
|
401
|
+
let(:copy_model) { orig_model.copy("Copies") }
|
402
|
+
before do
|
403
|
+
orig_model.create(id: "Jacob", age: 33)
|
404
|
+
orig_model.create(id: "Martin", age: 29)
|
405
|
+
end
|
406
|
+
|
407
|
+
subject { copy_model }
|
408
|
+
|
409
|
+
its(:count) { should == 2 }
|
410
|
+
it { subject.find("Jacob").age.should == 33 }
|
411
|
+
it { subject.find("Martin").age.should == 29 }
|
412
|
+
|
413
|
+
context "conflict" do
|
414
|
+
before do
|
415
|
+
copy_model
|
416
|
+
orig_model.create(id: "Jonathan", age: 33)
|
417
|
+
end
|
418
|
+
it { expect { orig_model.copy(copy_model.collection_name) }.to raise_error(ActiveRecord::RecordNotUnique) }
|
419
|
+
end
|
420
|
+
|
421
|
+
context "to existing collection" do
|
422
|
+
let(:other_model) { PostJson::Collection["Others"] }
|
423
|
+
before do
|
424
|
+
other_model.create(id: "John", age: 25)
|
425
|
+
other_model.copy(copy_model.collection_name)
|
426
|
+
orig_model.create(id: "Jonathan", age: 33)
|
427
|
+
end
|
428
|
+
subject { copy_model }
|
429
|
+
|
430
|
+
its(:count) { should == 3 }
|
431
|
+
it { subject.find("Jacob").age.should == 33 }
|
432
|
+
it { subject.find("Martin").age.should == 29 }
|
433
|
+
it { subject.find("John").age.should == 25 }
|
434
|
+
end
|
435
|
+
end
|
393
436
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: post_json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jacob Madsen and Martin Thoegersen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -103,6 +103,7 @@ files:
|
|
103
103
|
- lib/post_json/concerns/settings_methods.rb
|
104
104
|
- lib/post_json/concerns/query_methods.rb
|
105
105
|
- lib/post_json/concerns/argument_methods.rb
|
106
|
+
- lib/post_json/concerns/copyable.rb
|
106
107
|
- lib/post_json/concerns/finder_methods.rb
|
107
108
|
- lib/post_json/concerns/dynamic_index_methods.rb
|
108
109
|
- lib/post_json/version.rb
|