surus 0.5.1 → 0.6.0

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: 8c16570a2c0344b5f4294041a7a6b6e0e5d03674
4
- data.tar.gz: b28d6a4a328a01228cbaef0eb6d2024199e5cd64
3
+ metadata.gz: cd4bbbf8c57e01cfb2627d2b0a3913006f1432c7
4
+ data.tar.gz: 73504b7836c48ee52f43d62f91d93eeb0f52e733
5
5
  SHA512:
6
- metadata.gz: d610452b370a09fa5ae3b3a131e17439d52b625b827924cc15cc17d226b6df86f2310feed010028dda5541c675e5e36b5eab196dcca0123a8a6411108f922916
7
- data.tar.gz: 7ba624e05ff271e1b4587c16101adba2616b5e070ae35415dc96221a542eb33a67537f8492777049afed5d676cd6f6c8181ec020b31ed403031068ad29400d76
6
+ metadata.gz: ce79c2dabce1600a7a3503f992cd735e7eac90fd59c65ad557ee5a55e58cde0eb0eebfb91a8be97456479ca31c0efe88375b3cc0e8ae8f9ac7e699faf7b8cef0
7
+ data.tar.gz: 498d6d89a59f5c2d49d0119a94ec76429a7a589f398050ab3a22824264ada83c886017f7e7e9632188fd8f37eccda0f585eeca579610cea9f7a8ab87a00966fa
@@ -0,0 +1,17 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
4
+ - 2.1.5
5
+ - 2.0.0
6
+ gemfile:
7
+ - gemfiles/4.0.gemfile
8
+ - gemfiles/4.1.gemfile
9
+ - gemfiles/4.2.gemfile
10
+
11
+ addons:
12
+ postgresql: "9.2"
13
+
14
+ before_script:
15
+ - cp spec/database.yml.travis spec/database.yml
16
+ - psql -U postgres -c 'create database surus_test;'
17
+ - psql -U postgres -f spec/database_structure.sql surus_test
@@ -1,3 +1,8 @@
1
+ # 0.6.0 (May 15, 2015)
2
+
3
+ * find_json and all_json support has_one associations (Mathieu Dumont)
4
+ * find_json and all_json preserve "select" scope unless columns or include arguments are present
5
+
1
6
  # 0.5.1 (August 29, 2014)
2
7
 
3
8
  * Quote assocation column names
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  Surus
2
2
  =====
3
3
 
