unscoped_associations 0.6.5 → 0.7.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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +18 -1
- data/Appraisals +19 -0
- data/LICENSE +1 -1
- data/README.md +47 -17
- data/gemfiles/activerecord_3.2.gemfile +7 -0
- data/gemfiles/activerecord_4.0.gemfile +7 -0
- data/gemfiles/activerecord_4.1.gemfile +7 -0
- data/gemfiles/activerecord_4.2.gemfile +7 -0
- data/gemfiles/activerecord_5.0.gemfile +7 -0
- data/lib/unscoped_associations.rb +11 -12
- data/lib/unscoped_associations/version.rb +1 -1
- data/spec/spec_helper.rb +2 -4
- data/spec/support/models.rb +7 -2
- data/spec/unscoped_associations_spec.rb +9 -3
- data/unscoped_associations.gemspec +5 -3
- metadata +44 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 073c884846d75afaa72c4d70c5b085e59cfbd5cc
|
4
|
+
data.tar.gz: 1646ec2a8addf850400b89601622caa1205be995
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ded23dbed093edd84b46c97ef0a1bd0ea764681a083d945f6fb37bf824f067e7cc97c00590097bf871e7b5d2a4f7a83611311d8350db39b83d3f8560d7e2411
|
7
|
+
data.tar.gz: 46028f5d2bb6f15d8da7bb320c9a31c5b749e5ac070b93d1bc74152db731abc13839a5a4f0e9a02892e715436794dd1509ab68d6fb16c0a8334f16f69c5e078c
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
language: ruby
|
2
|
+
sudo: false
|
2
3
|
rvm:
|
4
|
+
- 2.3.3
|
5
|
+
- 2.2.6
|
3
6
|
- 2.1
|
4
7
|
- 2.0
|
5
|
-
- 1.9.3
|
8
|
+
- 1.9.3
|
9
|
+
gemfile:
|
10
|
+
- gemfiles/activerecord_5.0.gemfile
|
11
|
+
- gemfiles/activerecord_4.2.gemfile
|
12
|
+
- gemfiles/activerecord_4.1.gemfile
|
13
|
+
- gemfiles/activerecord_4.0.gemfile
|
14
|
+
- gemfiles/activerecord_3.2.gemfile
|
15
|
+
matrix:
|
16
|
+
exclude:
|
17
|
+
- rvm: 1.9.3
|
18
|
+
gemfile: gemfiles/activerecord_5.0.gemfile
|
19
|
+
- rvm: 2.0
|
20
|
+
gemfile: gemfiles/activerecord_5.0.gemfile
|
21
|
+
- rvm: 2.1
|
22
|
+
gemfile: gemfiles/activerecord_5.0.gemfile
|
data/Appraisals
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
appraise "activerecord-5.0" do
|
2
|
+
gem "activerecord", "~> 5.0.0"
|
3
|
+
end
|
4
|
+
|
5
|
+
appraise "activerecord-4.2" do
|
6
|
+
gem "activerecord", "~> 4.2.0"
|
7
|
+
end
|
8
|
+
|
9
|
+
appraise "activerecord-4.1" do
|
10
|
+
gem "activerecord", "~> 4.1.0"
|
11
|
+
end
|
12
|
+
|
13
|
+
appraise "activerecord-4.0" do
|
14
|
+
gem "activerecord", "~> 4.0.0"
|
15
|
+
end
|
16
|
+
|
17
|
+
appraise "activerecord-3.2" do
|
18
|
+
gem "activerecord", "~> 3.2.0"
|
19
|
+
end
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -3,10 +3,15 @@
|
|
3
3
|
[](http://badge.fury.io/rb/unscoped_associations)
|
4
4
|
[](https://travis-ci.org/markets/unscoped_associations)
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
Have you ever needed to skip the `default_scope` when fetching objects through associations methods (for some strange reasons)? Do it easily with this `Active Record` extension!
|
7
|
+
|
8
|
+
Supported associations:
|
9
|
+
|
10
|
+
- `:belongs_to`
|
11
|
+
- `:has_one`
|
12
|
+
- `:has_many`
|
13
|
+
|
14
|
+
Officially supported (tested) `Active Record` versions: 3.2, 4.0, 4.1, 4.2 and 5.0.
|
10
15
|
|
11
16
|
## Installation
|
12
17
|
|
@@ -28,9 +33,8 @@ Basic usage example:
|
|
28
33
|
|
29
34
|
```ruby
|
30
35
|
class User < ActiveRecord::Base
|
31
|
-
has_many :comments
|
36
|
+
has_many :comments
|
32
37
|
has_many :all_comments, class_name: 'Comment', unscoped: true
|
33
|
-
has_one :last_comment, class_name: 'Comment', order: 'created_at DESC', unscoped: true
|
34
38
|
|
35
39
|
default_scope { where(active: true) }
|
36
40
|
end
|
@@ -40,32 +44,58 @@ class Comment < ActiveRecord::Base
|
|
40
44
|
|
41
45
|
default_scope { where(public: true) }
|
42
46
|
end
|
47
|
+
```
|
43
48
|
|
44
|
-
|
45
|
-
@user.all_comments # => return all comments skipping default_scope
|
46
|
-
@user.last_comment # => return last comment skipping default_scope
|
47
|
-
@comment.user # => return user w/o taking account 'active' flag
|
49
|
+
From now on, you get:
|
48
50
|
|
49
|
-
|
51
|
+
- `@user.comments`: return all public comments
|
52
|
+
- `@user.all_comments`: return all comments skipping the default_scope
|
53
|
+
- `@comment.user`: return the user without taking account the 'active' flag
|
50
54
|
|
51
55
|
## Status
|
52
56
|
|
53
|
-
|
57
|
+
This project was originally thought and built for a Rails 3.2 application.
|
54
58
|
|
55
|
-
|
59
|
+
Rails 4 introduces some updates regarding associations. For example, since Rails 4 (AR 4 to be precise), you are able to customize associations using a scope block (overriding conditions), so you can skip the `default_scope` conditions by:
|
56
60
|
|
57
|
-
```
|
61
|
+
```ruby
|
58
62
|
class User < ActiveRecord::Base
|
59
63
|
has_many :all_comments, -> { where(public: [true, false]) }, class_name: 'Comment'
|
60
64
|
end
|
61
65
|
```
|
62
66
|
|
63
|
-
|
67
|
+
Since Rails 4.1, you can also override the default conditions using the `unscope` method:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
class User < ActiveRecord::Base
|
71
|
+
has_many :all_comments, -> { unscope(where: :public) }, class_name: 'Comment'
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
Anyway, you can continue using `unscoped_associations`, could be useful in certain situations, for example, if you prefer to bypass the entire `default_scope`, given a scope with multiple conditions, like:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
default_scope { where(public: true).order(:updated_at) }
|
79
|
+
```
|
80
|
+
|
81
|
+
It was also supported for Rails 4.X series and 5.0 as a migration path.
|
82
|
+
|
83
|
+
## Notes
|
84
|
+
|
85
|
+
- Under the hood, Unscoped Associations relies on the `unscoped` method (from AR). So, chaining unscoped associations with other AR query methods won't work. E.g.: `@user.all_comments.count` will load comments with the `defaul_scope` applied. In this case, `@user.all_comments.to_a.count` should work.
|
86
|
+
- Unscoped Associations doen't touch the preloading layer, so `includes`, `joins`, ... with unscoped associations, can cause `N+1` problems.
|
64
87
|
|
65
88
|
## Contributing
|
66
89
|
|
67
|
-
|
90
|
+
Any kind of fixes, both code and docs, or enhancements are really welcome!
|
91
|
+
|
92
|
+
To contribute, just fork the repo, hack on it and send a pull request. Don't forget to add specs for behaviour changes and run the tests by:
|
93
|
+
|
94
|
+
```
|
95
|
+
bundle exec rspec
|
96
|
+
bundle exec appraisal rspec # run against all supported AR versions
|
97
|
+
```
|
68
98
|
|
69
99
|
## License
|
70
100
|
|
71
|
-
Copyright (c)
|
101
|
+
Copyright (c) Marc Anguera. Unscoped Associations is released under the [MIT](LICENSE) License.
|
@@ -3,7 +3,7 @@ require 'unscoped_associations/version'
|
|
3
3
|
module UnscopedAssociations
|
4
4
|
def self.included(base)
|
5
5
|
base.extend ClassMethods
|
6
|
-
|
6
|
+
class << base
|
7
7
|
alias_method_chain :belongs_to, :unscoped
|
8
8
|
alias_method_chain :has_many, :unscoped
|
9
9
|
alias_method_chain :has_one, :unscoped
|
@@ -36,26 +36,25 @@ module UnscopedAssociations
|
|
36
36
|
end
|
37
37
|
|
38
38
|
if scope
|
39
|
-
|
39
|
+
send("#{assoc_type}_without_unscoped", assoc_name, scope, options, &extension)
|
40
40
|
else
|
41
|
-
|
41
|
+
send("#{assoc_type}_without_unscoped", assoc_name, options, &extension)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
def add_unscoped_association(association_name)
|
46
|
-
define_method(association_name) do
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
46
|
+
define_method(association_name) do |*args|
|
47
|
+
force_reload = args[0]
|
48
|
+
if !force_reload && instance_variable_get("@_cache_#{association_name}")
|
49
|
+
instance_variable_get("@_cache_#{association_name}")
|
51
50
|
else
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
instance_variable_set("@_cache_#{association_name}",
|
52
|
+
association(association_name).klass.unscoped { super(true) }
|
53
|
+
)
|
55
54
|
end
|
56
55
|
end
|
57
56
|
end
|
58
57
|
end
|
59
58
|
end
|
60
59
|
|
61
|
-
ActiveRecord::Base.
|
60
|
+
ActiveRecord::Base.send(:include, UnscopedAssociations)
|
data/spec/spec_helper.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
-
|
4
1
|
require 'active_record'
|
2
|
+
require 'logger'
|
5
3
|
require 'unscoped_associations'
|
6
4
|
|
7
5
|
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
8
6
|
|
9
|
-
Dir["./spec/support/**/*.rb"].sort.each {|f| require f}
|
7
|
+
Dir["./spec/support/**/*.rb"].sort.each { |f| require f}
|
10
8
|
|
11
9
|
RSpec.configure do |config|
|
12
10
|
config.run_all_when_everything_filtered = true
|
data/spec/support/models.rb
CHANGED
@@ -11,8 +11,13 @@ class User < ActiveRecord::Base
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
15
|
+
has_one :last_comment, -> { order('created_at DESC') }, class_name: 'Comment'
|
16
|
+
has_one :unscoped_last_comment, -> { order('created_at DESC') }, class_name: 'Comment', unscoped: true
|
17
|
+
else
|
18
|
+
has_one :last_comment, class_name: 'Comment', order: ('created_at DESC')
|
19
|
+
has_one :unscoped_last_comment, class_name: 'Comment', unscoped: true, order: ('created_at DESC')
|
20
|
+
end
|
16
21
|
|
17
22
|
has_many :votes, as: :votable, unscoped: true
|
18
23
|
|
@@ -2,9 +2,9 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe UnscopedAssociations do
|
4
4
|
let!(:user) { User.create(active: false) }
|
5
|
-
let!(:comment) { Comment.create(
|
6
|
-
let!(:user_vote) {
|
7
|
-
let!(:comment_vote) {
|
5
|
+
let!(:comment) { Comment.create(unscoped_user: user, public: false) }
|
6
|
+
let!(:user_vote) { Vote.create(votable: user, public: false) }
|
7
|
+
let!(:comment_vote) { Vote.create(votable: comment) }
|
8
8
|
|
9
9
|
context 'a belongs to association' do
|
10
10
|
it 'scoped' do
|
@@ -44,6 +44,12 @@ describe UnscopedAssociations do
|
|
44
44
|
expect(user.unscoped_comments).to eq([comment])
|
45
45
|
end
|
46
46
|
|
47
|
+
it 'unscoped accepts force_reload' do
|
48
|
+
comments_count = user.unscoped_comments.to_a.count
|
49
|
+
Comment.create(unscoped_user: user, public: false)
|
50
|
+
expect(user.unscoped_comments(true).to_a.count).to eq(comments_count + 1)
|
51
|
+
end
|
52
|
+
|
47
53
|
it 'unscoped with an extension' do
|
48
54
|
# Extended methods take the default_scope
|
49
55
|
expect(user.unscoped_comments.today).to be_empty
|
@@ -6,8 +6,8 @@ Gem::Specification.new do |spec|
|
|
6
6
|
spec.version = UnscopedAssociations::VERSION
|
7
7
|
spec.authors = ["Marc Anguera Insa"]
|
8
8
|
spec.email = ["srmarc.ai@gmail.com"]
|
9
|
-
spec.description =
|
10
|
-
spec.summary =
|
9
|
+
spec.description = "Skip default_scope in your associations"
|
10
|
+
spec.summary = "Skip default_scope in your associations"
|
11
11
|
spec.homepage = "https://github.com/markets/unscoped_associations"
|
12
12
|
spec.license = "MIT"
|
13
13
|
|
@@ -16,10 +16,12 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
17
|
spec.require_paths = ["lib"]
|
18
18
|
|
19
|
-
spec.add_dependency "activerecord", ">= 0"
|
19
|
+
spec.add_dependency "activerecord", ">= 3.2.0", "<= 5.1.0"
|
20
20
|
|
21
|
+
spec.add_development_dependency "appraisal"
|
21
22
|
spec.add_development_dependency "rake"
|
22
23
|
spec.add_development_dependency "rspec", '~> 3.1'
|
23
24
|
spec.add_development_dependency "sqlite3"
|
25
|
+
spec.add_development_dependency "byebug" if RUBY_VERSION.to_i >= 2
|
24
26
|
end
|
25
27
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unscoped_associations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc Anguera Insa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,9 +16,29 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 3.2.0
|
20
|
+
- - "<="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 5.1.0
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.2.0
|
30
|
+
- - "<="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 5.1.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: appraisal
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
22
42
|
version_requirements: !ruby/object:Gem::Requirement
|
23
43
|
requirements:
|
24
44
|
- - ">="
|
@@ -66,6 +86,20 @@ dependencies:
|
|
66
86
|
- - ">="
|
67
87
|
- !ruby/object:Gem::Version
|
68
88
|
version: '0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: byebug
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
69
103
|
description: Skip default_scope in your associations
|
70
104
|
email:
|
71
105
|
- srmarc.ai@gmail.com
|
@@ -75,10 +109,16 @@ extra_rdoc_files: []
|
|
75
109
|
files:
|
76
110
|
- ".gitignore"
|
77
111
|
- ".travis.yml"
|
112
|
+
- Appraisals
|
78
113
|
- Gemfile
|
79
114
|
- LICENSE
|
80
115
|
- README.md
|
81
116
|
- Rakefile
|
117
|
+
- gemfiles/activerecord_3.2.gemfile
|
118
|
+
- gemfiles/activerecord_4.0.gemfile
|
119
|
+
- gemfiles/activerecord_4.1.gemfile
|
120
|
+
- gemfiles/activerecord_4.2.gemfile
|
121
|
+
- gemfiles/activerecord_5.0.gemfile
|
82
122
|
- lib/unscoped_associations.rb
|
83
123
|
- lib/unscoped_associations/version.rb
|
84
124
|
- spec/spec_helper.rb
|
@@ -106,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
146
|
version: '0'
|
107
147
|
requirements: []
|
108
148
|
rubyforge_project:
|
109
|
-
rubygems_version: 2.
|
149
|
+
rubygems_version: 2.4.5
|
110
150
|
signing_key:
|
111
151
|
specification_version: 4
|
112
152
|
summary: Skip default_scope in your associations
|