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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2cd5582dcc1e8d3a4fe22a00bd5d1a93a6466df5
4
- data.tar.gz: 21129a908c3f75f70462e000b7e145d8a8dd57be
3
+ metadata.gz: 073c884846d75afaa72c4d70c5b085e59cfbd5cc
4
+ data.tar.gz: 1646ec2a8addf850400b89601622caa1205be995
5
5
  SHA512:
6
- metadata.gz: 7e39f18b8aefb84c2e4fd288f6706367397bf08e8a89cfb8945a82b4339cde54f72306a2441391077b09a10cbbb9df4b6bf51319549b6efe714211245953ac14
7
- data.tar.gz: 19574587b4d3d79b10513e26d022938e7ba57717be501712d5bb662e42c28bcfa0aa4b87acfcc68b879335858c46abf95b5345db22180fdb48ee7267f2a20bfa
6
+ metadata.gz: 5ded23dbed093edd84b46c97ef0a1bd0ea764681a083d945f6fb37bf824f067e7cc97c00590097bf871e7b5d2a4f7a83611311d8350db39b83d3f8560d7e2411
7
+ data.tar.gz: 46028f5d2bb6f15d8da7bb320c9a31c5b749e5ac070b93d1bc74152db731abc13839a5a4f0e9a02892e715436794dd1509ab68d6fb16c0a8334f16f69c5e078c
data/.gitignore CHANGED
@@ -2,3 +2,5 @@
2
2
  pkg
3
3
  .rvmrc
4
4
  Gemfile.lock
5
+ *.gemfile.lock
6
+ .byebug_history
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
@@ -1,4 +1,4 @@
1
- Copyright 2013-2014 Marc Anguera Insa
1
+ Copyright 2013-2017 Marc Anguera Insa
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -3,10 +3,15 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/unscoped_associations.svg)](http://badge.fury.io/rb/unscoped_associations)
4
4
  [![Build Status](https://travis-ci.org/markets/unscoped_associations.svg?branch=master)](https://travis-ci.org/markets/unscoped_associations)
5
5
 
6
- Want to skip the `default_scope` when you get objects through associations (for some strange reasons)? Do it easily with this lib. Supported associations:
7
- * `:belongs_to`
8
- * `:has_one`
9
- * `:has_many`
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 # or , unscoped: false
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
- @user.comments # => return public comments
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
- Tested on Rails 3 series and Rails 4. Originally was thought and built for Rails 3, but Rails 4 is also supported.
57
+ This project was originally thought and built for a Rails 3.2 application.
54
58
 
55
- **NOTE** Rails 4 introduces some updates (and more planned for upcoming releases) related to this part. For example, in Rails 4, you are able to customize associations using a scope block, so you can skip the `default_scope` by:
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
- Anyway, you can use `unscoped` option, if you prefer.
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
- Ideas, fixes, improvements or any comment are welcome!
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) 2013-2014 Marc Anguera. Unscoped Associations is released under the [MIT](LICENSE) License.
101
+ Copyright (c) Marc Anguera. Unscoped Associations is released under the [MIT](LICENSE) License.
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 3.2.0"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 4.0.0"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 4.1.0"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 4.2.0"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.0.0"
6
+
7
+ gemspec :path => "../"
@@ -3,7 +3,7 @@ require 'unscoped_associations/version'
3
3
  module UnscopedAssociations
4
4
  def self.included(base)
5
5
  base.extend ClassMethods
6
- (class << base; self; end).instance_eval do
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
- self.send("#{assoc_type}_without_unscoped", assoc_name, scope, options, &extension)
39
+ send("#{assoc_type}_without_unscoped", assoc_name, scope, options, &extension)
40
40
  else
41
- self.send("#{assoc_type}_without_unscoped", assoc_name, options, &extension)
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
- if self.class.reflect_on_association(association_name).options.key?(:polymorphic)
48
- self.association(association_name).klass.unscoped do
49
- super(association_name)
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
- self.class.reflect_on_association(association_name).klass.unscoped do
53
- super(association_name)
54
- end
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.instance_eval { include UnscopedAssociations }
60
+ ActiveRecord::Base.send(:include, UnscopedAssociations)
@@ -1,3 +1,3 @@
1
1
  module UnscopedAssociations
2
- VERSION = "0.6.5"
2
+ VERSION = "0.7.0"
3
3
  end
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
@@ -11,8 +11,13 @@ class User < ActiveRecord::Base
11
11
  end
12
12
  end
13
13
 
14
- has_one :last_comment, class_name: 'Comment', order: 'created_at DESC'
15
- has_one :unscoped_last_comment, class_name: 'Comment', order: 'created_at DESC', unscoped: true
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(user_id: user.id, public: false) }
6
- let!(:user_vote) { user.votes.create(public: false) }
7
- let!(:comment_vote) { comment.votes.create }
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 = %q{Skip default_scope in your associations}
10
- spec.summary = %q{Skip default_scope in your associations}
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.6.5
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: 2014-09-15 00:00:00.000000000 Z
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: '0'
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.2.0
149
+ rubygems_version: 2.4.5
110
150
  signing_key:
111
151
  specification_version: 4
112
152
  summary: Skip default_scope in your associations