scopes_for_associations 0.1.0 → 0.1.1
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.
- data/.rspec +1 -0
- data/README.rdoc +43 -2
- data/lib/scopes_for_associations/version.rb +1 -1
- data/lib/scopes_for_associations.rb +48 -13
- data/scopes_for_associations.gemspec +3 -1
- data/spec/scopes_for_associations_spec.rb +41 -10
- data/spec/spec_helper.rb +1 -4
- data/spec/support/models.rb +6 -3
- data/spec/support/schema.rb +3 -0
- metadata +21 -35
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/README.rdoc
CHANGED
@@ -16,6 +16,47 @@ Define very basic, commonly used scopes for ActiveRecord associations.
|
|
16
16
|
Movie.for(Director.first)
|
17
17
|
#=> [#<Movie ..., director_id: 1>]
|
18
18
|
|
19
|
-
==
|
19
|
+
== Supported association types
|
20
20
|
|
21
|
-
|
21
|
+
* belongs_to (non-polymorpic and polymorphic)
|
22
|
+
|
23
|
+
If you're like me and prefer learning through looking at code,
|
24
|
+
read through the specs.
|
25
|
+
The examples here are basically reproductions of the tests.
|
26
|
+
|
27
|
+
=== belongs_to (non-polymorphic)
|
28
|
+
|
29
|
+
class Movie < ActiveRecord::Base
|
30
|
+
belongs_to :director
|
31
|
+
scopes_for_associations
|
32
|
+
end
|
33
|
+
|
34
|
+
Movie.for_director(Director.first)
|
35
|
+
#=> [#<Movie ..., director_id: 1>]
|
36
|
+
Movie.for(Director.first)
|
37
|
+
#=> [#<Movie ..., director_id: 1>]
|
38
|
+
|
39
|
+
=== belongs_to (polymorphic)
|
40
|
+
|
41
|
+
class Movie < ActiveRecord::base
|
42
|
+
# It is important to define this association.
|
43
|
+
has_many :comments, :as => :commentable
|
44
|
+
end
|
45
|
+
class Comment < ActiveRecord::Base
|
46
|
+
belongs_to :commentable, :polymorphic => true
|
47
|
+
end
|
48
|
+
|
49
|
+
Commentable.for_movie(Movie.first)
|
50
|
+
#=> [#<Comment ..., commentable_type: "Movie", commentable_id: 1>]
|
51
|
+
Commentable.for(Movie.first)
|
52
|
+
#=> [#<Comment ..., commentable_type: "Movie", commentable_id: 1>]
|
53
|
+
|
54
|
+
== Installation
|
55
|
+
|
56
|
+
gem install scopes_for_associations
|
57
|
+
|
58
|
+
== Compatibility
|
59
|
+
|
60
|
+
works with ActiveRecord >=3.0.0
|
61
|
+
|
62
|
+
gem-testers: http://gem-testers.org/gems/scopes_for_associations
|
@@ -1,22 +1,57 @@
|
|
1
1
|
module ScopesForAssociations
|
2
2
|
|
3
3
|
def scopes_for_associations()
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
define_scopes_for_non_polymorpic_belongs_to_associations
|
5
|
+
define_scopes_for_polymorpic_belongs_to_associations
|
6
|
+
define_named_scope_for
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def non_polymorphic_belongs_to_reflections
|
12
|
+
reflect_on_all_associations(:belongs_to).reject { |reflection| reflection.options[:polymorphic] }
|
13
|
+
end
|
14
|
+
|
15
|
+
def polymorphic_belongs_to_reflections
|
16
|
+
reflect_on_all_associations(:belongs_to).select { |reflection| reflection.options[:polymorphic] }
|
17
|
+
end
|
18
|
+
|
19
|
+
def define_scopes_for_non_polymorpic_belongs_to_associations
|
7
20
|
non_polymorphic_belongs_to_reflections.each do |reflection|
|
8
21
|
name = reflection.name
|
9
|
-
scope :"for_#{name}", proc { |obj| where(:"#{name}_id" => obj) }
|
22
|
+
scope :"for_#{name}", proc { |obj| where(:"#{name}_id" => obj.id) }
|
10
23
|
end
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
24
|
+
end
|
25
|
+
|
26
|
+
def define_scopes_for_polymorpic_belongs_to_associations
|
27
|
+
polymorphic_belongs_to_reflections.each do |reflection|
|
28
|
+
name = reflection.name
|
29
|
+
scope :"for_#{name}", proc { |obj| where(:"#{name}_type" => obj.class.name, :"#{name}_id" => obj.id) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# return [name, reflection] from matching reflection.klass and obj.class
|
34
|
+
def reflection_for_object(obj)
|
35
|
+
reflections.detect { |name, reflection| reflection.class_name == obj.class.name }
|
36
|
+
end
|
37
|
+
|
38
|
+
def define_named_scope_for
|
39
|
+
scope :for, proc { |object|
|
40
|
+
name, reflection = reflection_for_object(object)
|
41
|
+
if name
|
42
|
+
send(:"for_#{name}", object)
|
43
|
+
else
|
44
|
+
# see if it's polymorphic from object's associations.
|
45
|
+
reflection = object.class.reflect_on_all_associations(:has_many).detect { |reflection|
|
46
|
+
reflection.options[:as] && reflection.klass == self
|
47
|
+
}
|
48
|
+
if reflection
|
49
|
+
send(:"for_#{reflection.options[:as]}", object)
|
50
|
+
else
|
51
|
+
raise "no scope for #{object.class}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
}
|
20
55
|
end
|
21
56
|
|
22
57
|
end
|
@@ -19,7 +19,9 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split($/).map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ['lib']
|
21
21
|
|
22
|
+
s.add_dependency 'activerecord', '>= 3.0.0'
|
23
|
+
|
24
|
+
s.add_development_dependency 'awesome_print'
|
22
25
|
s.add_development_dependency 'rspec', '2.5.0'
|
23
|
-
s.add_development_dependency 'activerecord', '>= 3.0.0'
|
24
26
|
s.add_development_dependency 'sqlite3-ruby', '1.2.5'
|
25
27
|
end
|
@@ -4,24 +4,55 @@ describe ScopesForAssociations do
|
|
4
4
|
|
5
5
|
let(:director) { Director.create! }
|
6
6
|
let(:production_company) { ProductionCompany.create! }
|
7
|
+
let(:movie) { Movie.create!(:director => director, :production_company => production_company) }
|
8
|
+
let(:comment) { Comment.create! :commentable_type => 'Movie', :commentable_id => movie.id }
|
7
9
|
|
8
10
|
it 'should be included in ActiveRecord::Base' do
|
9
11
|
ActiveRecord::Base.should respond_to('scopes_for_associations')
|
10
12
|
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
context 'for non-polymorphic belongs_to associations' do
|
15
|
+
|
16
|
+
it 'should define for_x scopes' do
|
17
|
+
Movie.should respond_to('for_director')
|
18
|
+
Movie.should respond_to('for_production_company')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should scope for association as object' do
|
22
|
+
Movie.for_director(director).to_sql.should eq(Movie.where(:director_id => director.id).to_sql)
|
23
|
+
Movie.for_director(director).should eq([movie])
|
24
|
+
Movie.for_production_company(production_company).to_sql.should eq(Movie.where(:production_company_id => production_company.id).to_sql)
|
25
|
+
Movie.for_production_company(director).should eq([movie])
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should have a "polymorphic" scope :for' do
|
29
|
+
Movie.for(director).to_sql.should eq(Movie.for_director(director).to_sql)
|
30
|
+
Movie.for(director).should eq([movie])
|
31
|
+
Movie.for(production_company).to_sql.should eq(Movie.for_production_company(production_company).to_sql)
|
32
|
+
Movie.for(production_company).should eq([movie])
|
33
|
+
end
|
16
34
|
|
17
|
-
it 'should scope for association as object' do
|
18
|
-
Movie.for_director(director).to_sql.should eq(Movie.where(:director_id => director.id).to_sql)
|
19
|
-
Movie.for_production_company(production_company).to_sql.should eq(Movie.where(:production_company_id => production_company.id).to_sql)
|
20
35
|
end
|
21
36
|
|
22
|
-
|
23
|
-
|
24
|
-
|
37
|
+
context 'for polymorphic belongs_to associations' do
|
38
|
+
|
39
|
+
it 'should define for_x scopes' do
|
40
|
+
Comment.should respond_to('for_commentable')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should scope for association as object' do
|
44
|
+
Comment.for_commentable(movie)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should scope for association as object' do
|
48
|
+
Comment.for_commentable(movie).to_sql.should eq(Comment.where(:commentable_type => 'Movie', :commentable_id => movie.id).to_sql)
|
49
|
+
Comment.for_commentable(movie).should eq([comment])
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should have a "polymorphic" scope :for' do
|
53
|
+
Comment.for(movie).to_sql.should eq(Comment.for_commentable(movie).to_sql)
|
54
|
+
end
|
55
|
+
|
25
56
|
end
|
26
57
|
|
27
58
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require 'active_record'
|
3
|
+
require 'awesome_print'
|
3
4
|
|
4
5
|
require File.join(Pathname(__FILE__).dirname.expand_path, '../lib/scopes_for_associations')
|
5
6
|
|
6
7
|
# require support .rb files.
|
7
8
|
Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f}
|
8
|
-
|
9
|
-
#RSpec.configure do |config|
|
10
|
-
#config.include(Macros)
|
11
|
-
#end
|
data/spec/support/models.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
class Movie < ActiveRecord::Base
|
2
|
-
|
3
2
|
belongs_to :director
|
4
3
|
belongs_to :production_company
|
5
4
|
has_one :trailer
|
6
|
-
|
5
|
+
has_many :comments, :as => 'commentable'
|
7
6
|
scopes_for_associations
|
8
|
-
|
9
7
|
end
|
10
8
|
|
11
9
|
class Director < ActiveRecord::Base
|
@@ -20,3 +18,8 @@ class Trailer < ActiveRecord::Base
|
|
20
18
|
belongs_to :production_company
|
21
19
|
scopes_for_associations
|
22
20
|
end
|
21
|
+
|
22
|
+
class Comment < ActiveRecord::Base
|
23
|
+
belongs_to :commentable, :polymorphic => true
|
24
|
+
scopes_for_associations
|
25
|
+
end
|
data/spec/support/schema.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scopes_for_associations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 27
|
5
4
|
prerelease:
|
6
|
-
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 0
|
10
|
-
version: 0.1.0
|
5
|
+
version: 0.1.1
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Jared Ning
|
@@ -19,53 +14,49 @@ date: 2011-02-08 00:00:00 -06:00
|
|
19
14
|
default_executable:
|
20
15
|
dependencies:
|
21
16
|
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
17
|
+
name: activerecord
|
23
18
|
prerelease: false
|
24
19
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
20
|
none: false
|
26
21
|
requirements:
|
27
|
-
- - "
|
22
|
+
- - ">="
|
28
23
|
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
|
31
|
-
- 2
|
32
|
-
- 5
|
33
|
-
- 0
|
34
|
-
version: 2.5.0
|
35
|
-
type: :development
|
24
|
+
version: 3.0.0
|
25
|
+
type: :runtime
|
36
26
|
version_requirements: *id001
|
37
27
|
- !ruby/object:Gem::Dependency
|
38
|
-
name:
|
28
|
+
name: awesome_print
|
39
29
|
prerelease: false
|
40
30
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
31
|
none: false
|
42
32
|
requirements:
|
43
33
|
- - ">="
|
44
34
|
- !ruby/object:Gem::Version
|
45
|
-
|
46
|
-
segments:
|
47
|
-
- 3
|
48
|
-
- 0
|
49
|
-
- 0
|
50
|
-
version: 3.0.0
|
35
|
+
version: "0"
|
51
36
|
type: :development
|
52
37
|
version_requirements: *id002
|
53
38
|
- !ruby/object:Gem::Dependency
|
54
|
-
name:
|
39
|
+
name: rspec
|
55
40
|
prerelease: false
|
56
41
|
requirement: &id003 !ruby/object:Gem::Requirement
|
57
42
|
none: false
|
58
43
|
requirements:
|
59
44
|
- - "="
|
60
45
|
- !ruby/object:Gem::Version
|
61
|
-
|
62
|
-
segments:
|
63
|
-
- 1
|
64
|
-
- 2
|
65
|
-
- 5
|
66
|
-
version: 1.2.5
|
46
|
+
version: 2.5.0
|
67
47
|
type: :development
|
68
48
|
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: sqlite3-ruby
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - "="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 1.2.5
|
58
|
+
type: :development
|
59
|
+
version_requirements: *id004
|
69
60
|
description: Define very basic, commonly used scopes for ActiveRecord associations. E.g. if a Post model has an author and a category association, scopes will be defined like Post.for(author) or Post.for(category).
|
70
61
|
email:
|
71
62
|
- jared@redningja.com
|
@@ -78,6 +69,7 @@ extra_rdoc_files: []
|
|
78
69
|
files:
|
79
70
|
- .gemtest
|
80
71
|
- .gitignore
|
72
|
+
- .rspec
|
81
73
|
- .rvmrc
|
82
74
|
- Gemfile
|
83
75
|
- README.rdoc
|
@@ -103,18 +95,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
103
95
|
requirements:
|
104
96
|
- - ">="
|
105
97
|
- !ruby/object:Gem::Version
|
106
|
-
hash: 3
|
107
|
-
segments:
|
108
|
-
- 0
|
109
98
|
version: "0"
|
110
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
100
|
none: false
|
112
101
|
requirements:
|
113
102
|
- - ">="
|
114
103
|
- !ruby/object:Gem::Version
|
115
|
-
hash: 3
|
116
|
-
segments:
|
117
|
-
- 0
|
118
104
|
version: "0"
|
119
105
|
requirements: []
|
120
106
|
|