4
+ [![Build Status](https://travis-ci.org/jackc/surus.svg?branch=master)](https://travis-ci.org/jackc/surus)
5
+
4
6
  # Description
5
7
 
6
8
  Surus adds PostgreSQL specific functionality to ActiveRecord. It adds
@@ -14,16 +16,33 @@ substantially faster than converting ActiveRecord objects to JSON.
14
16
 
15
17
  gem install surus
16
18
 
17
- Or add to your Gemfile.
19
+ Or add to your Gemfile. This version of Surus only works on Rails 4.
18
20
 
19
21
  gem 'surus'
20
22
 
21
23
  ## Rails 3
22
24
 
23
- This version of Surus only works on Rails 4. Use the 0.4 line for Rails 3
25
+ Use the 0.4 line for Rails 3
24
26
 
25
27
  gem 'surus', '~> 0.4.2'
26
28
 
29
+ # JSON
30
+
31
+ PostgreSQL 9.2 added `row_to_json` and `array_to_json` functions. These
32
+ functions can be used to build JSON very quickly. Unfortunately, they are
33
+ somewhat cumbersome to use. The `find_json` and `all_json` methods are easy to
34
+ use wrappers around the lower level PostgreSQL functions that closely mimic
35
+ the Rails `to_json` interface.
36
+
37
+ User.find_json 1
38
+ User.find_json 1, columns: [:id, :name, :email]
39
+ Post.find_json 1, include: :author
40
+ User.find_json(user.id, include: {posts: {columns: [:id, :subject]}})
41
+ User.all_json
42
+ User.where(admin: true).all_json
43
+ User.all_json(columns: [:id, :name, :email], include: {posts: {columns: [:id, :subject]}})
44
+ Post.all_json(include: [:forum, :post])
45
+
27
46
  # Hstore
28
47
 
29
48
  Hstores can be searched with helper scopes.
@@ -48,6 +67,22 @@ nested data structures can be serialized to an hstore. In other words, any
48
67
  hash that can be serialized with the normal Rails YAML serialization can be
49
68
  serialized with Surus.
50
69
 
70
+ **Serialize example (Rails 3+)**:
71
+
72
+ ```ruby
73
+ class User < ActiveRecord::Base
74
+ serialize :settings, Surus::Hstore::Serializer.new
75
+ end
76
+ ```
77
+
78
+ **Store example (Rails 4+)**:
79
+
80
+ ```ruby
81
+ class User < ActiveRecord::Base
82
+ store :settings, accessors: [:session_timeout], coder: Surus::Hstore::Serializer.new
83
+ end
84
+ ```
85
+
51
86
  # Array
52
87
 
53
88
  Arrays can be searched with helper scopes.
@@ -79,23 +114,6 @@ entire session or per transaction.
79
114
 
80
115
  Read more in the [PostgreSQL asynchronous commit documentation](http://www.postgresql.org/docs/9.1/interactive/wal-async-commit.html).
81
116
 
82
- # JSON
83
-
84
- PostgreSQL 9.2 added `row_to_json` and `array_to_json` functions. These
85
- functions can be used to build JSON very quickly. Unfortunately, they are
86
- somewhat cumbersome to use. The `find_json` and `all_json` methods are easy to
87
- use wrappers around the lower level PostgreSQL functions that closely mimic
88
- the Rails `to_json` interface.
89
-
90
- User.find_json 1
91
- User.find_json 1, columns: [:id, :name, :email]
92
- Post.find_json 1, include: :author
93
- User.find_json(user.id, include: {posts: {columns: [:id, :subject]}})
94
- User.all_json
95
- User.where(admin: true).all_json
96
- User.all_json(columns: [:id, :name, :email], include: {posts: {columns: [:id, :subject]}})
97
- Post.all_json(include: [:forum, :post])
98
-
99
117
  # Benchmarks
100
118
 
101
119
  JSON generation is with all_json and find_json is substantially faster than to_json.
data/Rakefile CHANGED
@@ -1 +1,11 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
9
+ rescue LoadError
10
+ # no rspec available
11
+ end
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "activerecord", "4.0.0"
4
+
5
+ gemspec :path=>"../"
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "activerecord", "~> 4.1.8"
4
+
5
+ gemspec :path=>"../"
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "activerecord", "~> 4.2.0"
4
+
5
+ gemspec :path=>"../"
@@ -15,7 +15,11 @@ module Surus
15
15
  end
16
16
 
17
17
  def subquery_sql
18
- select(columns.map(&:to_s).join(', ')).to_sql
18
+ if options.key?(:columns) || options.key?(:include)
19
+ select(columns.map(&:to_s).join(', ')).to_sql
20
+ else
21
+ original_scope.to_sql
22
+ end
19
23
  end
20
24
 
21
25
  def columns
@@ -39,10 +43,32 @@ module Surus
39
43
  def association_columns
40
44
  included_associations_name_and_options.map do |association_name, association_options|
41
45
  association = klass.reflect_on_association association_name
42
- subquery = case association.source_macro
46
+
47
+ # The way to get the association type is different in Rails 4.2 vs 4.0-4.1
48
+ association_type = if defined? ActiveRecord::Reflection::BelongsToReflection
49
+ # Rails 4.2+
50
+ case association
51
+ when ActiveRecord::Reflection::HasOneReflection
52
+ :has_one
53
+ when ActiveRecord::Reflection::BelongsToReflection
54
+ :belongs_to
55
+ when ActiveRecord::Reflection::HasManyReflection
56
+ :has_many
57
+ when ActiveRecord::Reflection::HasAndBelongsToManyReflection
58
+ :has_and_belongs_to_many
59
+ end
60
+ else
61
+ # Rails 4.0-4.1
62
+ association.source_macro
63
+ end
64
+
65
+ subquery = case association_type
43
66
  when :belongs_to
44
67
  association_scope = BelongsToScopeBuilder.new(original_scope, association).scope
45
68
  RowQuery.new(association_scope, association_options).to_sql
69
+ when :has_one
70
+ association_scope = HasManyScopeBuilder.new(original_scope, association).scope
71
+ RowQuery.new(association_scope, association_options).to_sql
46
72
  when :has_many
47
73
  association_scope = HasManyScopeBuilder.new(original_scope, association).scope
48
74
  ArrayAggQuery.new(association_scope, association_options).to_sql
@@ -1,3 +1,3 @@
1
1
  module Surus
2
- VERSION = "0.5.1"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -2,3 +2,4 @@ test:
2
2
  adapter: postgresql
3
3
  encoding: unicode
4
4
  database: surus_test
5
+
@@ -0,0 +1,5 @@
1
+ test:
2
+ adapter: postgresql
3
+ encoding: unicode
4
+ username: postgres
5
+ database: surus_test
@@ -62,6 +62,27 @@ CREATE TABLE users(
62
62
 
63
63
 
64
64
 
65
+ DROP TABLE IF EXISTS bios CASCADE;
66
+
67
+ CREATE TABLE bios(
68
+ id serial PRIMARY KEY,
69
+ body text NOT NULL,
70
+ website_url varchar NOT NULL,
71
+ author_id integer NOT NULL REFERENCES users
72
+ );
73
+
74
+
75
+
76
+ DROP TABLE IF EXISTS avatars CASCADE;
77
+
78
+ CREATE TABLE avatars(
79
+ id serial PRIMARY KEY,
80
+ url varchar NOT NULL,
81
+ author_id integer NOT NULL REFERENCES users
82
+ );
83
+
84
+
85
+
65
86
  DROP TABLE IF EXISTS forums CASCADE;
66
87
 
67
88
  CREATE TABLE forums(
@@ -98,4 +119,4 @@ CREATE TABLE posts_tags(
98
119
  post_id integer NOT NULL REFERENCES posts,
99
120
  tag_id integer NOT NULL REFERENCES tags,
100
121
  PRIMARY KEY (post_id, tag_id)
101
- );
122
+ );
@@ -17,5 +17,20 @@ FactoryGirl.define do
17
17
  factory :user, aliases: [:author] do
18
18
  name { Faker::Internet.user_name }
19
19
  email { Faker::Internet.email }
20
+ after(:build) do |user|
21
+ user.bio ||= FactoryGirl.build(:bio, author: user)
22
+ user.avatar ||= FactoryGirl.build(:avatar, author: user)
23
+ end
24
+ end
25
+
26
+ factory :bio do
27
+ author
28
+ body { Faker::Lorem.paragraph }
29
+ website_url { Faker::Internet.url }
30
+ end
31
+
32
+ factory :avatar do
33
+ author
34
+ url { Faker::Avatar.image }
20
35
  end
21
36
  end
@@ -22,6 +22,15 @@ describe 'json' do
22
22
  end
23
23
  end
24
24
 
25
+ context 'when scope chain has select' do
26
+ it 'uses the select for json' do
27
+ user = FactoryGirl.create :user
28
+ to_json = Oj.load user.to_json only: [:id, :name]
29
+ find_json = Oj.load User.select("id, name").find_json(user.id)
30
+ expect(find_json).to eq(to_json)
31
+ end
32
+ end
33
+
25
34
  context 'when scope chain has a joins with ambiguous column names' do
26
35
  it 'works' do
27
36
  user = FactoryGirl.create :user
@@ -60,6 +69,33 @@ describe 'json' do
60
69
  expect(find_json).to eq(to_json)
61
70
  end
62
71
 
72
+ it 'includes entire has_one object' do
73
+ user = FactoryGirl.create :user
74
+ to_json = Oj.load user.to_json(include: :bio)
75
+ find_json = Oj.load User.find_json(user.id, include: :bio)
76
+ expect(find_json).to eq(to_json)
77
+ end
78
+
79
+ it 'filters by has_one conditions' do
80
+ user = FactoryGirl.create :user
81
+ find_json = Oj.load User.find_json(user.id, include: :bio_with_impossible_conditions)
82
+ expect(find_json.fetch('bio_with_impossible_conditions')).to be_nil
83
+ end
84
+
85
+ it 'includes multiple entire has_one objects' do
86
+ user = FactoryGirl.create :user
87
+ to_json = Oj.load user.to_json(include: [:bio, :avatar])
88
+ find_json = Oj.load User.find_json(user.id, include: [:bio, :avatar])
89
+ expect(find_json).to eq(to_json)
90
+ end
91
+
92
+ it 'includes only selected columns of has_one object' do
93
+ user = FactoryGirl.create :user
94
+ to_json = Oj.load user.to_json(include: {bio: {only: [:id, :body]}})
95
+ find_json = Oj.load User.find_json(user.id, include: {bio: {columns: [:id, :body]}})
96
+ expect(find_json).to eq(to_json)
97
+ end
98
+
63
99
  it 'includes entire has_many association' do
64
100
  user = FactoryGirl.create :user
65
101
  posts = FactoryGirl.create_list :post, 2, author: user
@@ -168,5 +204,14 @@ describe 'json' do
168
204
  all_json = Oj.load User.all_json
169
205
  expect(all_json).to eq(to_json)
170
206
  end
207
+
208
+ context 'when scope chain has select' do
209
+ it 'uses the select for json' do
210
+ users = FactoryGirl.create_list :user, 3
211
+ to_json = Oj.load users.to_json only: [:id, :name]
212
+ all_json = Oj.load User.select("id, name").all_json
213
+ expect(all_json).to eq(to_json)
214
+ end
215
+ end
171
216
  end
172
217
  end
@@ -30,6 +30,21 @@ class User < ActiveRecord::Base
30
30
 
31
31
  # association name is reserved word in PostgreSQL
32
32
  has_many :rows, foreign_key: :author_id, class_name: 'Post', table_name: 'posts'
33
+
34
+ has_one :bio, foreign_key: :author_id
35
+ has_one :avatar, foreign_key: :author_id
36
+ has_one :bio_with_impossible_conditions,
37
+ -> { where '1=2' },
38
+ foreign_key: :author_id,
39
+ class_name: 'Bio'
40
+ end
41
+
42
+ class Bio < ActiveRecord::Base
43
+ belongs_to :author, class_name: 'User'
44
+ end
45
+
46
+ class Avatar < ActiveRecord::Base
47
+ belongs_to :author, class_name: 'User'
33
48
  end
34
49
 
35
50
  class Forum < ActiveRecord::Base
@@ -2,18 +2,18 @@ require 'spec_helper'
2
2
 
3
3
  describe Surus::SynchronousCommit::Model do
4
4
  let(:conn) { ActiveRecord::Base.connection }
5
-
5
+
6
6
  describe "synchronous_commit" do
7
7
  it "is delegated to connection" do
8
- conn.should_receive(:synchronous_commit)
8
+ expect(conn).to receive(:synchronous_commit)
9
9
  ActiveRecord::Base.synchronous_commit
10
10
  end
11
11
  end
12
-
12
+
13
13
  describe "synchronous_commit=" do
14
14
  it "is delegated to connection" do
15
- conn.should_receive(:synchronous_commit=)
15
+ expect(conn).to receive(:synchronous_commit=)
16
16
  ActiveRecord::Base.synchronous_commit = true
17
17
  end
18
- end
18
+ end
19
19
  end
@@ -34,5 +34,6 @@ Gem::Specification.new do |s|
34
34
  s.add_development_dependency 'pg'
35
35
  s.add_development_dependency 'pry', '~> 0.9.11'
36
36
  s.add_development_dependency 'factory_girl', '~> 4.2.0'
37
- s.add_development_dependency 'faker', '~> 1.1.2'
37
+ s.add_development_dependency 'faker', '~> 1.4.3'
38
+ s.add_development_dependency 'rake'
38
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: surus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jack Christensen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-29 00:00:00.000000000 Z
11
+ date: 2015-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -142,14 +142,28 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 1.1.2
145
+ version: 1.4.3
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 1.1.2
152
+ version: 1.4.3
153
+ - !ruby/object:Gem::Dependency
154
+ name: rake
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
153
167
  description: "Surus accelerates ActiveRecord with PostgreSQL specific types and\n
154
168
  \ functionality. It enables indexed searching of serialized arrays
155
169
  and hashes.\n It also can control PostgreSQL synchronous commit
@@ -163,6 +177,7 @@ extra_rdoc_files: []
163
177
  files:
164
178
  - ".gitignore"
165
179
  - ".rspec"
180
+ - ".travis.yml"
166
181
  - CHANGELOG.md
167
182
  - Gemfile
168
183
  - Guardfile
@@ -175,6 +190,9 @@ files:
175
190
  - bench/hstore_find.rb
176
191
  - bench/json_generation.rb
177
192
  - bench/synchronous_commit.rb
193
+ - gemfiles/4.0.gemfile
194
+ - gemfiles/4.1.gemfile
195
+ - gemfiles/4.2.gemfile
178
196
  - lib/generators/surus/hstore/install_generator.rb
179
197
  - lib/generators/surus/hstore/templates/install_hstore.rb
180
198
  - lib/surus.rb
@@ -194,6 +212,7 @@ files:
194
212
  - lib/surus/version.rb
195
213
  - spec/array/scope_spec.rb
196
214
  - spec/database.yml
215
+ - spec/database.yml.travis
197
216
  - spec/database_structure.sql
198
217
  - spec/factories.rb
199
218
  - spec/hstore/scope_spec.rb
@@ -224,13 +243,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
243
  version: '0'
225
244
  requirements: []
226
245
  rubyforge_project: ''
227
- rubygems_version: 2.2.2
246
+ rubygems_version: 2.4.5
228
247
  signing_key:
229
248
  specification_version: 4
230
249
  summary: PostgreSQL Acceleration for ActiveRecord
231
250
  test_files:
232
251
  - spec/array/scope_spec.rb
233
252
  - spec/database.yml
253
+ - spec/database.yml.travis
234
254
  - spec/database_structure.sql
235
255
  - spec/factories.rb
236
256
  - spec/hstore/scope_spec.rb