post_json 1.0.10 → 1.0.11

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: 3ba8f65c7f2db2eec1489a4f4fd47bb44d882a1f
4
- data.tar.gz: f40eda3e7b88abaab7ab6789413e28277ce28338
3
+ metadata.gz: fb5fea92951fd8ec7e82b70905b2ae78c5e28071
4
+ data.tar.gz: 412eaafc6a0b9c802dd02116898dc173f194d454
5
5
  SHA512:
6
- metadata.gz: 41dc503b940da4747ee0a6af8bba3481decb1196ace7605c87d89ba4596d2451cb3234506e3908458a39465a7d3b5607db867ed444d9ebd1e3685a5277103a47
7
- data.tar.gz: 83d71844541cfae6110fcbaebb480f62e1eaea185da3530eb34d039405941b5d0ce9b905977eed2582a3cb4546823672dea94d5b48a05c9adbea98a3e6863759
6
+ metadata.gz: 4874f99abaec969d3544de9ad4e1db5f651a16d50625ecb9112e2913b2048e7c6183b5ab154efcec482a1d0a6ab957a37a7a8cb22ec33417db76e548e4f16fe0
7
+ data.tar.gz: 9fc7845cf1082ed2f0670d43aa8ab07ab27780340122d0f3d139b2e2c9f8a1f8d0aae686f073a4e2f44e8191b05f743cdecf98a8efe94f08ff86462ccc6791ff
data/README.md CHANGED
@@ -11,15 +11,16 @@ See example of how we use PostJson as part of <a href="https://github.com/webnut
11
11
 
12
12
 
13
13
  ## Getting started
14
- 1. Add the gem to your Ruby on Rails application `Gemfile`:
15
14
 
16
- gem 'post_json'
15
+ ### Add the gem to your Ruby on Rails application `Gemfile`:
16
+
17
+ gem 'post_json'
17
18
 
18
- 2. At the command prompt, install the gem:
19
+ ### At the command prompt, install the gem, run the generator, and migrate the db:
19
20
 
20
- bundle install
21
- rails g post_json:install
22
- rake db:migrate
21
+ bundle install
22
+ rails g post_json:install
23
+ rake db:migrate
23
24
 
24
25
  That's it!
25
26
 
@@ -34,99 +35,114 @@ PostJson is all about collections. All models represent a collection.
34
35
 
35
36
  Also, __notice you don't have to define model attributes anywhere!__
36
37
 
37
- 1. Lets create your first model.
38
+ ### Lets create your first model.
38
39
 
39
- class Person < PostJson::Collection["people"]
40
- end
40
+ ```ruby
41
+ class Person < PostJson::Collection["people"]
42
+ end
41
43
 
42
- me = Person.create(name: "Jacob")
43
-
44
- As you can see it look the same as ActiveRecord, except you define `PostJson::Collection["people"]` instead of
45
- `ActiveRecord::Base`.
46
-
47
- `Person` can do the same as any model class inheriting `ActiveRecord::Base`.
44
+ me = Person.create(name: "Jacob")
45
+ ```
46
+
47
+ As you can see it look the same as ActiveRecord, except you define `PostJson::Collection["people"]` instead of
48
+ `ActiveRecord::Base`.
48
49
 
49
- You can also skip the creation of a class:
50
+ `Person` can do the same as any model class inheriting `ActiveRecord::Base`.
50
51
 
51
- people = PostJson::Collection["people"]
52
- me = people.create(name: "Jacob")
52
+ You can also skip the creation of a class:
53
+
54
+ ```ruby
55
+ people = PostJson::Collection["people"]
56
+ me = people.create(name: "Jacob")
57
+ ```
53
58
 
54
- 2. Adding some validation:
59
+ ### Adding some validation:
55
60
 
56
- class Person < PostJson::Collection["people"]
57
- validates :name, presence: true
58
- end
61
+ ```ruby
62
+ class Person < PostJson::Collection["people"]
63
+ validates :name, presence: true
64
+ end
65
+ ```
59
66
 
