ramaze 2012.03.07 → 2012.04.14
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/.gems +12 -11
- data/.mailmap +1 -0
- data/README.md +3 -3
- data/examples/app/wiktacular/mkd/markdown/current.mkd +2 -2
- data/examples/app/wiktacular/mkd/testing/2007-07-21_18-46-01.mkd +11 -11
- data/examples/app/wiktacular/mkd/testing/2007-07-21_18-46-32.mkd +12 -12
- data/guide/general/special_thanks.md +1 -0
- data/guide/general/testing.md +188 -22
- data/lib/ramaze/cache/memcache.rb +2 -2
- data/lib/ramaze/cache/redis.rb +13 -9
- data/lib/ramaze/helper/paginate.rb +60 -15
- data/lib/ramaze/version.rb +1 -1
- data/ramaze.gemspec +1 -1
- data/spec/ramaze/cache/redis.rb +1 -5
- data/spec/ramaze/helper/paginate.rb +205 -0
- data/spec/ramaze/session/localmemcache.rb +58 -0
- data/spec/ramaze/session/lru.rb +58 -0
- data/spec/ramaze/session/memcache.rb +1 -1
- data/spec/ramaze/session/redis.rb +63 -0
- data/spec/ramaze/session/sequel.rb +60 -0
- metadata +205 -61
data/.gems
CHANGED
|
@@ -1,34 +1,35 @@
|
|
|
1
1
|
# .gems generated gem export file. Note that any env variable settings will be missing. Append these after using a ';' field separator
|
|
2
2
|
bacon -v1.1.0
|
|
3
|
-
dalli -
|
|
3
|
+
dalli -v2.0.2
|
|
4
4
|
erector -v0.8.3
|
|
5
5
|
erubis -v2.7.0
|
|
6
6
|
ezamar -v2009.06
|
|
7
7
|
haml -v3.1.4
|
|
8
|
-
hpricot -v0.8.
|
|
9
|
-
innate -
|
|
8
|
+
hpricot -v0.8.6
|
|
9
|
+
innate -v2012.03
|
|
10
10
|
liquid -v2.3.0
|
|
11
11
|
locale -v2.0.5
|
|
12
|
-
localmemcache -v0.4.4
|
|
13
12
|
lokar -v0.2.1
|
|
14
13
|
maruku -v0.6.0
|
|
15
14
|
mustache -v0.99.4
|
|
16
15
|
nagoro -v2009.05
|
|
17
|
-
nokogiri -v1.5.0
|
|
18
16
|
polyglot -v0.3.3
|
|
19
|
-
rack -v1.4.
|
|
17
|
+
rack -v1.4.1
|
|
20
18
|
rack-contrib -v1.1.0
|
|
21
19
|
rack-test -v0.6.1
|
|
22
|
-
|
|
20
|
+
rake -v0.9.2.2
|
|
23
21
|
rdiscount -v1.6.8
|
|
24
22
|
redis -v2.2.2
|
|
25
23
|
Remarkably -v0.6.1
|
|
26
|
-
sass -v3.1.
|
|
27
|
-
sequel -v3.
|
|
24
|
+
sass -v3.1.15
|
|
25
|
+
sequel -v3.34.1
|
|
26
|
+
slim -v1.2.0
|
|
28
27
|
slippers -v0.0.14
|
|
29
28
|
sqlite3 -v1.3.5
|
|
30
29
|
syntax -v1.0.0
|
|
31
|
-
tagz -v9.
|
|
30
|
+
tagz -v9.3.0
|
|
31
|
+
temple -v0.4.0
|
|
32
32
|
tenjin -v0.7.1
|
|
33
|
+
tilt -v1.3.3
|
|
33
34
|
treetop -v1.4.10
|
|
34
|
-
yard -v0.7.
|
|
35
|
+
yard -v0.7.5
|
data/.mailmap
CHANGED
|
@@ -31,3 +31,4 @@ Michael Fellinger <m.fellinger@gmail.com> Michael Fellinger m.fellinger@gmail.co
|
|
|
31
31
|
Yorick Peterse <yorickpeterse@gmail.com> YorickPeterse <yorickpeterse@gmail.com>
|
|
32
32
|
Yorick Peterse <yorickpeterse@gmail.com> YorickPeterse <info@yorickpeterse.com>
|
|
33
33
|
Yorick Peterse <yorickpeterse@gmail.com> Yorick Peterse <info@yorickpeterse.com>
|
|
34
|
+
Yorick Peterse <yorickpeterse@gmail.com> Yorick Peterse <yorick@isset.nl>
|
data/README.md
CHANGED
|
@@ -10,7 +10,7 @@ give you the ultimate tools, but you have to use them yourself to achieve
|
|
|
10
10
|
perfect custom-tailored results.
|
|
11
11
|
|
|
12
12
|
Another one of the goals during development of Ramaze was to make every part as
|
|
13
|
-
modular and
|
|
13
|
+
modular and therefore reusable as possible, not only to provide a basic
|
|
14
14
|
understanding after the first glance, but also to make it as simple as possible
|
|
15
15
|
to reuse parts of the code.
|
|
16
16
|
|
|
@@ -25,7 +25,7 @@ in their own way rather than being forced to work in a way that the framework
|
|
|
25
25
|
importantly: it puts you back in control of your code. An example of this is the
|
|
26
26
|
default file structure of new Ramaze projects. Out of the box a new project
|
|
27
27
|
uses the MVC pattern. The cool thing about Ramaze however is that you're not
|
|
28
|
-
forced to use this pattern. If you
|
|
28
|
+
forced to use this pattern. If you prefer HMVC, PAC or something else you can
|
|
29
29
|
simply apply it. Another example is the use of a database toolkit. Ramaze does
|
|
30
30
|
not ship with one for a very simple reason: nobody likes the same toolkit. Some
|
|
31
31
|
people prefer Sequel, others use Datamapper. With Ramaze you can use any tool
|
|
@@ -118,7 +118,7 @@ directory.
|
|
|
118
118
|
* {file:general/sessions Sessions}
|
|
119
119
|
* {file:general/cache Caching Data}
|
|
120
120
|
* {file:general/logging Logging Information}
|
|
121
|
-
* {file:general/testing Testing
|
|
121
|
+
* {file:general/testing Testing Ramaze}
|
|
122
122
|
|
|
123
123
|
## Tutorials
|
|
124
124
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
# Markdown
|
|
2
|
-
|
|
1
|
+
# Markdown
|
|
2
|
+
|
|
3
3
|
Markdown is a engine for converting plain text to [[HTML]]. You can find more information at [markdown homepage](http://daringfireball.net/projects/markdown/)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# Just a test
|
|
2
|
-
|
|
3
|
-
Some more text
|
|
4
|
-
|
|
5
|
-
## nothing serious
|
|
6
|
-
|
|
7
|
-
And some text
|
|
8
|
-
|
|
9
|
-
### Even less serious
|
|
10
|
-
|
|
11
|
-
Here is a [[link]]
|
|
1
|
+
# Just a test
|
|
2
|
+
|
|
3
|
+
Some more text
|
|
4
|
+
|
|
5
|
+
## nothing serious
|
|
6
|
+
|
|
7
|
+
And some text
|
|
8
|
+
|
|
9
|
+
### Even less serious
|
|
10
|
+
|
|
11
|
+
Here is a [[link]]
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
# Just a test
|
|
2
|
-
|
|
3
|
-
Some more text
|
|
4
|
-
|
|
5
|
-
## nothing serious
|
|
6
|
-
|
|
7
|
-
And some text
|
|
8
|
-
|
|
9
|
-
### Even less serious
|
|
10
|
-
|
|
11
|
-
Here is a [[link]]
|
|
12
|
-
|
|
1
|
+
# Just a test
|
|
2
|
+
|
|
3
|
+
Some more text
|
|
4
|
+
|
|
5
|
+
## nothing serious
|
|
6
|
+
|
|
7
|
+
And some text
|
|
8
|
+
|
|
9
|
+
### Even less serious
|
|
10
|
+
|
|
11
|
+
Here is a [[link]]
|
|
12
|
+
|
|
13
13
|
<a href="foo">foo</a>
|
data/guide/general/testing.md
CHANGED
|
@@ -1,25 +1,193 @@
|
|
|
1
|
-
# Testing
|
|
1
|
+
# Testing Ramaze
|
|
2
|
+
|
|
3
|
+
Ramaze uses and encourages BDD (Behaviour Driven Development). Ramaze itself is
|
|
4
|
+
tested using [Bacon][bacon] and supports it out of the box, it however isn't
|
|
5
|
+
limited to just Bacon.
|
|
6
|
+
|
|
7
|
+
One might wonder why to bother with writing tests. The answer to this is quite
|
|
8
|
+
simple: stability. Manually testing an application works on a very basic level
|
|
9
|
+
but there are various issues that will arise once your application grows. The
|
|
10
|
+
two biggest issues are human errors and repeatability. Especially the latter
|
|
11
|
+
becomes an issue when your development team grows in size, while the initial
|
|
12
|
+
developer may be willing to manually test every feature every time a change has
|
|
13
|
+
been made others might not. Even worse, there's a chance they won't test their
|
|
14
|
+
code at all and assume it's production ready because on their setup.
|
|
15
|
+
|
|
16
|
+
Writing tests that can be executed using a single command (or automatically)
|
|
17
|
+
makes your life a lot easier as you no longer have to worry about any of these
|
|
18
|
+
issues (assuming people actually write tests). Whenever somebody commits code
|
|
19
|
+
they write a test and you can easily verify if it works on different setups by
|
|
20
|
+
simply running said test.
|
|
21
|
+
|
|
22
|
+
When writing Ruby code you can pick from a large collection of testing libraries
|
|
23
|
+
such as Bacon and [Rspec][rspec] for general tests, [SimpleCov][simplecov] for
|
|
24
|
+
code coverage and [Capybara][capybara] for testing form based actions and the
|
|
25
|
+
like. Of course the list doesn't stop here, there's simply too much to discuss
|
|
26
|
+
everything.
|
|
27
|
+
|
|
28
|
+
## Bacon
|
|
29
|
+
|
|
30
|
+
Bacon is a small and lightweight Rspec clone that's used by Ramaze and Innate
|
|
31
|
+
and is the recommended tool to use. Each bacon test consists out of at least two
|
|
32
|
+
bits: a "describe" block and an "it" (or "should") block. The describe block can
|
|
33
|
+
be seen as a group of multiple it/should blocks. In most cases these blocks are
|
|
34
|
+
used to specify the name of a class, module, etc. The it/should blocks are used
|
|
35
|
+
for individual tests.
|
|
36
|
+
|
|
37
|
+
Lets take a look at a simple block of code:
|
|
38
|
+
|
|
39
|
+
class Person
|
|
40
|
+
attr_accessor :name
|
|
41
|
+
|
|
42
|
+
def initialize(name = nil)
|
|
43
|
+
@name = name
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
Using Bacon we can test this code as following:
|
|
48
|
+
|
|
49
|
+
require 'bacon'
|
|
50
|
+
|
|
51
|
+
describe 'Person' do
|
|
52
|
+
should 'respond to #name' do
|
|
53
|
+
person = Person.new
|
|
54
|
+
|
|
55
|
+
person.respond_to?(:name).should == true
|
|
56
|
+
person.respond_to?(:name=).should == true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
should 'set the name in the constructor' do
|
|
60
|
+
person = Person.new('Matz')
|
|
61
|
+
|
|
62
|
+
person.name.should == 'Matz'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
should 'set the name using #name=' do
|
|
66
|
+
person = Person.new
|
|
67
|
+
|
|
68
|
+
person.name = 'Matz'
|
|
69
|
+
|
|
70
|
+
person.name.should == 'Matz'
|
|
71
|
+
end
|
|
72
|
+
end
|
|
2
73
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
74
|
+
For more information on the syntax of Bacon and other information see the
|
|
75
|
+
[Bacon Github project][bacon].
|
|
76
|
+
|
|
77
|
+
### Bacon With Ramaze
|
|
78
|
+
|
|
79
|
+
Ramaze makes it easy to test your code using Bacon by providing you with a small
|
|
80
|
+
helper file. This file can be loaded as following:
|
|
81
|
+
|
|
82
|
+
require 'ramaze/spec/bacon'
|
|
83
|
+
|
|
84
|
+
This file adds two bacon contexts (rack_test and webrat), configures Ramaze to
|
|
85
|
+
only show error messages and adds a few helper methods.
|
|
86
|
+
|
|
87
|
+
### Bacon and Rack::Test
|
|
88
|
+
|
|
89
|
+
In order to test Ramaze specific code you'll need to use a tool that's capable
|
|
90
|
+
of mocking Rack requests or execute this request in a different way (e.g. using
|
|
91
|
+
Selenium). Rack::Test (gem install rack-test) makes it possible to test your
|
|
92
|
+
Rack based (and thus Ramaze) applications without having to use a webbrowser.
|
|
93
|
+
|
|
94
|
+
Ramaze makes it easy to use Rack::Test by defining a special bacon context:
|
|
95
|
+
"rack_test". This context can be used by calling `behaves_like :rack_test`
|
|
96
|
+
inside your describe block:
|
|
97
|
+
|
|
98
|
+
describe 'Using Rack::Test' do
|
|
99
|
+
behaves_like :rack_test
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
Once loaded you can execute HTTP requests using methods such as `get`:
|
|
103
|
+
|
|
104
|
+
describe 'Using Rack::Test' do
|
|
105
|
+
behaves_like :rack_test
|
|
106
|
+
|
|
107
|
+
should 'display the homepage' do
|
|
108
|
+
get('/').body.should == 'Hello, Rack::Test!'
|
|
109
|
+
end
|
|
110
|
+
end
|
|
6
111
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
application using ``ramaze create`` Ramaze will automatically generate a
|
|
10
|
-
directory for your specifications.
|
|
112
|
+
More information about Rack::Test can be found on the [Github page of
|
|
113
|
+
Rack::Test][rack-test].
|
|
11
114
|
|
|
12
|
-
|
|
13
|
-
of simplicity this guide assumes you'll be using Bacon. In order to use Bacon
|
|
14
|
-
you must first install it from Rubygems. This can be done using the following
|
|
15
|
-
command:
|
|
115
|
+
## Capybara
|
|
16
116
|
|
|
17
|
-
|
|
117
|
+
Capybara is a Gem that can be used to simulate browser requests using
|
|
118
|
+
Rack::Test, Selenium or other drivers, it's even capable of testing Javascript
|
|
119
|
+
based code using Selenium.
|
|
18
120
|
|
|
19
|
-
In order to
|
|
20
|
-
command:
|
|
121
|
+
In order to use Capybara you must first install it:
|
|
21
122
|
|
|
22
|
-
|
|
123
|
+
$ gem install capybara
|
|
124
|
+
|
|
125
|
+
Once installed you'll have to configure Capybara so it knows how to use your
|
|
126
|
+
Ramaze application. Depending on the testing Gem you're using you'll also have
|
|
127
|
+
to configure said Gem, for this guide it's assumed that you're using Bacon.
|
|
128
|
+
|
|
129
|
+
First you should load and configure Capybara:
|
|
130
|
+
|
|
131
|
+
require 'capybara'
|
|
132
|
+
require 'capybara/dsl'
|
|
133
|
+
require 'bacon'
|
|
134
|
+
|
|
135
|
+
# Tells Capybara which driver to use and where to find your application.
|
|
136
|
+
# Without this Capybara will not work properly.
|
|
137
|
+
Capybara.configure do |config|
|
|
138
|
+
config.default_driver = :rack_test
|
|
139
|
+
config.app = Ramaze.middleware
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
Next you'll have to set up a context for Bacon:
|
|
143
|
+
|
|
144
|
+
shared :capybara do
|
|
145
|
+
Ramaze.setup_dependencies
|
|
146
|
+
extend Capybara::DSL
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
Last but not least, make sure Ramaze knows about your root directories and set
|
|
150
|
+
your mode:
|
|
151
|
+
|
|
152
|
+
Ramaze.options.roots << 'path/to/spec/directory'
|
|
153
|
+
Ramaze.options.mode = :spec
|
|
154
|
+
|
|
155
|
+
Once all of this has been done you can start using Capybara. A simple example of
|
|
156
|
+
this is the following:
|
|
157
|
+
|
|
158
|
+
class MainController < Ramaze::Controller
|
|
159
|
+
map '/'
|
|
160
|
+
|
|
161
|
+
def index
|
|
162
|
+
return 'Hello, Ramaze!'
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def redirect_request
|
|
166
|
+
redirect(MainController.r(:index))
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
describe 'Testing Ramaze' do
|
|
171
|
+
behaves_like :capybara
|
|
172
|
+
|
|
173
|
+
it 'Go to the homepage' do
|
|
174
|
+
visit '/'
|
|
175
|
+
|
|
176
|
+
page.has_content?('Hello, Ramaze!').should == true
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it 'Follow redirects' do
|
|
180
|
+
visit '/redirect_request'
|
|
181
|
+
|
|
182
|
+
page.current_path.should == '/index'
|
|
183
|
+
page.has_content?('Hello, Ramaze!').should == true
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
For more information on how to use Capybara with other testing tools, how to use
|
|
188
|
+
the syntax and so on you should resort to the [Capybara Github page][capybara].
|
|
189
|
+
|
|
190
|
+
## Code Coverage using SimpleCov
|
|
23
191
|
|
|
24
192
|
To test the Ramaze application tests coverage, you can use a tool like
|
|
25
193
|
[SimpleCov][simplecov]. SimpleCov requires minimal effort to get integrated,
|
|
@@ -48,14 +216,12 @@ In order to run the file you'd simply invoke the following:
|
|
|
48
216
|
|
|
49
217
|
Upon success SimpleCov will create a new directory ``coverage`` with the
|
|
50
218
|
results. You can point your browser to the index.html file inside that directory
|
|
51
|
-
|
|
52
|
-
and browse to the same folder. This can be done as following:
|
|
53
|
-
|
|
54
|
-
python -m SimpleHTTPServer 11111
|
|
219
|
+
to view the results.
|
|
55
220
|
|
|
56
|
-
For more information on using Simplecov see the [Github project][simplecov
|
|
221
|
+
For more information on using Simplecov see the [Github project][simplecov].
|
|
57
222
|
|
|
58
223
|
[bacon]: https://github.com/chneukirchen/bacon
|
|
59
224
|
[simplecov]: https://github.com/colszowka/simplecov
|
|
60
225
|
[rspec]: http://relishapp.com/rspec
|
|
61
|
-
[
|
|
226
|
+
[capybara]: http://jnicklas.github.com/capybara/
|
|
227
|
+
[rack-test]: https://github.com/brynary/rack-test
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Ramaze.setup(:verbose => false) do
|
|
2
|
-
gem 'dalli'
|
|
2
|
+
gem 'dalli', ['>= 2.0.2']
|
|
3
3
|
end
|
|
4
4
|
|
|
5
5
|
# Kgio gives a nice performance boost but it isn't required
|
|
@@ -62,7 +62,7 @@ module Ramaze
|
|
|
62
62
|
:expires_in => 604800,
|
|
63
63
|
|
|
64
64
|
# Compresses everything with Gzip if it's over 1K
|
|
65
|
-
:
|
|
65
|
+
:compress => true,
|
|
66
66
|
|
|
67
67
|
# Array containing all default Memcache servers
|
|
68
68
|
:servers => ['localhost:11211']
|
data/lib/ramaze/cache/redis.rb
CHANGED
|
@@ -81,9 +81,8 @@ module Ramaze
|
|
|
81
81
|
# information.
|
|
82
82
|
#
|
|
83
83
|
def initialize(options = {})
|
|
84
|
-
self.class.options ||=
|
|
85
|
-
options
|
|
86
|
-
)
|
|
84
|
+
self.class.options ||=
|
|
85
|
+
Ramaze::Cache::Redis.trait[:default].merge(options)
|
|
87
86
|
|
|
88
87
|
@options = options.merge(self.class.options)
|
|
89
88
|
end
|
|
@@ -103,8 +102,8 @@ module Ramaze
|
|
|
103
102
|
#
|
|
104
103
|
def cache_setup(hostname, username, appname, cachename)
|
|
105
104
|
options[:namespace] = [
|
|
106
|
-
hostname, username, appname, cachename
|
|
107
|
-
].compact.join('
|
|
105
|
+
'ramaze', hostname, username, appname, cachename
|
|
106
|
+
].compact.join(':')
|
|
108
107
|
|
|
109
108
|
@client = ::Redis.new(options)
|
|
110
109
|
end
|
|
@@ -126,7 +125,7 @@ module Ramaze
|
|
|
126
125
|
# @param [Array] *keys An array of key names to remove.
|
|
127
126
|
#
|
|
128
127
|
def cache_delete(*keys)
|
|
129
|
-
@client.del(*keys)
|
|
128
|
+
@client.del(*keys.map{|key| namespaced_key(key) })
|
|
130
129
|
end
|
|
131
130
|
|
|
132
131
|
##
|
|
@@ -139,8 +138,8 @@ module Ramaze
|
|
|
139
138
|
# @return [Mixed]
|
|
140
139
|
#
|
|
141
140
|
def cache_fetch(key, default = nil)
|
|
142
|
-
value = @client.get(key)
|
|
143
|
-
value.nil? ? default : value
|
|
141
|
+
value = @client.get(namespaced_key(key))
|
|
142
|
+
value.nil? ? default : ::Marshal.load(value)
|
|
144
143
|
end
|
|
145
144
|
|
|
146
145
|
##
|
|
@@ -155,10 +154,15 @@ module Ramaze
|
|
|
155
154
|
#
|
|
156
155
|
def cache_store(key, value, ttl = nil, options = {})
|
|
157
156
|
ttl = options[:ttl] || @options[:expires_in]
|
|
158
|
-
|
|
157
|
+
|
|
158
|
+
@client.setex(namespaced_key(key), ttl, ::Marshal.dump(value))
|
|
159
159
|
|
|
160
160
|
return value
|
|
161
161
|
end
|
|
162
|
+
|
|
163
|
+
def namespaced_key(key)
|
|
164
|
+
[options[:namespace], key].join(':')
|
|
165
|
+
end
|
|
162
166
|
end # Redis
|
|
163
167
|
end # Cache
|
|
164
168
|
end # Ramaze
|
|
@@ -14,6 +14,15 @@ module Ramaze
|
|
|
14
14
|
trait :paginate => {
|
|
15
15
|
:limit => 10,
|
|
16
16
|
:var => 'pager',
|
|
17
|
+
:css => {
|
|
18
|
+
:first => 'first',
|
|
19
|
+
:prev => 'prev',
|
|
20
|
+
:next => 'next',
|
|
21
|
+
:last => 'last',
|
|
22
|
+
:current => 'current',
|
|
23
|
+
:number => '',
|
|
24
|
+
:disabled => 'grey'
|
|
25
|
+
}
|
|
17
26
|
}
|
|
18
27
|
|
|
19
28
|
##
|
|
@@ -41,9 +50,37 @@ module Ramaze
|
|
|
41
50
|
#
|
|
42
51
|
# Note that you must first extend Sequel with the pagination extension"
|
|
43
52
|
#
|
|
44
|
-
#
|
|
45
53
|
# Sequel.extension :pagination
|
|
46
54
|
#
|
|
55
|
+
# Customizing the classes to use for the various HTML elements of the
|
|
56
|
+
# page list can be done by passing a key ``:css`` to the list of options.
|
|
57
|
+
# In this hash you can set the following keys:
|
|
58
|
+
#
|
|
59
|
+
# * first, defaults to "first"
|
|
60
|
+
# * prev, defaults to "prev"
|
|
61
|
+
# * next, defaults to "next"
|
|
62
|
+
# * last, defaults to "last"
|
|
63
|
+
# * current, defaults to "current"
|
|
64
|
+
# * number, empty by default
|
|
65
|
+
# * disabled, defaults to "grey"
|
|
66
|
+
#
|
|
67
|
+
# These options can also be specified globally in the trait ``:paginate``
|
|
68
|
+
# as following:
|
|
69
|
+
#
|
|
70
|
+
# class Posts < Ramaze::Controller
|
|
71
|
+
# map '/'
|
|
72
|
+
#
|
|
73
|
+
# trait :paginate => {
|
|
74
|
+
# :limit => 10,
|
|
75
|
+
# :var => 'page',
|
|
76
|
+
# :css => {
|
|
77
|
+
# :first => 'first_item',
|
|
78
|
+
# :prev => 'prev_item',
|
|
79
|
+
# # and so on.
|
|
80
|
+
# }
|
|
81
|
+
# }
|
|
82
|
+
# end
|
|
83
|
+
#
|
|
47
84
|
# @param [Sequel::Dataset|Array] dataset May be a Sequel dataset or an
|
|
48
85
|
# Array
|
|
49
86
|
# @param [Hash] options A hash containing custom options that takes
|
|
@@ -56,23 +93,30 @@ module Ramaze
|
|
|
56
93
|
# @option options [Fixnum] :page The page you are currently on, if not
|
|
57
94
|
# given it will be retrieved from current request variables. Defaults to
|
|
58
95
|
# 1 if neither exists.
|
|
96
|
+
# @option options [Hash] :css A hash containing various options that can
|
|
97
|
+
# be used to customize the HTML classes to use for the various page
|
|
98
|
+
# links.
|
|
59
99
|
#
|
|
60
100
|
def paginate(dataset, options = {})
|
|
61
101
|
options = ancestral_trait[:paginate].merge(options)
|
|
62
102
|
limit = options[:limit]
|
|
63
103
|
var = options[:var]
|
|
64
104
|
page = options[:page] || (request[var] || 1).to_i
|
|
65
|
-
|
|
66
|
-
|
|
105
|
+
opts = {}
|
|
106
|
+
opts.merge!({:css => options[:css]}) if options[:css]
|
|
107
|
+
Paginator.new(dataset, page, limit, var, opts)
|
|
67
108
|
end
|
|
68
109
|
|
|
69
110
|
# Provides easy pagination and navigation
|
|
70
111
|
class Paginator
|
|
71
112
|
include Ramaze::Helper
|
|
72
113
|
helper :link, :cgi
|
|
114
|
+
attr_reader :css
|
|
73
115
|
|
|
74
|
-
def initialize(data = [], page = 1, limit = 10, var = 'pager')
|
|
116
|
+
def initialize(data = [], page = 1, limit = 10, var = 'pager', opts = {})
|
|
75
117
|
@data, @page, @limit, @var = data, page, limit, var
|
|
118
|
+
@css = Paginate.trait[:paginate][:css].dup
|
|
119
|
+
@css.merge!(opts[:css]) if opts[:css]
|
|
76
120
|
@pager = pager_for(data)
|
|
77
121
|
@page = @page > page_count ? page_count : @page
|
|
78
122
|
@pager = pager_for(data)
|
|
@@ -110,34 +154,35 @@ module Ramaze
|
|
|
110
154
|
g = Ramaze::Gestalt.new
|
|
111
155
|
g.div :class => :pager do
|
|
112
156
|
if first_page?
|
|
113
|
-
g.span(:class =>
|
|
114
|
-
g.span(:class =>
|
|
157
|
+
g.span(:class => "#{@css[:first]} #{@css[:disabled]}"){ h('<<') }
|
|
158
|
+
g.span(:class => "#{@css[:prev]} #{@css[:disabled]}"){ h('<') }
|
|
115
159
|
else
|
|
116
|
-
link(g, 1, '<<', :class => :first)
|
|
117
|
-
link(g, prev_page, '<', :class => :
|
|
160
|
+
link(g, 1, '<<', :class => @css[:first])
|
|
161
|
+
link(g, prev_page, '<', :class => @css[:prev])
|
|
118
162
|
end
|
|
119
163
|
|
|
120
164
|
lower = limit ? (current_page - limit) : 1
|
|
121
165
|
lower = lower < 1 ? 1 : lower
|
|
122
166
|
|
|
123
167
|
(lower...current_page).each do |n|
|
|
124
|
-
link(g, n)
|
|
168
|
+
link(g, n, n, :class => @css[:number])
|
|
125
169
|
end
|
|
126
170
|
|
|
127
|
-
link(g, current_page, current_page,
|
|
171
|
+
link(g, current_page, current_page,
|
|
172
|
+
:class => "#{@css[:current]} #{@css[:number]}" )
|
|
128
173
|
|
|
129
174
|
if last_page?
|
|
130
|
-
g.span(:class =>
|
|
131
|
-
g.span(:class =>
|
|
175
|
+
g.span(:class => "#{@css[:next]} #{@css[:disabled]}"){ h('>') }
|
|
176
|
+
g.span(:class => "#{@css[:last]} #{@css[:disabled]}"){ h('>>') }
|
|
132
177
|
elsif next_page
|
|
133
178
|
higher = limit ? (next_page + limit) : page_count
|
|
134
179
|
higher = [higher, page_count].min
|
|
135
180
|
(next_page..higher).each do |n|
|
|
136
|
-
link(g, n)
|
|
181
|
+
link(g, n, n, :class => @css[:number])
|
|
137
182
|
end
|
|
138
183
|
|
|
139
|
-
link(g, next_page, '>', :class => :next)
|
|
140
|
-
link(g, page_count, '>>', :class => :last)
|
|
184
|
+
link(g, next_page, '>', :class => @css[:next])
|
|
185
|
+
link(g, page_count, '>>', :class => @css[:last])
|
|
141
186
|
end
|
|
142
187
|
end
|
|
143
188
|
g.to_s
|