dstrelau-minty_scopes 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.mkdn ADDED
@@ -0,0 +1,60 @@
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
+ # environment.rb
15
+ config.gem 'dstrelau-minty_scopes', :source => "http://gems.github.com"
16
+
17
+ # any model
18
+ class Post < ActiveRecord::Base
19
+ extend MintyScopes
20
+ end
21
+
22
+ Scopes
23
+ ======
24
+
25
+ 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`
26
+
27
+ ### Associations ###
28
+
29
+ with(:comments) #=> :joins => :comments, :group => 'posts.id' (only posts with comments)
30
+ without(:comments) #=> :joins => 'LEFT JOIN comments ON posts.id = comments.post_id',
31
+ # :conditions => {'comments.id' => nil}
32
+ including(:comments) #=> :include => [:comments]
33
+
34
+ ### Except ###
35
+
36
+ except(post) #=> [ 'posts.id NOT IN (?)', post ]
37
+ except(post, post) #=> [ 'posts.id NOT IN (?)', [post, post] ]
38
+ except(post_collection) #=> [ 'posts.id NOT IN (?)', post_collection ]
39
+
40
+ ### Order ###
41
+
42
+ newest #=> { :order => 'created_at DESC', :limit => per_page || limit }
43
+ newest(20) #=> { :order => 'created_at DESC', :limit => 20 }
44
+ oldest #=> { :order => 'created_at ASC', :limit => per_page || limit }
45
+ oldest(20) #=> { :order => 'created_at ASC', :limit => 20 }
46
+
47
+ ### Timestamps ###
48
+
49
+ created_on(date) #=> :created_at => (date.beginning_of_day..date.end_of_day)
50
+ modified_on(date) #=> :modified_at => (date.beginning_of_day..date.end_of_day)
51
+
52
+ Thanks
53
+ ======
54
+
55
+ Big thanks to Ryan Daigle for his [utility_scopes](http://github.com/yfactorial/utility_scope) plugin, the inspiration for this project.
56
+
57
+ License
58
+ =======
59
+
60
+ © 2008 Dean Strelau, Mint Digital. All Rights Reserved.
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/gempackagetask'
4
+ require 'lib/minty_scopes/version'
5
+
6
+ desc 'Default: Run Tests'
7
+ task :default => ['test']
8
+
9
+ spec = Gem::Specification.new do |s|
10
+ s.name = "minty_scopes"
11
+ s.version = MintyScopes::VERSION
12
+ s.summary = "Useful, reusable named_scopes for ActiveRecord."
13
+ s.homepage = "https://github.com/dstrelau/minty_scopes"
14
+
15
+ s.files = FileList["[A-Z]*", "{lib,test}/**/*"]
16
+
17
+ s.has_rdoc = false
18
+ s.extra_rdoc_files = ["README.mkdn", 'Rakefile']
19
+ s.rdoc_options = ["--line-numbers", "--inline-source",
20
+ "--main", "README.txt"]
21
+
22
+ s.authors = ["Dean Strelau"]
23
+ s.email = "dean@mintdigital.com"
24
+
25
+ s.add_dependency "activerecord", ">= 2.1.0"
26
+ s.add_dependency "activesupport", ">= 2.1.0"
27
+ end
28
+
29
+ Rake::GemPackageTask.new spec do |pkg|
30
+ pkg.need_tar = true
31
+ pkg.need_zip = true
32
+ end
33
+
34
+ desc "Generate a gemspec file for GitHub"
35
+ task :gemspec do
36
+ File.open("#{spec.name}.gemspec", 'w') do |f|
37
+ f.write spec.to_ruby
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ require 'minty_scopes/version'
2
+
3
+ require 'minty_scopes/associations'
4
+ require 'minty_scopes/except'
5
+ require 'minty_scopes/order'
6
+ require 'minty_scopes/timestamps'
7
+
8
+ module MintyScopes
9
+ def self.extended(within)
10
+ within.extend MintyScopes::Associations
11
+ within.extend MintyScopes::Except
12
+ within.extend MintyScopes::Order
13
+ within.extend MintyScopes::Timestamps
14
+ end
15
+ end
@@ -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,3 @@
1
+ module MintyScopes
2
+ VERSION = '0.9.0'
3
+ end
@@ -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 'activerecord'
8
+ require 'activesupport'
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,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dstrelau-minty_scopes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Dean Strelau
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-10-02 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
+ - !ruby/object:Gem::Dependency
25
+ name: activesupport
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 2.1.0
32
+ version:
33
+ description:
34
+ email: dean@mintdigital.com
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - README.mkdn
41
+ - Rakefile
42
+ files:
43
+ - Rakefile
44
+ - README.mkdn
45
+ - lib/minty_scopes
46
+ - lib/minty_scopes/associations.rb
47
+ - lib/minty_scopes/except.rb
48
+ - lib/minty_scopes/order.rb
49
+ - lib/minty_scopes/timestamps.rb
50
+ - lib/minty_scopes/version.rb
51
+ - lib/minty_scopes.rb
52
+ - test/test_helper.rb
53
+ - test/units
54
+ - test/units/associations_test.rb
55
+ - test/units/except_test.rb
56
+ - test/units/order_test.rb
57
+ - test/units/timestamps_test.rb
58
+ has_rdoc: false
59
+ homepage: https://github.com/dstrelau/minty_scopes
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --line-numbers
63
+ - --inline-source
64
+ - --main
65
+ - README.txt
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ version:
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 1.2.0
84
+ signing_key:
85
+ specification_version: 2
86
+ summary: Useful, reusable named_scopes for ActiveRecord.
87
+ test_files: []
88
+