60
- PostJson::Collection["people"] returns a class, which is based on `PostJson::Base`, which is based on
61
- `ActiveRecord::Base`. So its the exact same validation as you may know.
67
+ PostJson::Collection["people"] returns a class, which is based on `PostJson::Base`, which is based on
68
+ `ActiveRecord::Base`. So its the exact same validation as you may know.
62
69
 
63
- Read the <a href="http://guides.rubyonrails.org/active_record_validations.html" target="_blank">Rails guide about validation</a>
64
- if you need more information.
70
+ Read the <a href="http://guides.rubyonrails.org/active_record_validations.html" target="_blank">Rails guide about validation</a> if you need more information.
65
71
 
66
- 3. Lets create a more complex document and do a query:
72
+ ### Lets create a more complex document and do a query:
67
73
 
68
- me = Person.create(name: "Jacob", details: {age: 33})
69
-
70
- Now we can make a query and get the document:
71
-
72
- also_me_1 = Person.where(details: {age: 33}).first
73
- also_me_2 = Person.where("details.age" => 33).first
74
- also_me_3 = Person.where("function(doc) { return doc.details.age == 33; }").first
75
- also_me_4 = Person.where("json_details.age = ?", 33).first
76
-
77
- PostJson support filtering on nested attributes as you can see. The two first queries speak for themself.
78
-
79
- The third query is special and show it is possible to use a pure JavaScript function for selecting documents.
74
+ ```ruby
75
+ me = Person.create(name: "Jacob", details: {age: 33})
76
+ ```
77
+
78
+ Now we can make a query and get the document:
80
79
 
81
- The last query is also special and show it is possible to write real SQL queries. We just need to prefix
82
- the JSON attributes with `json_`.
80
+ ```ruby
81
+ # PostJson supports filtering on nested attributes
82
+ also_me_1 = Person.where(details: {age: 33}).first
83
+ also_me_2 = Person.where("details.age" => 33).first
83
84
 
84
- 4. Accessing attributes:
85
+ # It is possible to use a pure JavaScript function for selecting documents
86
+ also_me_3 = Person.where("function(doc) { return doc.details.age == 33; }").first
85
87
 
86
- person = Person.create(name: "Jacob")
87
- puts person.name # "Jacob"
88
- puts person.name_was # "Jacob"
89
- puts person.name_changed? # false
90
- puts person.name_change # nil
88
+ # It is also possible to write real SQL queries. Just prefix the JSON attributes with `json_`
89
+ also_me_4 = Person.where("json_details.age = ?", 33).first
90
+ ```
91
91
 
92
- person.name = "Martin"
92
+ ### Accessing attributes:
93
+
94
+ Like you would expect with ActiveRecord:
95
+
96
+ ```ruby
97
+ person = Person.create(name: "Jacob")
98
+ puts person.name # => "Jacob"
99
+ puts person.name_was # => "Jacob"
100
+ puts person.name_changed? # => false
101
+ puts person.name_change # => nil
102
+
103
+ person.name = "Martin"
93
104
 
94
- puts person.name_was # "Jacob"
95
- puts person.name # "Martin"
96
- puts person.name_changed? # true
97
- puts person.name_change # ["Jacob", "Martin"]
105
+ puts person.name_was # => "Jacob"
106
+ puts person.name # => "Martin"
107
+ puts person.name_changed? # => true
108
+ puts person.name_change # => ["Jacob", "Martin"]
98
109
 
99
- person.save
110
+ person.save
100
111
 
101
- puts person.name # "Martin"
102
- puts person.name_was # "Martin"
103
- puts person.name_changed? # false
104
- puts person.name_change # nil
105
-
106
- Like you would expect with ActiveRecord.
112
+ puts person.name # => "Martin"
113
+ puts person.name_was # => "Martin"
114
+ puts person.name_changed? # => false
115
+ puts person.name_change # => nil
116
+ ```
117
+
118
+ ### Introduction to select and selectors.
107
119
 
108
- 5. Introduction to select and selectors.
120
+ Sometimes we need a transformed version of documents. This is very easy with `select`
109
121
 
