yfactorial-utility_scopes 0.1.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.
- data/LICENSE +18 -0
- data/README.rdoc +1 -0
- data/Rakefile +18 -0
- data/init.rb +1 -0
- data/lib/utility_scopes.rb +15 -0
- data/lib/utility_scopes/eager.rb +10 -0
- data/lib/utility_scopes/except.rb +21 -0
- data/lib/utility_scopes/limited.rb +26 -0
- data/lib/utility_scopes/ordered.rb +52 -0
- data/spec/abstract_spec.rb +10 -0
- data/spec/eager_spec.rb +20 -0
- data/spec/except_spec.rb +25 -0
- data/spec/fixtures/article.rb +2 -0
- data/spec/limit_spec.rb +36 -0
- data/spec/ordered_spec.rb +28 -0
- data/spec/spec_helper.rb +5 -0
- metadata +85 -0
data/LICENSE
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Copyright (c) 2008 Ryan Daigle
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
5
|
+
the Software without restriction, including without limitation the rights to
|
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
7
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
8
|
+
subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
15
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
16
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
http://ryandaigle.com/articles/2008/8/20/named-scope-it-s-not-just-for-conditions-ya-know
|
data/Rakefile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake'
|
|
3
|
+
require 'rake/rdoctask'
|
|
4
|
+
|
|
5
|
+
# TODO add task to execute specs
|
|
6
|
+
|
|
7
|
+
desc 'Generate RDoc documentation.'
|
|
8
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
9
|
+
rdoc.rdoc_files.include('README.rdoc', 'LICENSE', 'Rakefile').
|
|
10
|
+
include('lib/**/*.rb')
|
|
11
|
+
|
|
12
|
+
rdoc.main = "README.rdoc"
|
|
13
|
+
rdoc.title = "utility_scopes documentation"
|
|
14
|
+
|
|
15
|
+
rdoc.rdoc_dir = 'doc' # rdoc output folder
|
|
16
|
+
rdoc.options << '--inline-source' << '--charset=UTF-8'
|
|
17
|
+
rdoc.options << '--webcvs=http://github.com/yfactorial/utility_scopes/tree/master/'
|
|
18
|
+
end
|
data/init.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'utility_scopes'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'utility_scopes/limited'
|
|
2
|
+
require 'utility_scopes/ordered'
|
|
3
|
+
require 'utility_scopes/eager'
|
|
4
|
+
require 'utility_scopes/except'
|
|
5
|
+
|
|
6
|
+
if defined?(ActiveRecord)
|
|
7
|
+
|
|
8
|
+
ActiveRecord::Base.class_eval do
|
|
9
|
+
include UtilityScopes::Limited
|
|
10
|
+
include UtilityScopes::Ordered
|
|
11
|
+
include UtilityScopes::Eager
|
|
12
|
+
include UtilityScopes::Except
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module UtilityScopes
|
|
2
|
+
module Except
|
|
3
|
+
|
|
4
|
+
def self.included(within)
|
|
5
|
+
|
|
6
|
+
within.class_eval do
|
|
7
|
+
|
|
8
|
+
# Allow easy rejection of items.
|
|
9
|
+
# Can take an a single id or ActiveRecord object, or an array of them
|
|
10
|
+
# Example:
|
|
11
|
+
# before Article.all.reject{|a| a == @bad_article }
|
|
12
|
+
# after Article.except(@bad_article)
|
|
13
|
+
named_scope :except, lambda { |item_or_list|
|
|
14
|
+
# nil or empty array causes issues here with mysql
|
|
15
|
+
item_or_list.blank? ? {} : {:conditions => ["#{quoted_table_name}.#{primary_key} NOT IN (?)", item_or_list]}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module UtilityScopes
|
|
2
|
+
module Limited
|
|
3
|
+
|
|
4
|
+
def self.included(within)
|
|
5
|
+
|
|
6
|
+
within.class_eval do
|
|
7
|
+
|
|
8
|
+
# Provide default limit scope (can be overridden
|
|
9
|
+
# if default_limit is called)
|
|
10
|
+
named_scope :limited, lambda { |*num|
|
|
11
|
+
{ :limit => num.flatten.first || (defined?(per_page) ? per_page : 10) }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
extend ClassMethods
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module ClassMethods
|
|
19
|
+
|
|
20
|
+
# Set the default limit to use for the limit scope
|
|
21
|
+
def default_limit(default)
|
|
22
|
+
named_scope :limited, lambda { |*num| { :limit => num.flatten.first || default } }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module UtilityScopes
|
|
2
|
+
module Ordered
|
|
3
|
+
|
|
4
|
+
def self.included(within)
|
|
5
|
+
within.class_eval do
|
|
6
|
+
|
|
7
|
+
# Provide an ordered scope
|
|
8
|
+
named_scope :ordered, lambda { |*order|
|
|
9
|
+
{ :order => order.flatten.first || self.default_ordering }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
# Set the default order
|
|
13
|
+
class << self
|
|
14
|
+
define_method(:default_ordering) { 'created_at DESC' }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
extend ClassMethods
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
module ClassMethods
|
|
22
|
+
|
|
23
|
+
# Decorate this class with the ability to order itself in queries
|
|
24
|
+
# either from a given parameter or from its default ordering:
|
|
25
|
+
#
|
|
26
|
+
# class Article < ActiveRecord::Base
|
|
27
|
+
# ordered_by "published_at DESC"
|
|
28
|
+
# end
|
|
29
|
+
#
|
|
30
|
+
# Article.ordered #=> all items ordered by "published_at DESC"
|
|
31
|
+
# Article.ordered('popularity ASC') #=> all items ordered by "popularity ASC"
|
|
32
|
+
# Article.default_ordering #=> "published_at DESC"
|
|
33
|
+
#
|
|
34
|
+
def ordered_by(clause)
|
|
35
|
+
|
|
36
|
+
# Override named scope on AR::Base so we can access default_ordering
|
|
37
|
+
# on subclass
|
|
38
|
+
named_scope :ordered, lambda { |*order|
|
|
39
|
+
{ :order => order.flatten.first || self.default_ordering }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
metaclass.instance_eval do
|
|
43
|
+
define_method(:default_ordering) { clause }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def metaclass; class << self; self end; end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[spec_helper])
|
|
2
|
+
require 'activerecord'
|
|
3
|
+
|
|
4
|
+
$:.unshift "#{File.dirname(__FILE__)}/../lib"
|
|
5
|
+
require 'utility_scopes'
|
|
6
|
+
|
|
7
|
+
# Load a test class
|
|
8
|
+
def uses_fixture(fixture_name)
|
|
9
|
+
require File.join(File.dirname(__FILE__), 'fixtures', fixture_name.to_s)
|
|
10
|
+
end
|
data/spec/eager_spec.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[abstract_spec])
|
|
2
|
+
|
|
3
|
+
describe "Eager scope" do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
uses_fixture(:article)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should provide eager loading of a single association" do
|
|
10
|
+
Article.with(:comments).proxy_options.should == {:include => [:comments] }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should provide eager loading of a multiple associations" do
|
|
14
|
+
Article.with(:comments, :contributors).proxy_options.should == {:include => [:comments, :contributors] }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should provider eager loading of nested associations" do
|
|
18
|
+
Article.with(:comments => :author).proxy_options.should == {:include => [ {:comments => :author} ] }
|
|
19
|
+
end
|
|
20
|
+
end
|
data/spec/except_spec.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[abstract_spec])
|
|
2
|
+
|
|
3
|
+
describe "except scope" do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
uses_fixture(:article)
|
|
7
|
+
# Stub these so it doesn't try to hit the (non-existant) database
|
|
8
|
+
ActiveRecord::Base.stub!(:quoted_table_name).and_return('articles')
|
|
9
|
+
ActiveRecord::Base.stub!(:primary_key).and_return('id')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should not change the scope with nil" do
|
|
13
|
+
Article.except(nil).proxy_options.should == {}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should return all items except the one specified" do
|
|
17
|
+
item = 123
|
|
18
|
+
Article.except(item).proxy_options.should == {:conditions => ['articles.id NOT IN (?)', item]}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should return all items except ones in the list specified" do
|
|
22
|
+
list = [123, 456, 7]
|
|
23
|
+
Article.except(list).proxy_options.should == {:conditions => ['articles.id NOT IN (?)', list]}
|
|
24
|
+
end
|
|
25
|
+
end
|
data/spec/limit_spec.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[abstract_spec])
|
|
2
|
+
|
|
3
|
+
describe "limited scope" do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
uses_fixture(:article)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should default to a limited of 10" do
|
|
10
|
+
Article.limited.proxy_options.should == {:limit => 10}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should allow the limited to be specified at runtime" do
|
|
14
|
+
Article.limited(20).proxy_options.should == {:limit => 20}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should find the per_page value from will_paginate" do
|
|
18
|
+
ActiveRecord::Base.instance_eval { def per_page; 50; end }
|
|
19
|
+
Article.limited.proxy_options.should == {:limit => 50}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should use the runtime limited value over the per_page value from will_paginate" do
|
|
23
|
+
ActiveRecord::Base.instance_eval { def per_page; 50; end }
|
|
24
|
+
Article.limited(5).proxy_options.should == {:limit => 5}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should allow override the default limited value with 'default_limited'" do
|
|
28
|
+
Article.default_limit 13
|
|
29
|
+
Article.limited.proxy_options.should == {:limit => 13}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should use the runtime value over the default limited value set with 'default_limited'" do
|
|
33
|
+
Article.default_limit 13
|
|
34
|
+
Article.limited(25).proxy_options.should == {:limit => 25}
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[abstract_spec])
|
|
2
|
+
|
|
3
|
+
describe "Ordered scope" do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
uses_fixture(:article)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should default to created_at DESC" do
|
|
10
|
+
Article.ordered.proxy_options.should == {:order => 'created_at DESC'}
|
|
11
|
+
Article.default_ordering.should == 'created_at DESC'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should allow the order to be specified at runtime" do
|
|
15
|
+
Article.ordered('created_at ASC').proxy_options.should == {:order => 'created_at ASC'}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should allow the default to be overidden by using ordered_by" do
|
|
19
|
+
Article.ordered_by 'published_at DESC'
|
|
20
|
+
Article.default_ordering.should == 'published_at DESC'
|
|
21
|
+
Article.ordered.proxy_options.should == {:order => 'published_at DESC'}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should use the runtime sort value over the ordered_by value" do
|
|
25
|
+
Article.ordered_by 'published_at DESC'
|
|
26
|
+
Article.ordered('popularity ASC').proxy_options.should == {:order => 'popularity ASC'}
|
|
27
|
+
end
|
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: yfactorial-utility_scopes
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Ryan Daigle
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2008-08-20 00:00:00 -07:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: activerecord
|
|
17
|
+
version_requirement:
|
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
19
|
+
requirements:
|
|
20
|
+
- - ">="
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: 2.1.0
|
|
23
|
+
version:
|
|
24
|
+
description: A collection of utilitarian named scopes providing common functionality for ActiveRecord models.
|
|
25
|
+
email: ryan@yfactorial.com
|
|
26
|
+
executables: []
|
|
27
|
+
|
|
28
|
+
extensions: []
|
|
29
|
+
|
|
30
|
+
extra_rdoc_files:
|
|
31
|
+
- README.rdoc
|
|
32
|
+
- Rakefile
|
|
33
|
+
- LICENSE
|
|
34
|
+
files:
|
|
35
|
+
- README.rdoc
|
|
36
|
+
- Rakefile
|
|
37
|
+
- LICENSE
|
|
38
|
+
- init.rb
|
|
39
|
+
- lib
|
|
40
|
+
- lib/utility_scopes
|
|
41
|
+
- lib/utility_scopes.rb
|
|
42
|
+
- lib/utility_scopes/eager.rb
|
|
43
|
+
- lib/utility_scopes/except.rb
|
|
44
|
+
- lib/utility_scopes/limited.rb
|
|
45
|
+
- lib/utility_scopes/ordered.rb
|
|
46
|
+
- spec
|
|
47
|
+
- spec/abstract_spec.rb
|
|
48
|
+
- spec/eager_spec.rb
|
|
49
|
+
- spec/except_spec.rb
|
|
50
|
+
- spec/limit_spec.rb
|
|
51
|
+
- spec/ordered_spec.rb
|
|
52
|
+
- spec/spec_helper.rb
|
|
53
|
+
- spec/fixtures
|
|
54
|
+
- spec/fixtures/article.rb
|
|
55
|
+
has_rdoc: true
|
|
56
|
+
homepage: http://github.com/yfactorial/utility_scopes
|
|
57
|
+
post_install_message:
|
|
58
|
+
rdoc_options:
|
|
59
|
+
- --main
|
|
60
|
+
- README.rdoc
|
|
61
|
+
- --inline-source
|
|
62
|
+
- --charset=UTF-8
|
|
63
|
+
require_paths:
|
|
64
|
+
- lib
|
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - ">="
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: "0"
|
|
70
|
+
version:
|
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: "0"
|
|
76
|
+
version:
|
|
77
|
+
requirements: []
|
|
78
|
+
|
|
79
|
+
rubyforge_project:
|
|
80
|
+
rubygems_version: 1.2.0
|
|
81
|
+
signing_key:
|
|
82
|
+
specification_version: 2
|
|
83
|
+
summary: A collection of utilitarian named scopes providing common functionality for ActiveRecord models
|
|
84
|
+
test_files: []
|
|
85
|
+
|