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 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.
@@ -0,0 +1 @@
1
+ http://ryandaigle.com/articles/2008/8/20/named-scope-it-s-not-just-for-conditions-ya-know
@@ -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,10 @@
1
+ module UtilityScopes
2
+ module Eager
3
+
4
+ def self.included(within)
5
+ within.class_eval do
6
+ named_scope :with, lambda { |*associations| { :include => associations } }
7
+ end
8
+ end
9
+ end
10
+ 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
@@ -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
@@ -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
@@ -0,0 +1,2 @@
1
+ class Article < ActiveRecord::Base
2
+ end
@@ -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
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ Spec::Runner.configure do |config|
5
+ end
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
+