110
- Sometimes we need a transformed version of documents. This is very easy with `select`
122
+ ```ruby
123
+ me = Person.create(name: "Jacob", details: {age: 33})
111
124
 
112
- me = Person.create(name: "Jacob", details: {age: 33})
125
+ other_me = Person.limit(1).select({name: "name", age: "details.age"}).first
113
126
 
114
- other_me = Person.limit(1).select({name: "name", age: "details.age"}).first
115
- puts other_me # {name: "Jacob", age: 33}
127
+ puts other_me
128
+ # => {name: "Jacob", age: 33}
116
129
 
117
- `select` takes a hash as argument and return an array of hashes. The value of each key/value pair in the hash argument is a selector. Selectors can point at attributes at root level, but also nested attributes. Each level of attributes is seperated with a dot (.).
130
+ ```
131
+ `select` takes a hash as argument and return an array of hashes. The value of each key/value pair in the hash argument is a selector. Selectors can point at attributes at root level, but also nested attributes. Each level of attributes is seperated with a dot (.).
118
132
 
119
- 6. Check out the initializer at `config/initializers/post_json.rb`
133
+ ### Check out the initializer at `config/initializers/post_json.rb`
120
134
 
121
- PostJson.setup "people" do |collection|
122
- collection.record_timestamps = true # default is 'true'
123
- collection.created_at_attribute_name = "created_at" # default is 'created_at'
124
- collection.updated_at_attribute_name = "updated_at" # default is 'updated_at'
125
- collection.include_version_number = true # default is 'true'
126
- collection.version_attribute_name = "version" # default is 'version'
127
- collection.use_dynamic_index = true # default is 'true'
128
- collection.create_dynamic_index_milliseconds_threshold = 50 # default is '50'
129
- end
135
+ ```ruby
136
+ PostJson.setup "people" do |collection|
137
+ collection.record_timestamps = true # default is 'true'
138
+ collection.created_at_attribute_name = "created_at" # default is 'created_at'
139
+ collection.updated_at_attribute_name = "updated_at" # default is 'updated_at'
140
+ collection.include_version_number = true # default is 'true'
141
+ collection.version_attribute_name = "version" # default is 'version'
142
+ collection.use_dynamic_index = true # default is 'true'
143
+ collection.create_dynamic_index_milliseconds_threshold = 50 # default is '50'
144
+ end
145
+ ```
130
146
 
131
147
  #### All of the following methods are supported
132
148
 
@@ -141,12 +157,14 @@ We also added `page(page, per_page)`, which translate into `offset((page-1)*per_
141
157
 
142
158
  On a virtual machine running on a 3 year old laptop we created 100.000 documents:
143
159
 
144
- test_model = PostJson::Collection["test"]
145
- 100000.times { test_model.create(content: SecureRandom.uuid) }
146
- content = test_model.last.content
160
+ ```ruby
161
+ test_model = PostJson::Collection["test"]
162
+ 100000.times { test_model.create(content: SecureRandom.uuid) }
163
+ content = test_model.last.content
147
164
 
148
- result = test_model.where(content: content).count
149
- # Rails debug tells me the duration was 975.5ms
165
+ result = test_model.where(content: content).count
166
+ # Rails debug tells me the duration was 975.5ms
167
+ ```
150
168
 
151
169
  The duration was above 50ms as you can see.
152
170
 
@@ -154,8 +172,10 @@ PostJson has a feature called "Dynamic Index". It is enabled by default and work
154
172
 
155
173
  Now lets see how the performance will be on the second and future queries using 'content':
156
174
 
157
- result = test_model.where(content: content).count
158
- # Rails debug tells me the duration was 1.5ms
175
+ ```ruby
176
+ result = test_model.where(content: content).count
177
+ # Rails debug tells me the duration was 1.5ms
178
+ ```
159
179
 
160
180
  It shows PostgreSQL as a document database combined with indexing has great performance out of the box.
161
181
 
@@ -183,16 +203,17 @@ you execute a query with `name` the performance will be much improved.
183
203
 
184
204
  You can adjust the settings:
185
205
 
186
- class Person < PostJson::Collection["people"]
187
- self.create_dynamic_index_milliseconds_threshold = 75
188
- end
206
+ ```ruby
207
+ class Person < PostJson::Collection["people"]
208
+ self.create_dynamic_index_milliseconds_threshold = 75
209
+ end
189
210
 
