required_scopes 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +29 -0
- data/Gemfile +17 -0
- data/LICENSE.txt +22 -0
- data/README.md +277 -0
- data/Rakefile +6 -0
- data/lib/required_scopes.rb +17 -0
- data/lib/required_scopes/active_record/base.rb +235 -0
- data/lib/required_scopes/active_record/relation.rb +121 -0
- data/lib/required_scopes/active_record/version_compatibility.rb +157 -0
- data/lib/required_scopes/errors.rb +48 -0
- data/lib/required_scopes/version.rb +3 -0
- data/required_scopes.gemspec +56 -0
- data/spec/required_scopes/helpers/database_helper.rb +174 -0
- data/spec/required_scopes/helpers/system_helpers.rb +98 -0
- data/spec/required_scopes/system/associations_system_spec.rb +150 -0
- data/spec/required_scopes/system/base_scope_system_spec.rb +71 -0
- data/spec/required_scopes/system/basic_system_spec.rb +121 -0
- data/spec/required_scopes/system/inheritance_system_spec.rb +67 -0
- data/spec/required_scopes/system/methods_system_spec.rb +312 -0
- data/spec/required_scopes/system/static_scopes_system_spec.rb +31 -0
- metadata +141 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_record/migration'
|
3
|
+
|
4
|
+
module RequiredScopes
|
5
|
+
module Helpers
|
6
|
+
module SystemHelpers
|
7
|
+
def migrate(&block)
|
8
|
+
migration_class = Class.new(::ActiveRecord::Migration)
|
9
|
+
metaclass = migration_class.class_eval { class << self; self; end }
|
10
|
+
metaclass.instance_eval { define_method(:up, &block) }
|
11
|
+
|
12
|
+
::ActiveRecord::Migration.suppress_messages do
|
13
|
+
migration_class.migrate(:up)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def define_model_class(name, table_name, &block)
|
18
|
+
model_class = Class.new(::ActiveRecord::Base)
|
19
|
+
::Object.send(:remove_const, name) if ::Object.const_defined?(name)
|
20
|
+
::Object.const_set(name, model_class)
|
21
|
+
model_class.table_name = table_name
|
22
|
+
model_class.class_eval(&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_standard_system_spec_tables!
|
26
|
+
migrate do
|
27
|
+
drop_table :rec_spec_users rescue nil
|
28
|
+
create_table :rec_spec_users do |t|
|
29
|
+
t.string :name, :null => false
|
30
|
+
t.string :favorite_color
|
31
|
+
t.string :favorite_taste
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def define_color_and_taste_scopes!
|
37
|
+
::User.class_eval do
|
38
|
+
must_scope_by :color, :taste
|
39
|
+
|
40
|
+
scope :red, lambda { where(:favorite_color => 'red') }, :satisfies => :color
|
41
|
+
scope :green, lambda { where(:favorite_color => 'green') }, :satisfies => :color
|
42
|
+
|
43
|
+
scope :salty, lambda { where(:favorite_taste => 'salty') }, :satisfies => :taste
|
44
|
+
scope :sweet, lambda { where(:favorite_taste => 'sweet') }, :satisfies => :taste
|
45
|
+
|
46
|
+
scope :red_and_salty, lambda { where(:favorite_color => 'red', :favorite_taste => 'salty') }, :satisfies => [ :color, :taste ]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def should_raise_missing_scopes(triggering_method, required, satisfied, options = { })
|
51
|
+
e = result = nil
|
52
|
+
|
53
|
+
begin
|
54
|
+
result = yield
|
55
|
+
rescue RequiredScopes::Errors::RequiredScopeCategoriesNotSatisfiedError => rscnse
|
56
|
+
e = rscnse
|
57
|
+
end
|
58
|
+
|
59
|
+
raise "Expected a scopes-not-satisfied error, but got none" unless e
|
60
|
+
|
61
|
+
expected_model_class = options[:model_class] || ::User
|
62
|
+
|
63
|
+
e.class.should == RequiredScopes::Errors::RequiredScopeCategoriesNotSatisfiedError
|
64
|
+
e.model_class.should == expected_model_class
|
65
|
+
e.current_relation.should be
|
66
|
+
e.current_relation.kind_of?(::ActiveRecord::Relation).should be
|
67
|
+
e.triggering_method.should == triggering_method
|
68
|
+
e.required_categories.sort_by(&:to_s).should == required.sort_by(&:to_s)
|
69
|
+
e.satisfied_categories.sort_by(&:to_s).should == satisfied.sort_by(&:to_s)
|
70
|
+
|
71
|
+
expected_missing_categories = required - satisfied
|
72
|
+
e.missing_categories.sort_by(&:to_s).should == expected_missing_categories.sort_by(&:to_s)
|
73
|
+
|
74
|
+
e.message.should match(/#{expected_model_class.name}/)
|
75
|
+
e.message.should match(/#{expected_missing_categories.sort_by(&:to_s).join(", ")}/)
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_standard_system_spec_models!
|
79
|
+
define_model_class(:User, 'rec_spec_users') { }
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_standard_system_spec_instances!
|
83
|
+
@red_salty = ::User.create!(:name => 'red-salty', :favorite_color => 'red', :favorite_taste => 'salty')
|
84
|
+
@green_salty = ::User.create!(:name => 'green-salty', :favorite_color => 'green', :favorite_taste => 'salty')
|
85
|
+
@blue_salty = ::User.create!(:name => 'blue-salty', :favorite_color => 'blue', :favorite_taste => 'salty')
|
86
|
+
@red_sweet = ::User.create!(:name => 'red-sweet', :favorite_color => 'red', :favorite_taste => 'sweet')
|
87
|
+
@green_sweet = ::User.create!(:name => 'green-sweet', :favorite_color => 'green', :favorite_taste => 'sweet')
|
88
|
+
@blue_sweet = ::User.create!(:name => 'blue-sweet', :favorite_color => 'blue', :favorite_taste => 'sweet')
|
89
|
+
end
|
90
|
+
|
91
|
+
def drop_standard_system_spec_tables!
|
92
|
+
migrate do
|
93
|
+
drop_table :rec_spec_users rescue nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'required_scopes'
|
2
|
+
require 'required_scopes/helpers/database_helper'
|
3
|
+
require 'required_scopes/helpers/system_helpers'
|
4
|
+
|
5
|
+
describe "RequiredScopes and associations" do
|
6
|
+
include RequiredScopes::Helpers::SystemHelpers
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@dh = RequiredScopes::Helpers::DatabaseHelper.new
|
10
|
+
@dh.setup_activerecord!
|
11
|
+
|
12
|
+
migrate do
|
13
|
+
drop_table :rec_spec_groups rescue nil
|
14
|
+
create_table :rec_spec_groups do |t|
|
15
|
+
t.string :name, :null => false
|
16
|
+
end
|
17
|
+
|
18
|
+
drop_table :rec_spec_users rescue nil
|
19
|
+
create_table :rec_spec_users do |t|
|
20
|
+
t.string :name, :null => false
|
21
|
+
t.integer :group_id
|
22
|
+
t.string :favorite_color
|
23
|
+
end
|
24
|
+
|
25
|
+
drop_table :rec_spec_user_preferences rescue nil
|
26
|
+
create_table :rec_spec_user_preferences do |t|
|
27
|
+
t.integer :user_id
|
28
|
+
t.string :preference
|
29
|
+
end
|
30
|
+
|
31
|
+
drop_table :rec_spec_categories rescue nil
|
32
|
+
create_table :rec_spec_categories do |t|
|
33
|
+
t.string :name
|
34
|
+
end
|
35
|
+
|
36
|
+
drop_table :rec_spec_categories_users rescue nil
|
37
|
+
create_table :rec_spec_categories_users, :id => false do |t|
|
38
|
+
t.integer :user_id
|
39
|
+
t.integer :category_id
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
define_model_class(:User, :rec_spec_users) do
|
44
|
+
must_scope_by :color
|
45
|
+
belongs_to :group
|
46
|
+
has_one :user_preference
|
47
|
+
has_and_belongs_to_many :categories, :join_table => :rec_spec_categories_users
|
48
|
+
|
49
|
+
scope :red, lambda { where(:favorite_color => :red) }, :satisfies => :color
|
50
|
+
end
|
51
|
+
|
52
|
+
define_model_class(:Group, :rec_spec_groups) do
|
53
|
+
has_many :users
|
54
|
+
end
|
55
|
+
|
56
|
+
define_model_class(:UserPreference, :rec_spec_user_preferences) do
|
57
|
+
belongs_to :user
|
58
|
+
|
59
|
+
must_scope_by :prefcolor
|
60
|
+
end
|
61
|
+
|
62
|
+
define_model_class(:Category, :rec_spec_categories) do
|
63
|
+
has_and_belongs_to_many :users, :join_table => :rec_spec_categories_users
|
64
|
+
|
65
|
+
must_scope_by :catcolor
|
66
|
+
end
|
67
|
+
|
68
|
+
@group1 = ::Group.create!(:name => 'Group 1')
|
69
|
+
@user1 = ::User.create!(:name => 'g1u1', :favorite_color => 'red', :group => @group1)
|
70
|
+
@user2 = ::User.create!(:name => 'g1u2', :favorite_color => 'green', :group => @group1)
|
71
|
+
|
72
|
+
@user1pref = ::UserPreference.create!(:user => @user1, :preference => 'u1p')
|
73
|
+
@user2pref = ::UserPreference.create!(:user => @user2, :preference => 'u2p')
|
74
|
+
|
75
|
+
@cat1 = ::Category.create!(:name => 'c1')
|
76
|
+
@cat2 = ::Category.create!(:name => 'c2')
|
77
|
+
|
78
|
+
@cat1.users << @user1
|
79
|
+
@cat1.users << @user2
|
80
|
+
@cat1.save!
|
81
|
+
|
82
|
+
@cat2.users << @user1
|
83
|
+
@cat2.users << @user2
|
84
|
+
@cat2.save!
|
85
|
+
end
|
86
|
+
|
87
|
+
after :each do
|
88
|
+
migrate do
|
89
|
+
drop_table :rec_spec_groups rescue nil
|
90
|
+
drop_table :rec_spec_users rescue nil
|
91
|
+
drop_table :rec_spec_user_preferences rescue nil
|
92
|
+
drop_table :rec_spec_categories rescue nil
|
93
|
+
drop_table :rec_spec_categories_users rescue nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should require a scope when accessed directly" do
|
98
|
+
lambda { ::User.where(:group_id => @group1.id).to_a }.should raise_error(RequiredScopes::Errors::RequiredScopeCategoriesNotSatisfiedError)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should not require a scope when accessed via an association" do
|
102
|
+
@group1.users.map(&:id).sort.should == [ @user1, @user2 ].map(&:id).sort
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should not require a scope when accessed via an association, with eager loading" do
|
106
|
+
Group.includes(:users).find(@group1.id).users.map(&:id).sort.should == [ @user1, @user2 ].map(&:id).sort
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should not require a scope when accessed via #joins" do
|
110
|
+
Group.joins(:users).find(@group1.id).users.map(&:id).sort.should == [ @user1, @user2 ].map(&:id).sort
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should not require a scope when accessed via #eager_load" do
|
114
|
+
Group.eager_load(:users).find(@group1.id).users.map(&:id).sort.should == [ @user1, @user2 ].map(&:id).sort
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should not require a scope when accessed via #preload" do
|
118
|
+
Group.preload(:users).find(@group1.id).users.map(&:id).sort.should == [ @user1, @user2 ].map(&:id).sort
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should not require a scope when accessed via #references" do
|
122
|
+
if ::RequiredScopes::ActiveRecord::VersionCompatibility.supports_references_method?
|
123
|
+
Group.references(:users).find(@group1.id).users.map(&:id).sort.should == [ @user1, @user2 ].map(&:id).sort
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should not require a scope when accessed via has_one" do
|
128
|
+
@user1.user_preference.should == @user1pref
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should not require a scope when accessed via has_one, with eager loading" do
|
132
|
+
User.includes(:user_preference).red.find(@user1.id).id.should == @user1pref.id
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should not require a scope when accessed via belongs_to" do
|
136
|
+
@user1pref.user.should == @user1
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should not require a scope when accessed via has_one, with eager loading" do
|
140
|
+
UserPreference.includes(:user).all_scope_categories_satisfied.find(@user1pref.id).id.should == @user1.id
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should not require a scope when accessed via has_and_belongs_to_many" do
|
144
|
+
@user1.categories.map(&:id).sort.should == [ @cat1, @cat2 ].map(&:id).sort
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should not require a scope when accessed via has_and_belongs_to_many, with eager loading" do
|
148
|
+
::User.includes(:categories).all_scope_categories_satisfied.find(@user1).categories.map(&:id).should == [ @cat1, @cat2 ].map(&:id).sort
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'required_scopes'
|
2
|
+
require 'required_scopes/helpers/database_helper'
|
3
|
+
require 'required_scopes/helpers/system_helpers'
|
4
|
+
|
5
|
+
describe "RequiredScopes base scope operations" do
|
6
|
+
include RequiredScopes::Helpers::SystemHelpers
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@dh = RequiredScopes::Helpers::DatabaseHelper.new
|
10
|
+
@dh.setup_activerecord!
|
11
|
+
|
12
|
+
create_standard_system_spec_tables!
|
13
|
+
create_standard_system_spec_models!
|
14
|
+
create_standard_system_spec_instances!
|
15
|
+
|
16
|
+
::User.class_eval do
|
17
|
+
base_scope_required!
|
18
|
+
|
19
|
+
base_scope :red, lambda { where(:favorite_color => 'red') }
|
20
|
+
base_scope :green, lambda { where(:favorite_color => 'green') }
|
21
|
+
|
22
|
+
scope :salty, lambda { where(:favorite_taste => 'salty') }
|
23
|
+
|
24
|
+
class << self
|
25
|
+
def blue
|
26
|
+
base_scope_satisfied.where(:favorite_color => 'blue')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
after :each do
|
33
|
+
drop_standard_system_spec_tables!
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should require the base scope" do
|
37
|
+
e = nil
|
38
|
+
|
39
|
+
begin
|
40
|
+
::User.all.to_a
|
41
|
+
rescue RequiredScopes::Errors::BaseScopeNotSatisfiedError => bsnse
|
42
|
+
e = bsnse
|
43
|
+
end
|
44
|
+
|
45
|
+
e.should be
|
46
|
+
e.class.should == RequiredScopes::Errors::BaseScopeNotSatisfiedError
|
47
|
+
e.model_class.should == ::User
|
48
|
+
|
49
|
+
e.current_relation.should be
|
50
|
+
e.current_relation.kind_of?(::ActiveRecord::Relation).should be
|
51
|
+
e.triggering_method.should == :exec_queries
|
52
|
+
|
53
|
+
e.required_categories.should == [ :base ]
|
54
|
+
e.satisfied_categories.should == [ ]
|
55
|
+
e.missing_categories.should == [ :base ]
|
56
|
+
|
57
|
+
e.message.should match(/base scope/i)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should work if a base scope is used" do
|
61
|
+
::User.red.to_a
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should work if a class method satisfying the base scope is used" do
|
65
|
+
::User.blue.to_a
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should work if you manually tell it that the base scope is satisfied" do
|
69
|
+
::User.base_scope_satisfied.to_a
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'required_scopes'
|
2
|
+
require 'required_scopes/helpers/database_helper'
|
3
|
+
require 'required_scopes/helpers/system_helpers'
|
4
|
+
|
5
|
+
describe "RequiredScopes basic operations" do
|
6
|
+
include RequiredScopes::Helpers::SystemHelpers
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@dh = RequiredScopes::Helpers::DatabaseHelper.new
|
10
|
+
@dh.setup_activerecord!
|
11
|
+
|
12
|
+
create_standard_system_spec_tables!
|
13
|
+
create_standard_system_spec_models!
|
14
|
+
create_standard_system_spec_instances!
|
15
|
+
|
16
|
+
define_color_and_taste_scopes!
|
17
|
+
end
|
18
|
+
|
19
|
+
after :each do
|
20
|
+
drop_standard_system_spec_tables!
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "queries" do
|
24
|
+
it "should raise if no categories are applied" do
|
25
|
+
should_raise_missing_scopes(:exec_queries, [ :color, :taste ], [ ]) { ::User.all.to_a }
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should raise if only one category is applied" do
|
29
|
+
should_raise_missing_scopes(:exec_queries, [ :color, :taste ], [ :color ]) { ::User.red.to_a }
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not raise if both categories are individually applied" do
|
33
|
+
::User.red.salty.to_a.should == [ @red_salty ]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should not raise if both categories are satisfied by a single scope" do
|
37
|
+
::User.red_and_salty.to_a.should == [ @red_salty ]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should allow further qualifying the scopes, and in the middle" do
|
41
|
+
::User.where("name LIKE 'red%'").red.where("name LIKE '%salty'").salty.where("name LIKE '%d-s%'").to_a.should == [ @red_salty ]
|
42
|
+
::User.where("name LIKE 'green%'").red.salty.to_a.should == [ ]
|
43
|
+
::User.red.where("name LIKE '%sweet'").salty.to_a.should == [ ]
|
44
|
+
::User.red.salty.where("name LIKE '%sweet'").to_a.should == [ ]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should automatically have a scope that includes all of each category" do
|
48
|
+
::User.red.ignoring_taste.to_a.sort.should == [ @red_salty, @red_sweet ].sort
|
49
|
+
::User.ignoring_color.sweet.to_a.sort.should == [ @red_sweet, @green_sweet, @blue_sweet ].sort
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should still require scopes even if #unscoped is used" do
|
53
|
+
should_raise_missing_scopes(:exec_queries, [ :color, :taste ], [ ]) { ::User.unscoped.to_a }
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should still require scopes even if #unscoped is used in a block form" do
|
57
|
+
should_raise_missing_scopes(:exec_queries, [ :color, :taste ], [ ]) { ::User.unscoped { ::User.all.to_a } }
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should allow manually saying that categories are satisfied" do
|
61
|
+
::User.red.scope_category_satisfied(:taste).to_a.sort.should == [ @red_salty, @red_sweet ].to_a
|
62
|
+
::User.scope_category_satisfied(:color).sweet.to_a.sort.should == [ @red_sweet, @green_sweet, @blue_sweet ].to_a
|
63
|
+
::User.scope_categories_satisfied(:color, :taste).to_a.sort.should ==
|
64
|
+
[ @red_sweet, @green_sweet, @blue_sweet, @red_salty, @green_salty, @blue_salty ].to_a.sort
|
65
|
+
::User.scope_categories_satisfied(:color, :taste).sweet.to_a.sort.should ==
|
66
|
+
[ @red_sweet, @green_sweet, @blue_sweet ].to_a.sort
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should allow manually saying that categories are satisfied, in a block" do
|
70
|
+
ran_block = false
|
71
|
+
::User.scope_category_satisfied(:taste) do
|
72
|
+
::User.red.to_a.sort.should == [ @red_salty, @red_sweet].to_a
|
73
|
+
ran_block = true
|
74
|
+
end
|
75
|
+
ran_block.should be
|
76
|
+
|
77
|
+
ran_block = false
|
78
|
+
::User.scope_category_satisfied(:taste) do
|
79
|
+
should_raise_missing_scopes(:exec_queries, [ :color, :taste ], [ :taste ]) { ::User.all.to_a }
|
80
|
+
ran_block = true
|
81
|
+
end
|
82
|
+
ran_block.should be
|
83
|
+
|
84
|
+
ran_block = false
|
85
|
+
::User.scope_category_satisfied(:taste) do
|
86
|
+
::User.red.to_a.sort.should == [ @red_salty, @red_sweet ].sort
|
87
|
+
ran_block = true
|
88
|
+
end
|
89
|
+
ran_block.should be
|
90
|
+
|
91
|
+
ran_block = false
|
92
|
+
::User.all_scope_categories_satisfied do
|
93
|
+
::User.all.to_a.sort.should == [ @red_salty, @red_sweet, @green_salty, @green_sweet, @blue_salty, @blue_sweet ].sort
|
94
|
+
ran_block = true
|
95
|
+
end
|
96
|
+
ran_block.should be
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should allow saying that categories are satisfied in a class method, in any position" do
|
100
|
+
::User.class_eval do
|
101
|
+
class << self
|
102
|
+
def red_and_green
|
103
|
+
scope_category_satisfied(:color).where(:favorite_color => %w{red green})
|
104
|
+
end
|
105
|
+
|
106
|
+
def green_and_blue
|
107
|
+
where(:favorite_color => %w{green blue}).scope_category_satisfied(:color)
|
108
|
+
end
|
109
|
+
|
110
|
+
def red_and_blue
|
111
|
+
where(:favorite_color => %w{red blue}).scope_category_satisfied(:color).where(:favorite_taste => %w{salty sweet})
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
::User.red_and_green.salty.to_a.sort.should == [ @red_salty, @green_salty ].sort
|
117
|
+
::User.green_and_blue.salty.to_a.sort.should == [ @green_salty, @blue_salty ].sort
|
118
|
+
::User.red_and_blue.salty.to_a.sort.should == [ @red_salty, @blue_salty ].sort
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'required_scopes'
|
2
|
+
require 'required_scopes/helpers/database_helper'
|
3
|
+
require 'required_scopes/helpers/system_helpers'
|
4
|
+
|
5
|
+
describe "RequiredScopes and inheritance" do
|
6
|
+
include RequiredScopes::Helpers::SystemHelpers
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@dh = RequiredScopes::Helpers::DatabaseHelper.new
|
10
|
+
@dh.setup_activerecord!
|
11
|
+
|
12
|
+
create_standard_system_spec_tables!
|
13
|
+
create_standard_system_spec_models!
|
14
|
+
create_standard_system_spec_instances!
|
15
|
+
end
|
16
|
+
|
17
|
+
after :each do
|
18
|
+
drop_standard_system_spec_tables!
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should combine multiple #must_scope_by declarations" do
|
22
|
+
::User.class_eval do
|
23
|
+
must_scope_by :color
|
24
|
+
must_scope_by :taste
|
25
|
+
|
26
|
+
scope :red, lambda { where(:favorite_color => 'red') }, :satisfies => :color
|
27
|
+
scope :salty, lambda { where(:favorite_taste => 'salty') }, :satisfies => :taste
|
28
|
+
end
|
29
|
+
|
30
|
+
should_raise_missing_scopes(:exec_queries, [ :color, :taste ], [ :taste ]) { ::User.salty.to_a }
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should inherit #must_scope_by in child classes" do
|
34
|
+
::User.class_eval do
|
35
|
+
must_scope_by :color
|
36
|
+
scope :red, lambda { where(:favorite_color => 'red') }, :satisfies => :color
|
37
|
+
end
|
38
|
+
|
39
|
+
class ::UserSub1 < ::User
|
40
|
+
self.table_name = ::User.table_name
|
41
|
+
|
42
|
+
must_scope_by :taste
|
43
|
+
scope :salty, lambda { where(:favorite_taste => 'salty') }, :satisfies => :taste
|
44
|
+
end
|
45
|
+
|
46
|
+
should_raise_missing_scopes(:exec_queries, [ :color, :taste ], [ :taste ], :model_class => ::UserSub1) { ::UserSub1.salty.to_a }
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should allow ignoring a required scope in a subclass" do
|
50
|
+
::User.class_eval do
|
51
|
+
must_scope_by :color
|
52
|
+
scope :red, lambda { where(:favorite_color => 'red') }, :satisfies => :color
|
53
|
+
end
|
54
|
+
|
55
|
+
class ::UserSub2 < ::User
|
56
|
+
self.table_name = ::User.table_name
|
57
|
+
|
58
|
+
must_scope_by :taste
|
59
|
+
scope :salty, lambda { where(:favorite_taste => 'salty') }, :satisfies => :taste
|
60
|
+
|
61
|
+
ignore_parent_scope_requirement :color
|
62
|
+
end
|
63
|
+
|
64
|
+
::UserSub2.salty.to_a.should be
|
65
|
+
should_raise_missing_scopes(:exec_queries, [ :taste ], [ ], :model_class => ::UserSub2) { ::UserSub2.all.to_a }
|
66
|
+
end
|
67
|
+
end
|