minty_scopes 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "autotest"]
2
+ path = autotest
3
+ url = git://github.com/metaskills/autotest_railsplugin.git
data/README.mkdn ADDED
@@ -0,0 +1,88 @@
1
+ What
2
+ ====
3
+
4
+ A collection of handy `named_scope`s that you should be able to use in just about any model.
5
+
6
+ Why
7
+ ===
8
+
9
+ Named scopes turn ugly finders into pretty ones.
10
+
11
+ Howto
12
+ =====
13
+
14
+ Specify the gem dependency in your `environment.rb`:
15
+
16
+ config.gem 'mintdigital-minty_scopes',
17
+ :lib => 'minty_scopes',
18
+ :source => "http://gems.github.com"
19
+
20
+ Then install and unpack the gem:
21
+
22
+ rake gems:install
23
+ rake gems:unpack
24
+
25
+ In any model, you can get the scopes by extending the module:
26
+
27
+ class Post < ActiveRecord::Base
28
+ extend MintyScopes
29
+ end
30
+
31
+ Scopes
32
+ ======
33
+
34
+ Scopes are grouped into modules by functionality. If you only want some scopes, feel free to extend only the modules you want: `extend MintyScopes::Timestamps`
35
+
36
+ ### Associations ###
37
+
38
+ with(:comments) #=> :joins => :comments, :group => 'posts.id' (only posts with comments)
39
+ without(:comments) #=> :joins => 'LEFT JOIN comments ON posts.id = comments.post_id',
40
+ # :conditions => {'comments.id' => nil}
41
+ including(:comments) #=> :include => [:comments]
42
+
43
+ ### Except ###
44
+
45
+ except(post) #=> [ 'posts.id NOT IN (?)', post ]
46
+ except(post, post) #=> [ 'posts.id NOT IN (?)', [post, post] ]
47
+ except(post_collection) #=> [ 'posts.id NOT IN (?)', post_collection ]
48
+
49
+ ### Order ###
50
+
51
+ newest #=> { :order => 'created_at DESC', :limit => per_page || limit }
52
+ newest(20) #=> { :order => 'created_at DESC', :limit => 20 }
53
+ oldest #=> { :order => 'created_at ASC', :limit => per_page || limit }
54
+ oldest(20) #=> { :order => 'created_at ASC', :limit => 20 }
55
+
56
+ ### Timestamps ###
57
+
58
+ created_on(date) #=> :created_at => (date.beginning_of_day..date.end_of_day)
59
+ modified_on(date) #=> :modified_at => (date.beginning_of_day..date.end_of_day)
60
+
61
+ Thanks
62
+ ======
63
+
64
+ Big thanks to Ryan Daigle for his [utility_scopes](http://github.com/yfactorial/utility_scope) plugin, the inspiration for this project.
65
+
66
+ License
67
+ =======
68
+ The MIT License
69
+
70
+ Copyright (c) 2009 Dean Strelau, Mint Digital
71
+
72
+ Permission is hereby granted, free of charge, to any person obtaining a copy
73
+ of this software and associated documentation files (the "Software"), to deal
74
+ in the Software without restriction, including without limitation the rights
75
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
76
+ copies of the Software, and to permit persons to whom the Software is
77
+ furnished to do so, subject to the following conditions:
78
+
79
+ The above copyright notice and this permission notice shall be included in
80
+ all copies or substantial portions of the Software.
81
+
82
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
83
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
84
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
85
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
86
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
87
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
88
+ THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/gempackagetask'
4
+
5
+ desc 'Default: Run Tests'
6
+ task :default => :test
7
+
8
+ Rake::TestTask.new(:test) do |test|
9
+ test.libs << 'lib' << 'test'
10
+ test.pattern = 'test/**/*_test.rb'
11
+ test.verbose = true
12
+ end
13
+
14
+ begin
15
+ require 'jeweler'
16
+ Jeweler::Tasks.new do |gem|
17
+ gem.name = "minty_scopes"
18
+ gem.summary = %Q{Useful, reusable named_scopes for ActiveRecord.}
19
+ gem.email = "philnash@gmail.com"
20
+ gem.homepage = "https://github.com/mintdigital/minty_scopes"
21
+ gem.authors = ["Dean Strelau", "Mint Digital"]
22
+ gem.extra_rdoc_files = ["README.mkdn", 'Rakefile']
23
+ gem.has_rdoc = false
24
+ gem.rdoc_options = ["--line-numbers", "--inline-source","--main", "README.txt"]
25
+ gem.add_dependency "activerecord", ">= 2.1.0"
26
+ gem.add_dependency "activesupport", ">= 2.1.0"
27
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
28
+ end
29
+ Jeweler::GemcutterTasks.new
30
+ rescue LoadError
31
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
32
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.9.1
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'minty_scopes'
@@ -0,0 +1,28 @@
1
+ module MintyScopes
2
+ module Associations
3
+
4
+ def self.extended(within)
5
+ within.class_eval do
6
+ # Only show items that have at least one of the associated items
7
+ # Meant for has_many associations
8
+ # Post.with(:comments)
9
+ named_scope :with, lambda { |assoc|
10
+ raise "The 'with' named_scope expects a non-nil argument." if assoc.nil?
11
+ { :joins => assoc.to_sym, :group => "#{quoted_table_name}.id" }
12
+ }
13
+
14
+ named_scope :without, lambda {|assoc|
15
+ raise "The 'without' named_scope expects a non-nil argument." if assoc.nil?
16
+ { :joins => "LEFT JOIN #{assoc.to_s} "+
17
+ "ON #{quoted_table_name}.id = #{assoc.to_s}.#{quoted_table_name.singularize}_id",
18
+ :conditions => {"#{assoc}.id" => nil} }
19
+ }
20
+ named_scope :including, lambda {|*assocs|
21
+ { :include => assocs.flatten }
22
+ }
23
+
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ module MintyScopes
2
+ module Except
3
+
4
+ def self.extended(within)
5
+ within.class_eval do
6
+ # Allow easy rejection of items.
7
+ # Can take an a single id or ActiveRecord object, or an array of them
8
+ named_scope :except, lambda { |*args|
9
+ args.flatten!
10
+ raise "The 'except' named_scope expects no nil values." unless args.all?
11
+ { :conditions => ["#{quoted_table_name}.#{primary_key} NOT IN (?)", args] }
12
+ }
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ module MintyScopes
2
+ module Order
3
+
4
+ def self.extended(within)
5
+ within.class_eval do
6
+ # Get only the newest items. Limit by given parameter.
7
+ # Default to per_page if will_paginate is installed or 10
8
+ named_scope :newest, lambda { |*limit| {
9
+ :order => "#{quoted_table_name}.created_at DESC",
10
+ :limit => limit.empty? ? (per_page rescue 10) : limit.first
11
+ } }
12
+
13
+ # Get only the oldest items. Limit by given parameter.
14
+ # Default to per_page if will_paginate is installed or 10
15
+ named_scope :oldest, lambda { |*limit| {
16
+ :order => "#{quoted_table_name}.created_at ASC",
17
+ :limit => limit.empty? ? (per_page rescue 10) : limit.first
18
+ } }
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module MintyScopes
2
+ module Timestamps
3
+
4
+ def self.extended(within)
5
+ within.class_eval do
6
+ # Allow filtering by day of created_on
7
+ # Argument must be a Date, Time, or DateTime
8
+ named_scope :created_on, lambda { |date|
9
+ raise "The 'created_on' named_scope expects a Date, Time or DateTime object" unless date.respond_to? :end_of_day
10
+ { :conditions => {:created_at => (date.beginning_of_day..date.end_of_day)} }
11
+ }
12
+
13
+ # Allow filtering by day of modified_on
14
+ # Argument must be a Date, Time, or DateTime
15
+ named_scope :modified_on, lambda { |date|
16
+ raise "The 'modified_on' named_scope expects a Date, Time or DateTime object" unless date.respond_to? :end_of_day
17
+ { :conditions => {:modified_on => (date.beginning_of_day..date.end_of_day)} }
18
+ }
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ require 'minty_scopes/associations'
2
+ require 'minty_scopes/except'
3
+ require 'minty_scopes/order'
4
+ require 'minty_scopes/timestamps'
5
+
6
+ module MintyScopes
7
+ def self.extended(within)
8
+ within.extend MintyScopes::Associations
9
+ within.extend MintyScopes::Except
10
+ within.extend MintyScopes::Order
11
+ within.extend MintyScopes::Timestamps
12
+ end
13
+ end
@@ -0,0 +1,65 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{minty_scopes}
8
+ s.version = "0.9.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Dean Strelau", "Mint Digital"]
12
+ s.date = %q{2009-12-04}
13
+ s.email = %q{philnash@gmail.com}
14
+ s.extra_rdoc_files = [
15
+ "README.mkdn",
16
+ "Rakefile"
17
+ ]
18
+ s.files = [
19
+ ".gitmodules",
20
+ "README.mkdn",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "init.rb",
24
+ "lib/minty_scopes.rb",
25
+ "lib/minty_scopes/associations.rb",
26
+ "lib/minty_scopes/except.rb",
27
+ "lib/minty_scopes/order.rb",
28
+ "lib/minty_scopes/timestamps.rb",
29
+ "minty_scopes.gemspec",
30
+ "test/test_helper.rb",
31
+ "test/units/associations_test.rb",
32
+ "test/units/except_test.rb",
33
+ "test/units/order_test.rb",
34
+ "test/units/timestamps_test.rb"
35
+ ]
36
+ s.homepage = %q{https://github.com/mintdigital/minty_scopes}
37
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--main", "README.txt"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = %q{1.3.5}
40
+ s.summary = %q{Useful, reusable named_scopes for ActiveRecord.}
41
+ s.test_files = [
42
+ "test/test_helper.rb",
43
+ "test/units/associations_test.rb",
44
+ "test/units/except_test.rb",
45
+ "test/units/order_test.rb",
46
+ "test/units/timestamps_test.rb"
47
+ ]
48
+
49
+ if s.respond_to? :specification_version then
50
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
51
+ s.specification_version = 3
52
+
53
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
54
+ s.add_runtime_dependency(%q<activerecord>, [">= 2.1.0"])
55
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.1.0"])
56
+ else
57
+ s.add_dependency(%q<activerecord>, [">= 2.1.0"])
58
+ s.add_dependency(%q<activesupport>, [">= 2.1.0"])
59
+ end
60
+ else
61
+ s.add_dependency(%q<activerecord>, [">= 2.1.0"])
62
+ s.add_dependency(%q<activesupport>, [">= 2.1.0"])
63
+ end
64
+ end
65
+
@@ -0,0 +1,19 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'minty_scopes'
3
+
4
+ require 'test/unit'
5
+ require 'rubygems'
6
+ require 'shoulda'
7
+ require 'active_record'
8
+ require 'active_support'
9
+
10
+ class Post < ActiveRecord::Base
11
+ def self.quoted_table_name; 'posts'; end
12
+ def self.primary_key; 'id'; end
13
+ extend MintyScopes
14
+ end
15
+
16
+ class PaginatedPost < Post
17
+ def self.per_page; 30; end
18
+ extend MintyScopes
19
+ end
@@ -0,0 +1,39 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class AssociationsTest < Test::Unit::TestCase # :nodoc:
4
+
5
+ context "with" do
6
+ should "complain if passed nil" do
7
+ assert_raise(RuntimeError) { Post.with(nil).proxy_options }
8
+ end
9
+
10
+ should "return all objects with associated items" do
11
+ assert_equal( { :joins => :comments, :group => 'posts.id' },
12
+ Post.with(:comments).proxy_options )
13
+ end
14
+ end
15
+
16
+ context "without" do
17
+ should "complain if passed nil" do
18
+ assert_raise(RuntimeError) { Post.with(nil).proxy_options }
19
+ end
20
+
21
+ should "return all objects without associated items" do
22
+ assert_equal( { :joins => "LEFT JOIN comments ON posts.id = comments.post_id",
23
+ :conditions => {"comments.id" => nil} },
24
+ Post.without(:comments).proxy_options )
25
+ end
26
+ end
27
+
28
+ context "including" do
29
+ should "return objects with given include" do
30
+ assert_equal( { :include => [:comments] },
31
+ Post.including(:comments).proxy_options )
32
+ end
33
+
34
+ should "return objects with all of given includes" do
35
+ assert_equal( { :include => [:comments, {:author => :avator}] },
36
+ Post.including(:comments, {:author => :avator}).proxy_options )
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,33 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class ExceptTest < Test::Unit::TestCase # :nodoc:
4
+
5
+ context "except" do
6
+ should "complain if passed nil" do
7
+ assert_raise(RuntimeError){ Post.except(nil).proxy_options }
8
+ end
9
+
10
+ should "complain if passed an array with nil" do
11
+ assert_raise(RuntimeError) { Post.except([99,nil,101]).proxy_options }
12
+ end
13
+
14
+ should "return all but the given object" do
15
+ item = 123
16
+ assert_equal( { :conditions => ["posts.id NOT IN (?)", [item]] },
17
+ Post.except(item).proxy_options )
18
+ end
19
+
20
+ should "return all but the items in the given list" do
21
+ list = [123, 456, 7]
22
+ assert_equal( { :conditions => ["posts.id NOT IN (?)", list] },
23
+ Post.except(list).proxy_options )
24
+ end
25
+
26
+ should "return all but the given items" do
27
+ maple, oak = 42, 24
28
+ assert_equal( { :conditions => ["posts.id NOT IN (?)", [maple, oak]] },
29
+ Post.except(maple, oak).proxy_options )
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,49 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class OrderTest < Test::Unit::TestCase # :nodoc:
4
+
5
+ context "newest" do
6
+ should "return most recent items" do
7
+ assert Post.newest.proxy_options[:order] = 'posts.created_at DESC'
8
+ end
9
+
10
+ should "default to 10 items" do
11
+ assert_equal 10, Post.newest.proxy_options[:limit]
12
+ end
13
+
14
+ should "use the given limit" do
15
+ assert_equal 20, Post.newest(20).proxy_options[:limit]
16
+ end
17
+
18
+ should "default to per_page if it exists" do
19
+ assert_equal 30, PaginatedPost.newest.proxy_options[:limit]
20
+ end
21
+
22
+ should "use the given limit over per_page" do
23
+ assert_equal 15, PaginatedPost.newest(15).proxy_options[:limit]
24
+ end
25
+ end
26
+
27
+ context "oldest" do
28
+ should "return oldest items" do
29
+ assert Post.oldest.proxy_options[:order] = 'posts.created_at ASC'
30
+ end
31
+
32
+ should "default to 10 items" do
33
+ assert_equal 10, Post.oldest.proxy_options[:limit]
34
+ end
35
+
36
+ should "use the given limit" do
37
+ assert_equal 20, Post.oldest(20).proxy_options[:limit]
38
+ end
39
+
40
+ should "default to per_page if it exists" do
41
+ assert_equal 30, PaginatedPost.oldest.proxy_options[:limit]
42
+ end
43
+
44
+ should "use the given limit over per_page" do
45
+ assert_equal 15, PaginatedPost.oldest(15).proxy_options[:limit]
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,32 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class TimestampsTest < Test::Unit::TestCase # :nodoc:
4
+ def setup
5
+ @today = Date.today
6
+ end
7
+
8
+ context "created_on" do
9
+ should "complain if passed a non date or time" do
10
+ assert_raise(RuntimeError){ Post.created_on(nil).proxy_options }
11
+ end
12
+
13
+ should "return all objects created on the given date" do
14
+ assert_equal({:conditions =>
15
+ { :created_at => (@today.beginning_of_day..@today.end_of_day) }
16
+ }, Post.created_on(@today).proxy_options)
17
+ end
18
+ end
19
+
20
+ context "modified_on" do
21
+ should "complain if passed a non date or time" do
22
+ assert_raise(RuntimeError){ Post.modified_on(nil).proxy_options }
23
+ end
24
+
25
+ should "return all objects modified on the given date" do
26
+ assert_equal({:conditions =>
27
+ { :modified_on => (@today.beginning_of_day..@today.end_of_day) }
28
+ }, Post.modified_on(@today).proxy_options)
29
+ end
30
+ end
31
+
32
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minty_scopes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
+ platform: ruby
6
+ authors:
7
+ - Dean Strelau
8
+ - Mint Digital
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-12-04 00:00:00 +00:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: activerecord
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 2.1.0
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: activesupport
28
+ type: :runtime
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 2.1.0
35
+ version:
36
+ description:
37
+ email: philnash@gmail.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - README.mkdn
44
+ - Rakefile
45
+ files:
46
+ - .gitmodules
47
+ - README.mkdn
48
+ - Rakefile
49
+ - VERSION
50
+ - init.rb
51
+ - lib/minty_scopes.rb
52
+ - lib/minty_scopes/associations.rb
53
+ - lib/minty_scopes/except.rb
54
+ - lib/minty_scopes/order.rb
55
+ - lib/minty_scopes/timestamps.rb
56
+ - minty_scopes.gemspec
57
+ - test/test_helper.rb
58
+ - test/units/associations_test.rb
59
+ - test/units/except_test.rb
60
+ - test/units/order_test.rb
61
+ - test/units/timestamps_test.rb
62
+ has_rdoc: true
63
+ homepage: https://github.com/mintdigital/minty_scopes
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --line-numbers
69
+ - --inline-source
70
+ - --main
71
+ - README.txt
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ version:
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: "0"
85
+ version:
86
+ requirements: []
87
+
88
+ rubyforge_project:
89
+ rubygems_version: 1.3.5
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: Useful, reusable named_scopes for ActiveRecord.
93
+ test_files:
94
+ - test/test_helper.rb
95
+ - test/units/associations_test.rb
96
+ - test/units/except_test.rb
97
+ - test/units/order_test.rb
98
+ - test/units/timestamps_test.rb