scoped_associations 0.1.0 → 0.1.2
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/.travis.yml +17 -0
- data/Appraisals +8 -0
- data/gemfiles/activerecord50.gemfile +8 -0
- data/gemfiles/activerecord51.gemfile +8 -0
- data/lib/scoped_associations/activerecord5/has_many.rb +57 -0
- data/lib/scoped_associations/activerecord5/has_one.rb +57 -0
- data/lib/scoped_associations/version.rb +1 -1
- data/lib/scoped_associations.rb +4 -5
- data/scoped_associations.gemspec +1 -1
- data/spec/spec_helper.rb +14 -37
- metadata +9 -7
- data/spec/integration_spec.rb +0 -186
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c920f87d0a7b46ba8aa7031eb49201b5be9b36f
|
4
|
+
data.tar.gz: 6f146f97633e3611894daa4e832f257cab5dfa28
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67099c7e7d825ec9253952c4e890801f145f259598d58604207e756bfc3fac0b3f18012e3799c743f80f4a5391bdbec76659644b11aff2c53bfb2c0b7120c049
|
7
|
+
data.tar.gz: 5b270420fbcd6612de18a6b0087d505e11f17b9085c3e48f2d921a60233b753befe3d1462e1bad75ec2d2c9a0876cd1ad95858871c1f9ad90d4389a3fffe0704
|
data/.travis.yml
CHANGED
@@ -4,10 +4,27 @@ rvm:
|
|
4
4
|
- "1.9.3"
|
5
5
|
- "2.0.0"
|
6
6
|
- "2.2.2"
|
7
|
+
- "2.3.0"
|
7
8
|
|
8
9
|
gemfile:
|
9
10
|
- "gemfiles/activerecord40.gemfile"
|
10
11
|
- "gemfiles/activerecord41.gemfile"
|
11
12
|
- "gemfiles/activerecord42.gemfile"
|
13
|
+
- "gemfiles/activerecord50.gemfile"
|
14
|
+
- "gemfiles/activerecord51.gemfile"
|
15
|
+
|
16
|
+
matrix:
|
17
|
+
exclude:
|
18
|
+
- rvm: "1.9.3"
|
19
|
+
gemfile: "gemfiles/activerecord50.gemfile"
|
20
|
+
- rvm: "1.9.3"
|
21
|
+
gemfile: "gemfiles/activerecord51.gemfile"
|
22
|
+
- rvm: "2.0.0"
|
23
|
+
gemfile: "gemfiles/activerecord50.gemfile"
|
24
|
+
- rvm: "2.0.0"
|
25
|
+
gemfile: "gemfiles/activerecord51.gemfile"
|
26
|
+
|
27
|
+
before_install:
|
28
|
+
- gem install bundler
|
12
29
|
|
13
30
|
script: "bundle exec rake spec"
|
data/Appraisals
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
module ScopedAssociations
|
2
|
+
module ActiveRecord5
|
3
|
+
module HasManyClassMethods
|
4
|
+
def valid_options(options)
|
5
|
+
super + [:scoped]
|
6
|
+
end
|
7
|
+
|
8
|
+
def build(model, name, scope, options, &block)
|
9
|
+
reflection = super(model, name, scope, options, &block)
|
10
|
+
extend_reflection(reflection)
|
11
|
+
reflection
|
12
|
+
end
|
13
|
+
|
14
|
+
def extend_reflection(reflection)
|
15
|
+
if reflection.options[:scoped]
|
16
|
+
reflection.extend ReflectionExtension
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class ScopedHasManyAssociation < ActiveRecord::Associations::HasManyAssociation
|
21
|
+
def creation_attributes
|
22
|
+
attributes = super
|
23
|
+
attributes[reflection.foreign_scope] = reflection.name.to_s
|
24
|
+
attributes
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module ReflectionExtension
|
29
|
+
def foreign_scope
|
30
|
+
if options[:as]
|
31
|
+
"#{options[:as]}_scope"
|
32
|
+
else
|
33
|
+
name = active_record.name
|
34
|
+
name.underscore.demodulize + "_scope"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def scope
|
39
|
+
old_scope = super
|
40
|
+
scope_conditions = { foreign_scope => name }
|
41
|
+
proc_scope = proc { where(scope_conditions) }
|
42
|
+
if old_scope.nil?
|
43
|
+
proc { instance_eval(&proc_scope) }
|
44
|
+
else
|
45
|
+
proc { instance_eval(&proc_scope).instance_eval(&old_scope) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def association_class
|
50
|
+
ScopedHasManyAssociation
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
ActiveRecord::Associations::Builder::HasMany.send :extend, ScopedAssociations::ActiveRecord5::HasManyClassMethods
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module ScopedAssociations
|
2
|
+
module ActiveRecord5
|
3
|
+
module HasOne
|
4
|
+
def valid_options(options)
|
5
|
+
super + [:scoped]
|
6
|
+
end
|
7
|
+
|
8
|
+
def build(model, name, scope, options, &block)
|
9
|
+
reflection = super(model, name, scope, options, &block)
|
10
|
+
extend_reflection(reflection)
|
11
|
+
reflection
|
12
|
+
end
|
13
|
+
|
14
|
+
def extend_reflection(reflection)
|
15
|
+
if reflection.options[:scoped]
|
16
|
+
reflection.extend ReflectionExtension
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class ScopedHasOneAssociation < ActiveRecord::Associations::HasOneAssociation
|
21
|
+
def creation_attributes
|
22
|
+
attributes = super
|
23
|
+
attributes[reflection.foreign_scope] = reflection.name.to_s
|
24
|
+
attributes
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module ReflectionExtension
|
29
|
+
def foreign_scope
|
30
|
+
if options[:as]
|
31
|
+
"#{options[:as]}_scope"
|
32
|
+
else
|
33
|
+
name = active_record.name
|
34
|
+
name.underscore.demodulize + "_scope"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def scope
|
39
|
+
old_scope = super
|
40
|
+
scope_conditions = { foreign_scope => name }
|
41
|
+
proc_scope = proc { where(scope_conditions) }
|
42
|
+
if old_scope.nil?
|
43
|
+
proc { instance_eval(&proc_scope) }
|
44
|
+
else
|
45
|
+
proc { instance_eval(&proc_scope).instance_eval(&old_scope) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def association_class
|
50
|
+
ScopedHasOneAssociation
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
ActiveRecord::Associations::Builder::HasOne.send :extend, ScopedAssociations::ActiveRecord5::HasOne
|
data/lib/scoped_associations.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
if defined?(ActiveRecord::Base)
|
2
|
-
if ActiveRecord::VERSION::MAJOR ==
|
2
|
+
if ActiveRecord::VERSION::MAJOR == 5
|
3
|
+
require 'scoped_associations/activerecord5/has_many'
|
4
|
+
require 'scoped_associations/activerecord5/has_one'
|
5
|
+
elsif ActiveRecord::VERSION::MAJOR == 4
|
3
6
|
require 'scoped_associations/activerecord4/has_many'
|
4
7
|
require 'scoped_associations/activerecord4/has_one'
|
5
|
-
elsif ActiveRecord::VERSION::MAJOR == 3
|
6
|
-
require 'scoped_associations/activerecord3/has_many'
|
7
|
-
require 'scoped_associations/activerecord3/has_one'
|
8
8
|
end
|
9
9
|
end
|
10
|
-
|
data/scoped_associations.gemspec
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -61,10 +61,7 @@ class Tag < ActiveRecord::Base
|
|
61
61
|
end
|
62
62
|
|
63
63
|
class Post < ActiveRecord::Base
|
64
|
-
has_one :primary_tag, as: :owner,
|
65
|
-
class_name: "Tag",
|
66
|
-
scoped: true
|
67
|
-
|
64
|
+
has_one :primary_tag, as: :owner, class_name: "Tag", scoped: true
|
68
65
|
accepts_nested_attributes_for :primary_tag
|
69
66
|
|
70
67
|
has_one :active_tag,
|
@@ -73,16 +70,20 @@ class Post < ActiveRecord::Base
|
|
73
70
|
class_name: "Tag",
|
74
71
|
scoped: true
|
75
72
|
|
73
|
+
has_one :secondary_tag, as: :owner, class_name: "Tag", scoped: true
|
76
74
|
|
75
|
+
has_one :primary_comment, class_name: "Comment", scoped: true
|
76
|
+
accepts_nested_attributes_for :primary_comment
|
77
77
|
|
78
|
-
has_one :
|
79
|
-
|
78
|
+
has_one :secondary_comment, class_name: "Comment", scoped: true
|
79
|
+
|
80
|
+
has_one :active_comment,
|
81
|
+
-> { where(active: true) },
|
82
|
+
class_name: "Comment",
|
80
83
|
scoped: true
|
81
84
|
|
82
|
-
has_many :primary_tags, as: :owner,
|
83
|
-
class_name: "Tag",
|
84
|
-
scoped: true
|
85
85
|
|
86
|
+
has_many :primary_tags, as: :owner, class_name: "Tag", scoped: true
|
86
87
|
accepts_nested_attributes_for :primary_tags
|
87
88
|
|
88
89
|
has_many :active_tags,
|
@@ -91,41 +92,17 @@ class Post < ActiveRecord::Base
|
|
91
92
|
class_name: "Tag",
|
92
93
|
scoped: true
|
93
94
|
|
94
|
-
|
95
|
-
has_many :secondary_tags,
|
96
|
-
as: :owner,
|
97
|
-
class_name: "Tag",
|
98
|
-
scoped: true
|
95
|
+
has_many :secondary_tags, as: :owner, class_name: "Tag", scoped: true
|
99
96
|
|
100
97
|
has_many :comments
|
101
98
|
|
102
|
-
|
103
|
-
|
104
|
-
scoped: true
|
105
|
-
|
106
|
-
has_one :active_comment,
|
107
|
-
-> { where(active: true) },
|
108
|
-
class_name: "Comment",
|
109
|
-
scoped: true
|
110
|
-
|
111
|
-
accepts_nested_attributes_for :primary_comment
|
112
|
-
|
113
|
-
has_one :secondary_comment,
|
114
|
-
class_name: "Comment",
|
115
|
-
scoped: true
|
99
|
+
has_many :primary_comments, class_name: "Comment", scoped: true
|
100
|
+
accepts_nested_attributes_for :primary_comments
|
116
101
|
|
117
|
-
has_many :
|
118
|
-
class_name: "Comment",
|
119
|
-
scoped: true
|
102
|
+
has_many :secondary_comments, class_name: "Comment", scoped: true
|
120
103
|
|
121
104
|
has_many :active_comments,
|
122
105
|
-> { where(active: true) },
|
123
106
|
class_name: "Comment",
|
124
107
|
scoped: true
|
125
|
-
|
126
|
-
accepts_nested_attributes_for :primary_comments
|
127
|
-
|
128
|
-
has_many :secondary_comments,
|
129
|
-
class_name: "Comment",
|
130
|
-
scoped: true
|
131
108
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scoped_associations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefano Verna
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2017-04-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -104,7 +104,7 @@ dependencies:
|
|
104
104
|
version: '4.0'
|
105
105
|
- - "<"
|
106
106
|
- !ruby/object:Gem::Version
|
107
|
-
version: '
|
107
|
+
version: '5.2'
|
108
108
|
type: :runtime
|
109
109
|
prerelease: false
|
110
110
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -114,7 +114,7 @@ dependencies:
|
|
114
114
|
version: '4.0'
|
115
115
|
- - "<"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
117
|
+
version: '5.2'
|
118
118
|
- !ruby/object:Gem::Dependency
|
119
119
|
name: activesupport
|
120
120
|
requirement: !ruby/object:Gem::Requirement
|
@@ -149,16 +149,19 @@ files:
|
|
149
149
|
- gemfiles/activerecord40.gemfile
|
150
150
|
- gemfiles/activerecord41.gemfile
|
151
151
|
- gemfiles/activerecord42.gemfile
|
152
|
+
- gemfiles/activerecord50.gemfile
|
153
|
+
- gemfiles/activerecord51.gemfile
|
152
154
|
- lib/scoped_associations.rb
|
153
155
|
- lib/scoped_associations/activerecord4/has_many.rb
|
154
156
|
- lib/scoped_associations/activerecord4/has_one.rb
|
157
|
+
- lib/scoped_associations/activerecord5/has_many.rb
|
158
|
+
- lib/scoped_associations/activerecord5/has_one.rb
|
155
159
|
- lib/scoped_associations/version.rb
|
156
160
|
- scoped_associations.gemspec
|
157
161
|
- spec/has_many_polymorphic_spec.rb
|
158
162
|
- spec/has_many_spec.rb
|
159
163
|
- spec/has_one_polymorphic_spec.rb
|
160
164
|
- spec/has_one_spec.rb
|
161
|
-
- spec/integration_spec.rb
|
162
165
|
- spec/spec_helper.rb
|
163
166
|
homepage: https://github.com/stefanoverna/scoped_associations
|
164
167
|
licenses:
|
@@ -180,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
183
|
version: '0'
|
181
184
|
requirements: []
|
182
185
|
rubyforge_project:
|
183
|
-
rubygems_version: 2.
|
186
|
+
rubygems_version: 2.5.1
|
184
187
|
signing_key:
|
185
188
|
specification_version: 4
|
186
189
|
summary: Create multiple `has_to` and `has_many` associations between two ActiveRecord
|
@@ -190,5 +193,4 @@ test_files:
|
|
190
193
|
- spec/has_many_spec.rb
|
191
194
|
- spec/has_one_polymorphic_spec.rb
|
192
195
|
- spec/has_one_spec.rb
|
193
|
-
- spec/integration_spec.rb
|
194
196
|
- spec/spec_helper.rb
|
data/spec/integration_spec.rb
DELETED
@@ -1,186 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe 'ScopedAssociations' do
|
4
|
-
let(:post) { Post.new }
|
5
|
-
|
6
|
-
context "non polymorphic" do
|
7
|
-
|
8
|
-
describe "has_one" do
|
9
|
-
it "works with direct assignment" do
|
10
|
-
post.secondary_comment = Comment.new(comment: "foo")
|
11
|
-
post.save!
|
12
|
-
post.reload
|
13
|
-
|
14
|
-
expect(post.secondary_comment).to be_present
|
15
|
-
expect(post.primary_comment).to be_nil
|
16
|
-
end
|
17
|
-
|
18
|
-
it "works with nested attributes" do
|
19
|
-
post = Post.new(primary_comment_attributes: { comment: "foo" })
|
20
|
-
post.save!
|
21
|
-
post.reload
|
22
|
-
|
23
|
-
expect(post.primary_comment).to be_present
|
24
|
-
expect(post.secondary_comment).to be_nil
|
25
|
-
end
|
26
|
-
|
27
|
-
it "works with .build" do
|
28
|
-
post.build_secondary_comment(comment: "foo")
|
29
|
-
post.save!
|
30
|
-
post.reload
|
31
|
-
|
32
|
-
expect(post.secondary_comment).to be_present
|
33
|
-
expect(post.primary_comment).to be_nil
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe "has_many" do
|
38
|
-
it "works with direct assignment" do
|
39
|
-
post.secondary_comments = [ Comment.new(comment: "foo") ]
|
40
|
-
post.save!
|
41
|
-
|
42
|
-
post.reload
|
43
|
-
expect(post.secondary_comments.size).to eq 1
|
44
|
-
expect(post.primary_comments.size).to eq 0
|
45
|
-
end
|
46
|
-
|
47
|
-
it "works with <<" do
|
48
|
-
post.save
|
49
|
-
post.secondary_comments << Comment.new(comment: "foo")
|
50
|
-
|
51
|
-
post.reload
|
52
|
-
expect(post.secondary_comments.size).to eq 1
|
53
|
-
expect(post.primary_comments.size).to eq 0
|
54
|
-
end
|
55
|
-
|
56
|
-
it "works with .build" do
|
57
|
-
post.secondary_comments.build(comment: "foo")
|
58
|
-
post.save
|
59
|
-
|
60
|
-
post.reload
|
61
|
-
expect(post.secondary_comments.size).to eq 1
|
62
|
-
expect(post.primary_comments.size).to eq 0
|
63
|
-
end
|
64
|
-
|
65
|
-
it "works with nested attributes" do
|
66
|
-
post = Post.new(primary_comments_attributes: [ { comment: "foo" } ])
|
67
|
-
post.save!
|
68
|
-
post.reload
|
69
|
-
|
70
|
-
expect(post.primary_comments.size).to eq 1
|
71
|
-
expect(post.secondary_comments.size).to eq 0
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
describe "using more relation" do
|
76
|
-
before do
|
77
|
-
post.primary_comment = Comment.new(comment: "foo")
|
78
|
-
post.primary_comments.build(comment: "bar")
|
79
|
-
post.save!
|
80
|
-
post.reload
|
81
|
-
end
|
82
|
-
|
83
|
-
it "has one element" do
|
84
|
-
expect(post.primary_comment).to be_present
|
85
|
-
end
|
86
|
-
|
87
|
-
it "has many has 1 elements" do
|
88
|
-
expect(post.primary_comments.size).to eq(1)
|
89
|
-
end
|
90
|
-
|
91
|
-
it "not contain the has_one element inside has_many elements" do
|
92
|
-
expect(post.primary_comments).to_not include(post.primary_comment)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
context "polymorphic" do
|
98
|
-
describe "has_one" do
|
99
|
-
it "works with direct assignment" do
|
100
|
-
post.secondary_tag = Tag.new(name: "foo")
|
101
|
-
post.save!
|
102
|
-
post.reload
|
103
|
-
|
104
|
-
expect(post.secondary_tag).to be_present
|
105
|
-
expect(post.primary_tag).to be_nil
|
106
|
-
end
|
107
|
-
|
108
|
-
it "works with nested attributes" do
|
109
|
-
post = Post.new(primary_tag_attributes: { name: "foo" })
|
110
|
-
post.save!
|
111
|
-
post.reload
|
112
|
-
|
113
|
-
expect(post.primary_tag).to be_present
|
114
|
-
expect(post.secondary_tag).to be_nil
|
115
|
-
end
|
116
|
-
|
117
|
-
it "works with .build" do
|
118
|
-
post.build_secondary_tag(name: "foo")
|
119
|
-
post.save!
|
120
|
-
post.reload
|
121
|
-
|
122
|
-
expect(post.secondary_tag).to be_present
|
123
|
-
expect(post.primary_tag).to be_nil
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
describe "has_many" do
|
128
|
-
it "works with direct assignment" do
|
129
|
-
post.secondary_tags = [ Tag.new(name: "foo") ]
|
130
|
-
post.save!
|
131
|
-
|
132
|
-
post.reload
|
133
|
-
expect(post.secondary_tags.size).to eq 1
|
134
|
-
expect(post.primary_tags.size).to eq 0
|
135
|
-
end
|
136
|
-
|
137
|
-
it "works with <<" do
|
138
|
-
post.save
|
139
|
-
post.secondary_tags << Tag.new(name: "foo")
|
140
|
-
|
141
|
-
post.reload
|
142
|
-
expect(post.secondary_tags.size).to eq 1
|
143
|
-
expect(post.primary_tags.size).to eq 0
|
144
|
-
end
|
145
|
-
|
146
|
-
it "works with .build" do
|
147
|
-
post.secondary_tags.build(name: "foo")
|
148
|
-
post.save
|
149
|
-
|
150
|
-
post.reload
|
151
|
-
expect(post.secondary_tags.size).to eq 1
|
152
|
-
expect(post.primary_tags.size).to eq 0
|
153
|
-
end
|
154
|
-
|
155
|
-
it "works with nested attributes" do
|
156
|
-
post = Post.new(primary_tags_attributes: [ { name: "foo" } ])
|
157
|
-
post.save!
|
158
|
-
post.reload
|
159
|
-
|
160
|
-
expect(post.primary_tags.size).to eq 1
|
161
|
-
expect(post.secondary_tags.size).to eq 0
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
describe "using more relation" do
|
166
|
-
before do
|
167
|
-
post.primary_tag = Tag.new(name: "foo")
|
168
|
-
post.primary_tags.build(name: "bar")
|
169
|
-
post.save!
|
170
|
-
post.reload
|
171
|
-
end
|
172
|
-
|
173
|
-
it "has one element" do
|
174
|
-
expect(post.primary_tag).to be_present
|
175
|
-
end
|
176
|
-
|
177
|
-
it "has many has 1 elements" do
|
178
|
-
expect(post.primary_tags.size).to eq(1)
|
179
|
-
end
|
180
|
-
|
181
|
-
it "not contain the has_one element inside has_many elements" do
|
182
|
-
expect(post.primary_tags).to_not include(post.primary_tag)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|