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.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.textile +471 -0
- data/Rakefile +55 -0
- data/VERSION.yml +4 -0
- data/lib/paged_scopes.rb +9 -0
- data/lib/paged_scopes/collection.rb +45 -0
- data/lib/paged_scopes/context.rb +36 -0
- data/lib/paged_scopes/controller.rb +54 -0
- data/lib/paged_scopes/index.rb +62 -0
- data/lib/paged_scopes/pages.rb +194 -0
- data/lib/paged_scopes/paginator.rb +68 -0
- data/lib/paged_scopes/resources.rb +32 -0
- data/paged_scopes.gemspec +72 -0
- data/rails/init.rb +1 -0
- data/spec/collection_spec.rb +66 -0
- data/spec/context_spec.rb +27 -0
- data/spec/controller_spec.rb +234 -0
- data/spec/index_spec.rb +31 -0
- data/spec/page_spec.rb +249 -0
- data/spec/paginator_spec.rb +256 -0
- data/spec/resources_spec.rb +72 -0
- data/spec/spec_helper.rb +160 -0
- metadata +95 -0
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|