4 require 'models/comment'
6 require 'models/author'
7 require 'models/developer'
9 class NamedScopeTest
< ActiveRecord
::TestCase
10 fixtures
:posts, :authors, :topics, :comments, :author_addresses
12 def test_implements_enumerable
13 assert
!Topic
.find(:all).empty
?
15 assert_equal Topic
.find(:all), Topic
.base
16 assert_equal Topic
.find(:all), Topic
.base
.to_a
17 assert_equal Topic
.find(:first), Topic
.base
.first
18 assert_equal Topic
.find(:all), Topic
.base
.map
{ |i
| i
}
21 def test_found_items_are_cached
23 all_posts
= Topic
.base
31 def test_reload_expires_cache_of_found_items
32 all_posts
= Topic
.base
35 new_post
= Topic
.create
!
36 assert
!all_posts
.include?(new_post
)
37 assert all_posts
.reload
.include?(new_post
)
40 def test_delegates_finds_and_calculations_to_the_base_class
41 assert
!Topic
.find(:all).empty
?
43 assert_equal Topic
.find(:all), Topic
.base
.find(:all)
44 assert_equal Topic
.find(:first), Topic
.base
.find(:first)
45 assert_equal Topic
.count
, Topic
.base
.count
46 assert_equal Topic
.average(:replies_count), Topic
.base
.average(:replies_count)
49 def test_scope_should_respond_to_own_methods_and_methods_of_the_proxy
50 assert Topic
.approved
.respond_to
?(:proxy_found)
51 assert Topic
.approved
.respond_to
?(:count)
52 assert Topic
.approved
.respond_to
?(:length)
55 def test_respond_to_respects_include_private_parameter
56 assert
!Topic
.approved
.respond_to
?(:load_found)
57 assert Topic
.approved
.respond_to
?(:load_found, true)
60 def test_subclasses_inherit_scopes
61 assert Topic
.scopes
.include?(:base)
63 assert Reply
.scopes
.include?(:base)
64 assert_equal Reply
.find(:all), Reply
.base
67 def test_scopes_with_options_limit_finds_to_those_matching_the_criteria_specified
68 assert
!Topic
.find(:all, :conditions => {:approved => true}).empty
?
70 assert_equal Topic
.find(:all, :conditions => {:approved => true}), Topic
.approved
71 assert_equal Topic
.count(:conditions => {:approved => true}), Topic
.approved
.count
74 def test_scopes_with_string_name_can_be_composed
75 # NOTE that scopes defined with a string as a name worked on their own
76 # but when called on another scope the other scope was completely replaced
77 assert_equal Topic
.replied
.approved
, Topic
.replied
.approved_as_string
80 def test_scopes_can_be_specified_with_deep_hash_conditions
81 assert_equal Topic
.replied
.approved
, Topic
.replied
.approved_as_hash_condition
84 def test_scopes_are_composable
85 assert_equal (approved
= Topic
.find(:all, :conditions => {:approved => true})), Topic
.approved
86 assert_equal (replied
= Topic
.find(:all, :conditions => 'replies_count > 0')), Topic
.replied
87 assert
!(approved
== replied
)
88 assert
!(approved
& replied
).empty
?
90 assert_equal approved
& replied
, Topic
.approved
.replied
93 def test_procedural_scopes
94 topics_written_before_the_third
= Topic
.find(:all, :conditions => ['written_on < ?', topics(:third).written_on
])
95 topics_written_before_the_second
= Topic
.find(:all, :conditions => ['written_on < ?', topics(:second).written_on
])
96 assert_not_equal topics_written_before_the_second
, topics_written_before_the_third
98 assert_equal topics_written_before_the_third
, Topic
.written_before(topics(:third).written_on
)
99 assert_equal topics_written_before_the_second
, Topic
.written_before(topics(:second).written_on
)
102 def test_procedural_scopes_returning_nil
103 all_topics
= Topic
.find(:all)
105 assert_equal all_topics
, Topic
.written_before(nil)
108 def test_scopes_with_joins
109 address
= author_addresses(:david_address)
110 posts_with_authors_at_address
= Post
.find(
111 :all, :joins => 'JOIN authors ON authors.id = posts.author_id',
112 :conditions => [ 'authors.author_address_id = ?', address
.id
]
114 assert_equal posts_with_authors_at_address
, Post
.with_authors_at_address(address
)
117 def test_scopes_with_joins_respects_custom_select
118 address
= author_addresses(:david_address)
119 posts_with_authors_at_address_titles
= Post
.find(:all,
121 :joins => 'JOIN authors ON authors.id = posts.author_id',
122 :conditions => [ 'authors.author_address_id = ?', address
.id
]
124 assert_equal posts_with_authors_at_address_titles
, Post
.with_authors_at_address(address
).find(:all, :select => 'title')
128 assert_equal
1, Topic
.anonymous_extension
.one
129 assert_equal
2, Topic
.named_extension
.two
132 def test_multiple_extensions
133 assert_equal
2, Topic
.multiple_extensions
.extension_two
134 assert_equal
1, Topic
.multiple_extensions
.extension_one
137 def test_has_many_associations_have_access_to_named_scopes
138 assert_not_equal Post
.containing_the_letter_a
, authors(:david).posts
139 assert
!Post
.containing_the_letter_a
.empty
?
141 assert_equal
authors(:david).posts
& Post
.containing_the_letter_a
, authors(:david).posts
.containing_the_letter_a
144 def test_has_many_through_associations_have_access_to_named_scopes
145 assert_not_equal Comment
.containing_the_letter_e
, authors(:david).comments
146 assert
!Comment
.containing_the_letter_e
.empty
?
148 assert_equal
authors(:david).comments
& Comment
.containing_the_letter_e
, authors(:david).comments
.containing_the_letter_e
151 def test_named_scopes_honor_current_scopes_from_when_defined
152 assert
!Post
.ranked_by_comments
.limit(5).empty
?
153 assert
!authors(:david).posts
.ranked_by_comments
.limit(5).empty
?
154 assert_not_equal Post
.ranked_by_comments
.limit(5), authors(:david).posts
.ranked_by_comments
.limit(5)
155 assert_not_equal Post
.top(5), authors(:david).posts
.top(5)
156 assert_equal
authors(:david).posts
.ranked_by_comments
.limit(5), authors(:david).posts
.top(5)
157 assert_equal Post
.ranked_by_comments
.limit(5), Post
.top(5)
160 def test_active_records_have_scope_named__all__
161 assert
!Topic
.find(:all).empty
?
163 assert_equal Topic
.find(:all), Topic
.base
166 def test_active_records_have_scope_named__scoped__
167 assert
!Topic
.find(:all, scope
= {:conditions => "content LIKE '%Have%'"}).empty
?
169 assert_equal Topic
.find(:all, scope
), Topic
.scoped(scope
)
172 def test_proxy_options
173 expected_proxy_options
= { :conditions => { :approved => true } }
174 assert_equal expected_proxy_options
, Topic
.approved
.proxy_options
177 def test_first_and_last_should_support_find_options
178 assert_equal Topic
.base
.first(:order => 'title'), Topic
.base
.find(:first, :order => 'title')
179 assert_equal Topic
.base
.last(:order => 'title'), Topic
.base
.find(:last, :order => 'title')
182 def test_first_and_last_should_allow_integers_for_limit
183 assert_equal Topic
.base
.first(2), Topic
.base
.to_a
.first(2)
184 assert_equal Topic
.base
.last(2), Topic
.base
.to_a
.last(2)
187 def test_first_and_last_should_not_use_query_when_results_are_loaded
189 topics
.reload
# force load
196 def test_first_and_last_find_options_should_use_query_when_results_are_loaded
198 topics
.reload
# force load
200 topics
.first(:order => 'title')
201 topics
.last(:order => 'title')
205 def test_empty_should_not_load_results
208 topics
.empty
? # use count query
209 topics
.collect
# force load
210 topics
.empty
? # use loaded (no query)
214 def test_any_should_not_load_results
217 topics
.any
? # use count query
218 topics
.collect
# force load
219 topics
.any
? # use loaded (no query)
223 def test_any_should_call_proxy_found_if_using_a_block
226 topics
.expects(:empty?).never
231 def test_any_should_not_fire_query_if_named_scope_loaded
233 topics
.collect
# force load
234 assert_no_queries
{ assert topics
.any
? }
237 def test_should_build_with_proxy_options
238 topic
= Topic
.approved
.build({})
239 assert topic
.approved
242 def test_should_build_new_with_proxy_options
243 topic
= Topic
.approved
.new
244 assert topic
.approved
247 def test_should_create_with_proxy_options
248 topic
= Topic
.approved
.create({})
249 assert topic
.approved
252 def test_should_create_with_bang_with_proxy_options
253 topic
= Topic
.approved
.create
!({})
254 assert topic
.approved
257 def test_should_build_with_proxy_options_chained
258 topic
= Topic
.approved
.by_lifo
.build({})
259 assert topic
.approved
260 assert_equal
'lifo', topic
.author_name
263 def test_find_all_should_behave_like_select
264 assert_equal Topic
.base
.select(&:approved), Topic
.base
.find_all(&:approved)
267 def test_rand_should_select_a_random_object_from_proxy
268 assert Topic
.approved
.rand
.is_a
?(Topic
)
271 def test_should_use_where_in_query_for_named_scope
272 assert_equal Developer
.find_all_by_name('Jamis').to_set
, Developer
.find_all_by_id(Developer
.jamises
).to_set
275 def test_size_should_use_count_when_results_are_not_loaded
278 assert_sql(/COUNT/i
) { topics
.size
}
282 def test_size_should_use_length_when_results_are_loaded
284 topics
.reload
# force load
286 topics
.size
# use loaded (no query)
290 def test_chaining_with_duplicate_joins
291 join
= "INNER JOIN comments ON comments.post_id = posts.id"
293 assert_equal post
.comments
.size
, Post
.scoped(:joins => join
).scoped(:joins => join
, :conditions => "posts.id = #{post.id}").size
296 def test_chaining_should_use_latest_conditions_when_creating
297 post
= Topic
.rejected
.new
298 assert
!post
.approved
?
300 post
= Topic
.rejected
.approved
.new
301 assert post
.approved
?
303 post
= Topic
.approved
.rejected
.new
304 assert
!post
.approved
?
306 post
= Topic
.approved
.rejected
.approved
.new
307 assert post
.approved
?
310 def test_chaining_should_use_latest_conditions_when_searching
311 # Normal hash conditions
312 assert_equal Topic
.all(:conditions => {:approved => true}), Topic
.rejected
.approved
.all
313 assert_equal Topic
.all(:conditions => {:approved => false}), Topic
.approved
.rejected
.all
315 # Nested hash conditions with same keys
316 assert_equal
[posts(:sti_comments)], Post
.with_special_comments
.with_very_special_comments
.all
318 # Nested hash conditions with different keys
319 assert_equal
[posts(:sti_comments)], Post
.with_special_comments
.with_post(4).all
.uniq
322 def test_methods_invoked_within_scopes_should_respect_scope
323 assert_equal
[], Topic
.approved
.by_rejected_ids
.proxy_options
[:conditions][:id]
326 def test_named_scopes_batch_finders
327 assert_equal
3, Topic
.approved
.count
330 Topic
.approved
.find_each(:batch_size => 1) {|t
| assert t
.approved
? }
334 Topic
.approved
.find_in_batches(:batch_size => 2) do |group
|
335 group
.each
{|t
| assert t
.approved
? }
341 class DynamicScopeMatchTest
< ActiveRecord
::TestCase
342 def test_scoped_by_no_match
343 assert_nil ActiveRecord
::DynamicScopeMatch.match("not_scoped_at_all")
347 match
= ActiveRecord
::DynamicScopeMatch.match("scoped_by_age_and_sex_and_location")
350 assert_equal
%w(age sex location
), match
.attribute_names
354 class DynamicScopeTest
< ActiveRecord
::TestCase
355 def test_dynamic_scope
356 assert_equal Post
.scoped_by_author_id(1).find(1), Post
.find(1)
357 assert_equal Post
.scoped_by_author_id_and_title(1, "Welcome to the weblog").first
, Post
.find(:first, :conditions => { :author_id => 1, :title => "Welcome to the weblog"})