190
- # Or you can do:
211
+ # Or you can do:
191
212
 
192
- PostJson::Collection["people"].create_dynamic_index_milliseconds_threshold = 75
193
-
194
- # Now indexes are only created if queries are slower than 75 milliseconds.
213
+ PostJson::Collection["people"].create_dynamic_index_milliseconds_threshold = 75
195
214
 
215
+ # Now indexes are only created if queries are slower than 75 milliseconds.
216
+ ```
196
217
 
197
218
  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.
198
219
 
@@ -202,23 +223,32 @@ Do not set create_dynamic_index_milliseconds_threshold too low as PostJson will
202
223
 
203
224
  PostJson assign UUID as primary key (id):
204
225
 
205
- me = Person.create(name: "Jacob")
206
- puts me.id
207
- # "297a2500-a456-459b-b3e9-e876f59602c2"
226
+ ```ruby
227
+ me = Person.create(name: "Jacob")
228
+
229
+ puts me.id
230
+ # => "297a2500-a456-459b-b3e9-e876f59602c2"
231
+ ```
208
232
 
209
233
  But you also set the primary key yourself:
210
234
 
211
- john_doe = Person.create(id: "John Doe")
235
+ ```ruby
236
+ john_doe = Person.create(id: "John Doe")
237
+ ```
212
238
 
213
239
  Notice the primary key is downcased when doing a query or finding records:
214
240
 
215
- found = Person.where(id: "JOhN DoE").first
216
- puts found.attributes
217
- # {"id"=>"John Doe", "version"=>1, "created_at"=>"2013-10-22T10:42:26.190Z", "updated_at"=>"2013-10-22T10:42:26.190Z"}
241
+ ```ruby
242
+ found = Person.where(id: "JOhN DoE").first
243
+
244
+ puts found.attributes
245
+ # => {"id"=>"John Doe", "version"=>1, "created_at"=>"2013-10-22T10:42:26.190Z", "updated_at"=>"2013-10-22T10:42:26.190Z"}
218
246
 
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"}
247
+ found_again = Person.find("JOhN DoE")
248
+
249
+ puts found_again.attributes
250
+ # => {"id"=>"John Doe", "version"=>1, "created_at"=>"2013-10-22T10:42:26.190Z", "updated_at"=>"2013-10-22T10:42:26.190Z"}
251
+ ```
222
252
 
223
253
  ## The future
224
254
 
@@ -12,11 +12,32 @@ module PostJson
12
12
  include Copyable
13
13
 
14
14
  def initialize(*args)
15
- __local__primary_key = self.class.primary_key
16
- __local__attrs = (args[0] || {}).with_indifferent_access
17
- __local__attrs[__local__primary_key] = __local__attrs[__local__primary_key].to_s if __local__attrs.has_key?(__local__primary_key)
18
- args[0] = {__local__primary_key => __local__attrs[__local__primary_key], '__doc__body' => __local__attrs}.with_indifferent_access
19
- super
15
+ if args[0]
16
+ __local__doc__body = HashWithIndifferentAccess.new
17
+
18
+ args[0] = args[0].with_indifferent_access.inject(HashWithIndifferentAccess.new('__doc__body' => {})) do |result, (attribute_name, value)|
19
+ if self.class.primary_key == attribute_name
20
+ result[attribute_name] = value
21
+ result['__doc__body'][attribute_name] = value
22
+ elsif self.class.column_names.include?(attribute_name)
23
+ result[attribute_name] = value
24
+ else
25
+ __local__doc__body[attribute_name] = value
26
+ end
27
+ result
28
+ end
29
+
30
+ super(*args) do |new_record|
31
+ __local__doc__body.each do |attribute_name, value|
32
+ new_record.public_send("#{attribute_name}=", value)
33
+ end
34
+
35
+ yield new_record if block_given?
36
+ end
37
+ else
38
+ args[0] = HashWithIndifferentAccess.new('__doc__body' => {})
39
+ super
40
+ end
20
41
  end
21
42
 
22
43
  def cache_key
@@ -26,7 +47,11 @@ module PostJson
26
47
  end
27
48
 
28
49
  def attributes
29
- read_attribute('__doc__body').try(:with_indifferent_access) || HashWithIndifferentAccess.new
50
+ if @new_record != nil
51
+ (read_attribute('__doc__body') || {}).with_indifferent_access
52
+ else
53
+ HashWithIndifferentAccess.new
54
+ end
30
55
  end
31
56
 
32
57
  def to_h
@@ -108,6 +133,8 @@ module PostJson
108
133
  self.__doc__body_write_attribute(attribute_name, value)
109
134
  end
110
135
 
136
+ alias_method :super_respond_to?, :respond_to?
137
+
111
138
  def respond_to?(method_symbol, include_all = false)
112
139
  if super
113
140
  true
@@ -121,6 +148,8 @@ module PostJson
121
148
  method_name[0..-2]
122
149
  elsif method_name.end_with?("_change")
123
150
  method_name[0..-8]
151
+ elsif method_name.end_with?("_will_change!")
152
+ method_name[0..-14]
124
153
  else
125
154
  method_name
126
155
  end
@@ -138,6 +167,8 @@ module PostJson
138
167
  method_name[0..-2]
139
168
  elsif method_name.end_with?("_change")
140
169
  method_name[0..-8]
170
+ elsif method_name.end_with?("_will_change!")
171
+ method_name[0..-14]
141
172
  else
142
173
  method_name
143
174
  end
@@ -174,10 +205,7 @@ module PostJson
174
205
  if @collection_name == nil
175
206
  @collection_name = superclass.collection_name rescue nil
176
207
  end
177
- message = "You need to assign a collection name to class \"#{name}\":
178
- class #{name}
179
- self.collection_name = #{name.underscore.pluralize}
180
- end"
208
+ message = "You need to assign a collection name to \"#{name || 'Class'}.collection_name\""
181
209
  raise ArgumentError, message unless @collection_name.present?
182
210
  @collection_name
183
211
  end
@@ -219,6 +247,10 @@ end"
219
247
  def #{attribute_name}_change
220
248
  __doc__body_attribute_change('#{attribute_name}')
221
249
  end
250
+
251
+ def #{attribute_name}_will_change!
252
+ (__doc__body_will_change! || {})['#{attribute_name}']
253
+ end
222
254
  RUBY
223
255
  end
224
256
  end
@@ -1,3 +1,3 @@
1
1
  module PostJson
2
- VERSION = "1.0.10"
2
+ VERSION = "1.0.11"
3
3
  end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Base model as superclass" do
4
+ class ChildModel < PostJson::Collection["children"]
5
+ def name=(value)
6
+ super(value.to_s.upcase)
7
+ end
8
+ end
9
+
10
+ subject { ChildModel }
11
+
12
+ its(:collection_name) { should == "children" }
13
+
14
+ context "document" do
15
+ let(:name) { "jacob" }
16
+ subject { ChildModel.create(name: name) }
17
+ its(:name) { should == name.upcase }
18
+ end
19
+ 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.10
4
+ version: 1.0.11
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-23 00:00:00.000000000 Z
11
+ date: 2013-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -80,8 +80,8 @@ dependencies:
80
80
  - - ~>
81
81
  - !ruby/object:Gem::Version
82
82
  version: '2.0'
83
- description: Fast and flexible Document database by combining features of PostgreSQL
84
- with PLV8 and Ruby
83
+ description: A Fast and Flexible Document Database by Combining Features of Ruby and
84
+ PostgreSQL with PLV8
85
85
  email:
86
86
  - hello@webnuts.com
87
87
  executables: []
@@ -112,6 +112,7 @@ files:
112
112
  - lib/post_json/base.rb
113
113
  - spec/models/base_spec.rb
114
114
  - spec/models/queries_spec.rb
115
+ - spec/models/derived_base_spec.rb
115
116
  - spec/models/collection_spec.rb
116
117
  - spec/spec_helper.rb
117
118
  - spec/dummy/app/helpers/application_helper.rb