paged_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.
@@ -0,0 +1,72 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Resources" do
4
+ before(:each) do
5
+ ActionController::Routing::Routes.clear!
6
+ end
7
+
8
+ after(:each) do
9
+ ActionController::Routing::Routes.clear!
10
+ end
11
+
12
+ it "should not affect normal resource mapping if :paged option is not specified" do
13
+ drawing_routes { |map| map.resources :articles }.should change { number_of_routes }.by(7)
14
+ end
15
+
16
+ it "should add a paged index route if a :paged option is specified" do
17
+ drawing_routes { |map| map.resources :articles, :paged => true }.should change { number_of_routes }.by(7+1)
18
+ end
19
+
20
+ context "with a :paged options" do
21
+ it "should map a paged index route for GET only" do
22
+ draw_routes { |map| map.resources :articles, :paged => true }
23
+ recognise_path( :get, "/pages/1/articles").should == { :controller => "articles", :action => "index", :page_id => "1" }
24
+ recognise_path( :put, "/pages/1/articles").should be_nil
25
+ recognise_path( :post, "/pages/1/articles").should be_nil
26
+ recognise_path(:delete, "/pages/1/articles").should be_nil
27
+ end
28
+
29
+ it "should add a named route for the paged index route" do
30
+ draw_routes { |map| map.resources :articles, :paged => true }
31
+ named_routes.names.should include(:page_articles)
32
+ end
33
+
34
+ it "should observe the :path_prefix option in the paged route" do
35
+ draw_routes { |map| map.resources :articles, :paged => true, :path_prefix => "foo" }
36
+ recognise_path(:get, "/foo/pages/1/articles").should == { :controller => "articles", :action => "index", :page_id => "1" }
37
+ end
38
+
39
+ it "should observe a :namespace option in the paged route" do
40
+ draw_routes { |map| map.resources :articles, :paged => true, :namespace => "bar/" }
41
+ recognise_path(:get, "/pages/1/articles").should == { :controller => "bar/articles", :action => "index", :page_id => "1" }
42
+ end
43
+
44
+ it "should accept an :as option in the :paged option" do
45
+ draw_routes { |map| map.resources :articles, :paged => { :as => "page" } }
46
+ recognise_path(:get, "/page/1/articles").should == { :controller => "articles", :action => "index", :page_id => "1" }
47
+ end
48
+
49
+ it "should accept a :name option in the :paged option" do
50
+ draw_routes { |map| map.resources :articles, :paged => { :name => :groups } }
51
+ recognise_path(:get, "/groups/1/articles").should == { :controller => "articles", :action => "index", :group_id => "1" }
52
+ end
53
+
54
+ it "should accept a :path_prefix hash as the :paged option" do
55
+ draw_routes { |map| map.resources :articles, :paged => true, :name_prefix => "baz_" }
56
+ named_routes.names.should include(:baz_page_articles)
57
+ end
58
+
59
+ context "and nested resources" do
60
+ it "should not change the nested routes" do
61
+ drawing_routes do |map|
62
+ map.resources :articles, :paged => true do |article|
63
+ article.resources :comments
64
+ end
65
+ end.should change { number_of_routes }.by(7+1+7)
66
+ drawing_routes do |map|
67
+ map.resources :articles, :paged => true, :has_many => :comments
68
+ end.should change { number_of_routes }.by(7+1+7)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,160 @@
1
+ require 'spec'
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ require 'rubygems'
6
+ require 'active_support'
7
+ require 'active_record'
8
+ require 'action_controller'
9
+ require 'action_controller/test_process'
10
+ require 'action_view/test_case'
11
+ require 'paged_scopes'
12
+
13
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :dbfile => ':memory:')
14
+ ActiveRecord::Schema.define do
15
+ create_table "users", :force => true do |t|
16
+ t.column "name", :text
17
+ end
18
+ create_table "articles", :force => true do |t|
19
+ t.column "user_id", :integer
20
+ t.column "title", :text
21
+ t.column "published_at", :datetime
22
+ end
23
+ create_table "comments", :force => true do |t|
24
+ t.column "article_id", :integer
25
+ t.column "user_id", :integer
26
+ end
27
+ create_table "contributions", :force => true do |t|
28
+ t.column "article_id", :integer
29
+ t.column "user_id", :integer
30
+ end
31
+ end
32
+
33
+ class ::User < ActiveRecord::Base
34
+ has_many :articles
35
+ has_many :recent_articles, :order => "published_at DESC", :conditions => [ "published_at IS NOT :nil", { :nil => nil } ], :class_name => "Article"
36
+ has_many :contributions
37
+ has_many :shared_articles, :through => :contributions, :source => :article
38
+ end
39
+ class ::Article < ActiveRecord::Base
40
+ belongs_to :user
41
+ has_many :comments
42
+ named_scope :untitled, :conditions => { :title => nil }
43
+ named_scope :including_user, :include => :user
44
+ named_scope :with_user, :joins => 'INNER JOIN users ON users.id = articles.user_id'
45
+ named_scope :with_named_user, :joins => 'INNER JOIN users ON users.id = articles.user_id', :conditions => [ 'users.name IS NOT :nil', { :nil => nil } ]
46
+ named_scope :ordered_by_user_name, :joins => 'INNER JOIN users ON users.id = articles.user_id', :conditions => [ 'users.name IS NOT :nil', { :nil => nil } ], :order => 'users.name'
47
+ named_scope :with_comments, :joins => 'INNER JOIN comments AS article_comments ON article_comments.article_id = articles.id', :group => 'articles.id'
48
+ named_scope :first_three_with_comments, :joins => 'INNER JOIN comments AS article_comments ON article_comments.article_id = articles.id', :group => 'articles.id', :limit => 3
49
+ named_scope :with_multiple_comments, :include => :comments, :joins => 'INNER JOIN (SELECT count(id) AS count, article_id FROM comments GROUP BY article_id) article_comments ON article_comments.article_id = articles.id', :conditions => 'article_comments.count > 1'
50
+ named_scope :first_three, :limit => 3
51
+ named_scope :two_through_four, :limit => 3, :offset => 1
52
+ named_scope :descending_id, :order => 'articles.id DESC'
53
+ end
54
+ class ::Comment < ActiveRecord::Base
55
+ belongs_to :article
56
+ end
57
+ class ::Contribution < ActiveRecord::Base
58
+ belongs_to :article
59
+ belongs_to :user
60
+ end
61
+
62
+ User.create(:name => "user #1")
63
+ User.create(:name => nil)
64
+ User.create(:name => "user #3")
65
+ 9.times do |n|
66
+ shared_article = User.first.articles.create
67
+ User.all.each_with_index do |user, i|
68
+ user.articles.create
69
+ user.articles.create(:title => "Article #%03d" % Article.count)
70
+ published_article = user.articles.create(:title => "Article #%03d" % Article.count, :published_at => n.weeks.ago)
71
+ n.times { published_article.comments << Comment.new }
72
+ user.articles.create(:published_at => n.weeks.ago)
73
+ user.shared_articles << shared_article unless user == User.first
74
+ end
75
+ n.times { shared_article.comments << Comment.new }
76
+ end
77
+
78
+ module ControllerHelpers
79
+ def in_instance(instance, &block)
80
+ instance.instance_eval do
81
+ extend Spec::Matchers
82
+ instance_eval(&block)
83
+ end
84
+ end
85
+
86
+ def in_controller(controller, &block)
87
+ controller.copy_instance_variables_from(self)
88
+ in_instance controller do
89
+ stub!(:params).and_return({})
90
+ instance_eval(&block)
91
+ end
92
+ end
93
+ end
94
+
95
+ module RoutingHelpers
96
+ def draw_routes(&block)
97
+ ActionController::Routing::Routes.draw(&block)
98
+ end
99
+
100
+ def drawing_routes(&block)
101
+ lambda { draw_routes(&block) }
102
+ end
103
+
104
+ def number_of_routes
105
+ ActionController::Routing::Routes.routes.size
106
+ end
107
+
108
+ def named_routes
109
+ ActionController::Routing::Routes.named_routes
110
+ end
111
+
112
+ def recognise_path(method, path)
113
+ request = ActionController::TestRequest.new
114
+ request.request_method = method
115
+ ActionController::Routing::Routes.recognize_path(path, ActionController::Routing::Routes.extract_request_environment(request))
116
+ rescue ActionController::RoutingError, ActionController::MethodNotAllowed
117
+ nil
118
+ end
119
+ end
120
+
121
+ module Contexts
122
+ def in_contexts(&block)
123
+ [
124
+ [ "a scoped ActiveRecord class", "Article.scoped({})" ],
125
+ [ "a has_many association", "User.last.articles" ],
126
+ [ "an ordered has_many association", "User.last.recent_articles" ],
127
+ [ "a has_many, :through association", "User.last.shared_articles" ] # not tested for habtm!
128
+ ].each do |base_type, base|
129
+ [
130
+ [ "", "" ],
131
+ [ "scoped with :conditions", ".untitled" ],
132
+ [ "scoped with :include", ".including_user" ],
133
+ [ "scoped with :joins", ".with_user" ],
134
+ [ "scoped with :joins & :conditions", ".with_named_user" ],
135
+ [ "scoped with :joins, :conditions & :order", ".ordered_by_user_name" ],
136
+ [ "scoped with :joins & :group", ".with_comments" ],
137
+ [ "scoped with :joins, :group & :limit", ".first_three_with_comments" ],
138
+ [ "scoped with :includes, :joins & subquery", ".with_multiple_comments" ],
139
+ [ "scoped with :limit", ".first_three" ],
140
+ [ "scoped with :limit & :offset", ".two_through_four" ],
141
+ [ "scoped with :order", ".descending_id" ]
142
+ ].each do |scope_type, scope|
143
+ context "for #{base_type} #{scope_type}" do
144
+ before(:each) do
145
+ @articles = eval("#{base}#{scope}")
146
+ @articles.all.should_not be_empty # sanity check: make sure our collection actually has some elements!
147
+ @articles.all.should == @articles.all.uniq # don't want duplicate items in our test collection
148
+ end
149
+ instance_eval(&block)
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ Spec::Runner.configure do |config|
157
+ config.extend Contexts
158
+ config.include RoutingHelpers
159
+ config.include ControllerHelpers
160
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: paged_scopes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Matthew Hollingworth
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-10 00:00:00 +11:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activerecord
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.2.1
24
+ version:
25
+ description:
26
+ email: mdholling@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.textile
34
+ files:
35
+ - .document
36
+ - .gitignore
37
+ - LICENSE
38
+ - README.textile
39
+ - Rakefile
40
+ - VERSION.yml
41
+ - lib/paged_scopes.rb
42
+ - lib/paged_scopes/collection.rb
43
+ - lib/paged_scopes/context.rb
44
+ - lib/paged_scopes/controller.rb
45
+ - lib/paged_scopes/index.rb
46
+ - lib/paged_scopes/pages.rb
47
+ - lib/paged_scopes/paginator.rb
48
+ - lib/paged_scopes/resources.rb
49
+ - paged_scopes.gemspec
50
+ - rails/init.rb
51
+ - spec/collection_spec.rb
52
+ - spec/context_spec.rb
53
+ - spec/controller_spec.rb
54
+ - spec/index_spec.rb
55
+ - spec/page_spec.rb
56
+ - spec/paginator_spec.rb
57
+ - spec/resources_spec.rb
58
+ - spec/spec_helper.rb
59
+ has_rdoc: true
60
+ homepage: http://github.com/mholling/paged_scopes
61
+ licenses: []
62
+
63
+ post_install_message:
64
+ rdoc_options:
65
+ - --charset=UTF-8
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.3.5
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: PagedScopes is an ActiveRecord pagination gem. It lets you easily paginate collection associations and named scopes. It also paginates collections which already have :limit and :offset scopes in place. You can also find the page containing a given object in a collection, and find the next and previous objects for each object in the collection.
87
+ test_files:
88
+ - spec/collection_spec.rb
89
+ - spec/context_spec.rb
90
+ - spec/controller_spec.rb
91
+ - spec/index_spec.rb
92
+ - spec/page_spec.rb
93
+ - spec/paginator_spec.rb
94
+ - spec/resources_spec.rb
95
+ - spec/spec_helper.rb