sinatra-helpers 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/README.markdown +58 -0
- data/Rakefile +6 -0
- data/VERSION +1 -1
- data/lib/sinatra/helpers.rb +210 -13
- data/lib/sinatra/helpers/compat-1.8.6.rb +5 -2
- data/lib/sinatra/helpers/country.rb +78 -64
- data/lib/sinatra/helpers/haml_error_presenter.rb +1 -2
- data/sinatra-helpers.gemspec +28 -6
- data/test/helper.rb +6 -1
- data/test/test_country.rb +29 -0
- data/test/test_sinatra_helpers.rb +298 -0
- metadata +85 -8
- data/README.rdoc +0 -38
data/.gitignore
CHANGED
data/README.markdown
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
Sinatra Helpers: a common collection of useful utilities
|
2
|
+
--------------------------------------------------------
|
3
|
+
|
4
|
+
Bare minimum, close to the metal helpers for your average sinatra application.
|
5
|
+
Read the full documentation at [http://labs.sinefunc.com/sinatra-helpers/doc](http://labs.sinefunc.com/sinatra-helpers/doc).
|
6
|
+
|
7
|
+
Defines...
|
8
|
+
----------
|
9
|
+
|
10
|
+
# from a Sinatra context point of view...
|
11
|
+
set :default_year_loffset, -60
|
12
|
+
set :default_year_uoffset, 0
|
13
|
+
set :default_month_names, Date::MONTHNAMES
|
14
|
+
|
15
|
+
set :default_currency_unit, '$'
|
16
|
+
set :default_currency_precision, 2
|
17
|
+
set :default_currency_separator, ','
|
18
|
+
|
19
|
+
Examples
|
20
|
+
--------
|
21
|
+
|
22
|
+
# what are helpers for if you don't have `h` ^_^
|
23
|
+
=h "<Bar>"
|
24
|
+
|
25
|
+
%select(name='country')
|
26
|
+
!= country_choices
|
27
|
+
|
28
|
+
%select(name='birthday[month'])
|
29
|
+
!= month_choices
|
30
|
+
|
31
|
+
%select(name='birthday[day]')
|
32
|
+
!= day_choices
|
33
|
+
|
34
|
+
%select(name='birthday[year'])
|
35
|
+
!= year_choices
|
36
|
+
|
37
|
+
%select(name="categories")
|
38
|
+
!= select_options [['First', 1], ['Second', 2]]
|
39
|
+
|
40
|
+
= currency(100)
|
41
|
+
-# displays $ 100.00
|
42
|
+
|
43
|
+
= percentage(100)
|
44
|
+
-# displays 100.00%
|
45
|
+
|
46
|
+
# If you have an ohm model which you want to present the errors of:
|
47
|
+
# (this is taken from the reddit-clone courtesy of citrusbyte)
|
48
|
+
|
49
|
+
# This should be put in your HAML file
|
50
|
+
|
51
|
+
- errors_on @user do |e|
|
52
|
+
- e.on [:email, :not_present] "You must supply an email address"
|
53
|
+
- e.on [:password, :not_present] "A password is required"
|
54
|
+
- e.on [:password, :not_confirmed] "You must confirm your password"
|
55
|
+
|
56
|
+
### Copyright
|
57
|
+
|
58
|
+
Copyright (c) 2010 Cyril David. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -10,7 +10,13 @@ begin
|
|
10
10
|
gem.email = "cyx.ucron@gmail.com"
|
11
11
|
gem.homepage = "http://github.com/sinefunc/sinatra-helpers"
|
12
12
|
gem.authors = ["Cyril David"]
|
13
|
+
gem.add_dependency "sinatra", ">= 1.0"
|
13
14
|
gem.add_development_dependency "contest", ">= 0"
|
15
|
+
gem.add_development_dependency "mocha", ">= 0"
|
16
|
+
gem.add_development_dependency "rack-test", ">= 0"
|
17
|
+
gem.add_development_dependency "nokogiri", ">= 0"
|
18
|
+
gem.add_development_dependency "ohm", ">= 0"
|
19
|
+
gem.add_development_dependency "haml", ">= 0"
|
14
20
|
end
|
15
21
|
Jeweler::GemcutterTasks.new
|
16
22
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/sinatra/helpers.rb
CHANGED
@@ -1,32 +1,163 @@
|
|
1
1
|
require 'date'
|
2
|
+
require 'sinatra/base'
|
2
3
|
require 'sinatra/helpers/compat-1.8.6'
|
3
4
|
|
4
5
|
module Sinatra
|
5
6
|
module Helpers
|
7
|
+
VERSION = "0.2.0"
|
8
|
+
|
6
9
|
autoload :HamlErrorPresenter, "sinatra/helpers/haml_error_presenter"
|
7
10
|
autoload :Country, "sinatra/helpers/country"
|
11
|
+
|
12
|
+
# @private Sinatra extension writing style.
|
13
|
+
# @see http://www.sinatrarb.com/extensions.html#setting_options_and_other_extension_setup
|
14
|
+
def self.registered(app)
|
15
|
+
app.set :default_year_loffset, -60
|
16
|
+
app.set :default_year_uoffset, 0
|
17
|
+
app.set :default_month_names, Date::MONTHNAMES
|
18
|
+
|
19
|
+
app.set :default_currency_unit, '$'
|
20
|
+
app.set :default_currency_precision, 2
|
21
|
+
app.set :default_currency_separator, ','
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns an HTML sanitized string.
|
25
|
+
def h(str)
|
26
|
+
Rack::Utils.escape_html(str)
|
27
|
+
end
|
8
28
|
|
29
|
+
# Returns an array of pairs i.e.
|
30
|
+
#
|
31
|
+
# - ["Afghanistan", "AF"]
|
32
|
+
# - ...
|
33
|
+
# - ["United States", "US"]
|
34
|
+
# - ...
|
35
|
+
# - ["Zimbabwe", "ZW"]
|
36
|
+
#
|
37
|
+
# @return [Array] the array of name, code pairs.
|
9
38
|
def country_choices
|
10
39
|
Country.to_select
|
11
40
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
41
|
+
|
42
|
+
# Returns an array of pairs i.e.
|
43
|
+
#
|
44
|
+
# - [1, 1]
|
45
|
+
# - [2, 2]
|
46
|
+
# - ...
|
47
|
+
# - [31, 31]
|
48
|
+
#
|
49
|
+
# @return [Array] the array of day, day pairs.
|
50
|
+
def day_choices
|
51
|
+
days = (1..31).to_a
|
52
|
+
days.zip(days)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns an array of pairs i.e.
|
56
|
+
# - ['January', 1]
|
57
|
+
# - ['February', 2]
|
58
|
+
# - ...
|
59
|
+
# - ['December', 12]
|
60
|
+
#
|
61
|
+
# You may pass in Date::ABBR_MONTHNAMES if you want the shortened month names.
|
62
|
+
#
|
63
|
+
# @param [Array] month_names (defaults to Date::MONTHNAMES) an array with the
|
64
|
+
# first element being nil, element 1 being January, etc.
|
65
|
+
# @return [Array] the array of month name, month pairs.
|
66
|
+
def month_choices(month_names = settings.default_month_names)
|
67
|
+
month_names.map.
|
68
|
+
with_index { |month, idx| [month, idx] }.
|
16
69
|
tap { |arr| arr.shift }
|
17
70
|
end
|
18
|
-
|
19
|
-
|
71
|
+
|
72
|
+
# Returns an array of pairs i.e.
|
73
|
+
# - [2005, 2005]
|
74
|
+
# - [2006, 2006]
|
75
|
+
# - ...
|
76
|
+
# - [2010, 2010]
|
77
|
+
#
|
78
|
+
# @example
|
79
|
+
#
|
80
|
+
# year_choices # assuming it's now 2010
|
81
|
+
# # => [[1950, 1950], ..., [2010, 2010]]
|
82
|
+
#
|
83
|
+
# # we can pass in options
|
84
|
+
# year_choices(0, 6) # like for credit card options
|
85
|
+
# # => [[2010, 2010], ..., [2016, 2016]]
|
86
|
+
#
|
87
|
+
# # also we can override settings at the app level
|
88
|
+
# set :default_year_loffset, 0
|
89
|
+
# set :default_year_uoffset, 6
|
90
|
+
# year_choices
|
91
|
+
# # => [[2010, 2010], ..., [2016, 2016]]
|
92
|
+
#
|
93
|
+
# @param [Fixnum] loffset (defaults to -60) The lower offset relative to the current year.
|
94
|
+
# If it's 2010 now, passing in -5 here will start the year
|
95
|
+
# list at 2005 for example.
|
96
|
+
# @param [Fixnum] uoffset (defaults to 0) The upper offset relative to the
|
97
|
+
# current year. If it's 2010 now, passing in 5 or +5 here
|
98
|
+
# will end the year list at 2015 for example.
|
99
|
+
# @return [Array] the array of year, year pairs.
|
100
|
+
def year_choices(loffset = settings.default_year_loffset, uoffset = settings.default_year_uoffset)
|
20
101
|
years = ((Date.today.year + loffset)..(Date.today.year + uoffset)).to_a
|
21
102
|
years.zip(years)
|
22
103
|
end
|
104
|
+
|
105
|
+
# Accepts a list of pairs and produces option tags.
|
106
|
+
#
|
107
|
+
# @example
|
108
|
+
#
|
109
|
+
# select_options([['One', 1], ['Two', 2]])
|
110
|
+
# select_options([['One', 1], ['Two', 2]], 1)
|
111
|
+
# select_options([['One', 1], ['Two', 2]], 1, '- Choose -')
|
112
|
+
#
|
113
|
+
# # using it with the provided date helpers...
|
114
|
+
# select_options year_choices, 2010 # select 2010 as default
|
115
|
+
# select_options month_choices, 5 # select May as default
|
116
|
+
# select_options day_choices, 25 # select the 25th as default
|
117
|
+
#
|
118
|
+
# @param [Array] pairs a collection of label, value tuples.
|
119
|
+
# @param [Object] current the current value of this select.
|
120
|
+
# @param [#to_s] prompt a default prompt to place at the beginning
|
121
|
+
# of the list.
|
122
|
+
def select_options(pairs, current = nil, prompt = nil)
|
123
|
+
pairs.unshift([prompt, '']) if prompt
|
23
124
|
|
24
|
-
def select_options(pairs, current)
|
25
125
|
pairs.map { |label, value|
|
26
126
|
tag(:option, label, :value => value, :selected => (current == value))
|
27
127
|
}.join("\n")
|
28
128
|
end
|
29
|
-
|
129
|
+
|
130
|
+
# Presents errors on your form. Takes the explicit approach and assumes
|
131
|
+
# that for every form you have, the copy for the errors are important,
|
132
|
+
# instead of producing canned responses.
|
133
|
+
#
|
134
|
+
# Allows you to do the following in your haml view:
|
135
|
+
#
|
136
|
+
# @example
|
137
|
+
#
|
138
|
+
# - errors_on @user do |e|
|
139
|
+
# - e.on [:email, :not_present], "We need your email address."
|
140
|
+
# - e.on [:password, :not_present], "You must specify a password."
|
141
|
+
#
|
142
|
+
# # produces the following:
|
143
|
+
# # <div class="errors">
|
144
|
+
# # <ul>
|
145
|
+
# # <li>We need your email address</li>
|
146
|
+
# # <li>You must specify a password.</li>
|
147
|
+
# # </ul>
|
148
|
+
# # </div>
|
149
|
+
#
|
150
|
+
# @param [#errors] object An object responding to #errors. This validation
|
151
|
+
# also checks for the presence of a #full_messages method
|
152
|
+
# in the errors object for compatibility with ActiveRecord
|
153
|
+
# style objects.
|
154
|
+
# @param [Hash] options a hash of HTML attributes to place on the
|
155
|
+
# containing div.
|
156
|
+
# @option options [#to_s] :class (defaults to errors) The css class to put
|
157
|
+
# in the div.
|
158
|
+
# @yield [Sinatra::Helpers::HamlErrorPresenter] an object responding to #on.
|
159
|
+
#
|
160
|
+
# @see Sinatra::Helpers::HamlErrorPresenter#on
|
30
161
|
def errors_on(object, options = { :class => 'errors' }, &block)
|
31
162
|
return if object.errors.empty?
|
32
163
|
|
@@ -44,15 +175,81 @@ module Sinatra
|
|
44
175
|
end
|
45
176
|
end
|
46
177
|
end
|
47
|
-
|
178
|
+
|
179
|
+
# Formats a number into a currency display. Uses the following settings:
|
180
|
+
#
|
181
|
+
# - settings.default_currency_unit (defaults to '$')
|
182
|
+
# - settings.default_currency_precision (defaults to 2)
|
183
|
+
# - settings.default_currenty_separator (defaults to ',')
|
184
|
+
#
|
185
|
+
# @example
|
186
|
+
#
|
187
|
+
# currency(100) == "$ 100.00"
|
188
|
+
# # => true
|
189
|
+
#
|
190
|
+
# currency(100, :unit => "£") == "£ 100.00"
|
191
|
+
# # => true
|
192
|
+
#
|
193
|
+
# currency(100, :precision => 0) == "$ 100"
|
194
|
+
# => # true
|
195
|
+
#
|
196
|
+
# # somewhere in your sinatra context after registering Sinatra::Helpers
|
197
|
+
# set :default_currency_unit, '£'
|
198
|
+
# set :default_currency_precision, 3
|
199
|
+
# set :default_currency_separator, ' '
|
200
|
+
#
|
201
|
+
# currency(100) == "£ 100.000"
|
202
|
+
# # => true
|
203
|
+
#
|
204
|
+
# @param [Numeric] number the number you wish to display as a currency.
|
205
|
+
# @param [Hash] opts the various options available.
|
206
|
+
# @option opts [#to_s] :unit (defaults to '$')
|
207
|
+
# @option opts [Fixnum] :precision (defaults to 2)
|
208
|
+
# @option opts [#to_s] :separator (defaults to ',')
|
209
|
+
# @return [String] the formatted string based on `number`.
|
210
|
+
# @return [nil] if given nil or an empty string.
|
211
|
+
def currency(number, opts = {})
|
212
|
+
return if number.to_s.empty?
|
213
|
+
|
214
|
+
unit = opts[:unit] || settings.default_currency_unit
|
215
|
+
precision = opts[:precision] || settings.default_currency_precision
|
216
|
+
separator = opts[:separator] || settings.default_currency_separator
|
217
|
+
|
218
|
+
ret = "%s %.#{ Integer(precision) }f" % [unit, number]
|
219
|
+
parts = ret.split('.')
|
220
|
+
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{separator}")
|
221
|
+
parts.join('.')
|
222
|
+
end
|
223
|
+
|
224
|
+
# Show the percentage representation of a numeric value.
|
225
|
+
#
|
226
|
+
# @example
|
227
|
+
# percentage(100) == "100.00%"
|
228
|
+
# percentage(100, 0) == "100%"
|
229
|
+
#
|
230
|
+
# @param [Numeric] number A numeric value
|
231
|
+
# @param [Fixnum] precision (defaults to 2) Number of decimals to show.
|
232
|
+
# @return [String] the number displayed as a percentage
|
233
|
+
# @return [nil] given a nil value or an empty string.
|
234
|
+
def percentage(number, precision = 2)
|
235
|
+
return if number.to_s.empty?
|
236
|
+
|
237
|
+
ret = "%02.#{ precision }f%" % number
|
238
|
+
ret.gsub(/\.0*%$/, '%')
|
239
|
+
end
|
240
|
+
|
48
241
|
protected
|
49
242
|
def tag(tag, content, atts = {})
|
50
|
-
tag_atts = atts.inject(
|
51
|
-
a << ('%s="%s"' % [k, v]) if v
|
243
|
+
tag_atts = atts.inject([]) { |a, (k, v)|
|
244
|
+
a << (' %s="%s"' % [k, escape_attr(v)]) if v
|
52
245
|
a
|
53
|
-
}
|
246
|
+
}.join('')
|
247
|
+
|
248
|
+
%(<#{ tag }#{ tag_atts }>#{h content}</#{ tag }>)
|
249
|
+
end
|
54
250
|
|
55
|
-
|
251
|
+
def escape_attr(str)
|
252
|
+
str.to_s.gsub("'", "'").gsub('"', """)
|
56
253
|
end
|
57
254
|
end
|
58
255
|
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# Taken from ohm
|
2
2
|
|
3
3
|
unless "".respond_to?(:lines)
|
4
|
+
# @private 1.8.6 compatibility only
|
4
5
|
class String
|
5
|
-
|
6
|
+
# @private
|
6
7
|
# This version of String#lines is almost fully compatible with that
|
7
8
|
# of Ruby 1.9. If a zero-length record separator is supplied in Ruby
|
8
9
|
# 1.9, the string is split into paragraphs delimited by multiple
|
@@ -17,11 +18,13 @@ unless "".respond_to?(:lines)
|
|
17
18
|
end
|
18
19
|
|
19
20
|
unless respond_to?(:tap)
|
21
|
+
# @private 1.8.6 compatibility only
|
20
22
|
class Object
|
23
|
+
# @private no need to explain. Standard ruby 1.9 stuff.
|
24
|
+
# @see http://ruby-doc.org/ruby-1.9/classes/Object.html#M000239
|
21
25
|
def tap
|
22
26
|
yield(self)
|
23
27
|
self
|
24
28
|
end
|
25
29
|
end
|
26
30
|
end
|
27
|
-
|
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
module Sinatra
|
4
4
|
module Helpers
|
5
|
-
|
6
|
-
|
5
|
+
# A simple module containing all countries as of 2010.
|
6
|
+
module Country
|
7
|
+
@all = {
|
7
8
|
:AF => "Afghanistan",
|
8
|
-
:AX => "
|
9
|
+
:AX => "Åland Islands",
|
9
10
|
:AL => "Albania",
|
10
11
|
:DZ => "Algeria",
|
11
12
|
:AS => "American Samoa",
|
@@ -30,22 +31,19 @@ module Sinatra
|
|
30
31
|
:BJ => "Benin",
|
31
32
|
:BM => "Bermuda",
|
32
33
|
:BT => "Bhutan",
|
33
|
-
:BO => "Bolivia",
|
34
|
+
:BO => "Bolivia, Plurinational State of",
|
34
35
|
:BA => "Bosnia and Herzegovina",
|
35
36
|
:BW => "Botswana",
|
36
37
|
:BV => "Bouvet Island",
|
37
38
|
:BR => "Brazil",
|
38
|
-
:BQ => "British Antarctic Territory",
|
39
39
|
:IO => "British Indian Ocean Territory",
|
40
|
-
:
|
41
|
-
:BN => "Brunei",
|
40
|
+
:BN => "Brunei Darussalam",
|
42
41
|
:BG => "Bulgaria",
|
43
42
|
:BF => "Burkina Faso",
|
44
43
|
:BI => "Burundi",
|
45
44
|
:KH => "Cambodia",
|
46
45
|
:CM => "Cameroon",
|
47
46
|
:CA => "Canada",
|
48
|
-
:CT => "Canton and Enderbury Islands",
|
49
47
|
:CV => "Cape Verde",
|
50
48
|
:KY => "Cayman Islands",
|
51
49
|
:CF => "Central African Republic",
|
@@ -53,13 +51,14 @@ module Sinatra
|
|
53
51
|
:CL => "Chile",
|
54
52
|
:CN => "China",
|
55
53
|
:CX => "Christmas Island",
|
56
|
-
:CC => "Cocos Islands",
|
54
|
+
:CC => "Cocos (Keeling) Islands",
|
57
55
|
:CO => "Colombia",
|
58
56
|
:KM => "Comoros",
|
59
|
-
:CG => "Congo
|
60
|
-
:CD => "Congo
|
57
|
+
:CG => "Congo",
|
58
|
+
:CD => "Congo, the Democratic Republic of the",
|
61
59
|
:CK => "Cook Islands",
|
62
60
|
:CR => "Costa Rica",
|
61
|
+
:CI => "CÔte D'ivoire",
|
63
62
|
:HR => "Croatia",
|
64
63
|
:CU => "Cuba",
|
65
64
|
:CY => "Cyprus",
|
@@ -68,9 +67,6 @@ module Sinatra
|
|
68
67
|
:DJ => "Djibouti",
|
69
68
|
:DM => "Dominica",
|
70
69
|
:DO => "Dominican Republic",
|
71
|
-
:NQ => "Dronning Maud Land",
|
72
|
-
:DD => "East Germany",
|
73
|
-
:TL => "East Timor",
|
74
70
|
:EC => "Ecuador",
|
75
71
|
:EG => "Egypt",
|
76
72
|
:SV => "El Salvador",
|
@@ -78,8 +74,7 @@ module Sinatra
|
|
78
74
|
:ER => "Eritrea",
|
79
75
|
:EE => "Estonia",
|
80
76
|
:ET => "Ethiopia",
|
81
|
-
:
|
82
|
-
:FK => "Falkland Islands",
|
77
|
+
:FK => "Falkland Islands (Malvinas)",
|
83
78
|
:FO => "Faroe Islands",
|
84
79
|
:FJ => "Fiji",
|
85
80
|
:FI => "Finland",
|
@@ -87,7 +82,6 @@ module Sinatra
|
|
87
82
|
:GF => "French Guiana",
|
88
83
|
:PF => "French Polynesia",
|
89
84
|
:TF => "French Southern Territories",
|
90
|
-
:FQ => "French Southern and Antarctic Territories",
|
91
85
|
:GA => "Gabon",
|
92
86
|
:GM => "Gambia",
|
93
87
|
:GE => "Georgia",
|
@@ -102,44 +96,45 @@ module Sinatra
|
|
102
96
|
:GT => "Guatemala",
|
103
97
|
:GG => "Guernsey",
|
104
98
|
:GN => "Guinea",
|
105
|
-
:GW => "Guinea-
|
99
|
+
:GW => "Guinea-bissau",
|
106
100
|
:GY => "Guyana",
|
107
101
|
:HT => "Haiti",
|
108
|
-
:HM => "Heard Island and
|
102
|
+
:HM => "Heard Island and Mcdonald Islands",
|
103
|
+
:VA => "Holy See (Vatican City State)",
|
109
104
|
:HN => "Honduras",
|
110
105
|
:HK => "Hong Kong",
|
111
106
|
:HU => "Hungary",
|
112
107
|
:IS => "Iceland",
|
113
108
|
:IN => "India",
|
114
109
|
:ID => "Indonesia",
|
115
|
-
:IR => "Iran",
|
110
|
+
:IR => "Iran, Islamic Republic of",
|
116
111
|
:IQ => "Iraq",
|
117
112
|
:IE => "Ireland",
|
118
113
|
:IM => "Isle of Man",
|
119
114
|
:IL => "Israel",
|
120
115
|
:IT => "Italy",
|
121
|
-
:CI => "Ivory Coast",
|
122
116
|
:JM => "Jamaica",
|
123
117
|
:JP => "Japan",
|
124
118
|
:JE => "Jersey",
|
125
|
-
:JT => "Johnston Island",
|
126
119
|
:JO => "Jordan",
|
127
120
|
:KZ => "Kazakhstan",
|
128
121
|
:KE => "Kenya",
|
129
122
|
:KI => "Kiribati",
|
123
|
+
:KP => "Korea, Democratic People's Republic of",
|
124
|
+
:KR => "Korea, Republic of",
|
130
125
|
:KW => "Kuwait",
|
131
126
|
:KG => "Kyrgyzstan",
|
132
|
-
:LA => "
|
127
|
+
:LA => "Lao People's Democratic Republic",
|
133
128
|
:LV => "Latvia",
|
134
129
|
:LB => "Lebanon",
|
135
130
|
:LS => "Lesotho",
|
136
131
|
:LR => "Liberia",
|
137
|
-
:LY => "
|
132
|
+
:LY => "Libyan Arab Jamahiriya",
|
138
133
|
:LI => "Liechtenstein",
|
139
134
|
:LT => "Lithuania",
|
140
135
|
:LU => "Luxembourg",
|
141
|
-
:MO => "
|
142
|
-
:MK => "Macedonia",
|
136
|
+
:MO => "Macao",
|
137
|
+
:MK => "Macedonia, the Former Yugoslav Republic of",
|
143
138
|
:MG => "Madagascar",
|
144
139
|
:MW => "Malawi",
|
145
140
|
:MY => "Malaysia",
|
@@ -151,11 +146,9 @@ module Sinatra
|
|
151
146
|
:MR => "Mauritania",
|
152
147
|
:MU => "Mauritius",
|
153
148
|
:YT => "Mayotte",
|
154
|
-
:FX => "Metropolitan France",
|
155
149
|
:MX => "Mexico",
|
156
|
-
:FM => "Micronesia",
|
157
|
-
:
|
158
|
-
:MD => "Moldova",
|
150
|
+
:FM => "Micronesia, Federated States of",
|
151
|
+
:MD => "Moldova, Republic of",
|
159
152
|
:MC => "Monaco",
|
160
153
|
:MN => "Mongolia",
|
161
154
|
:ME => "Montenegro",
|
@@ -168,7 +161,6 @@ module Sinatra
|
|
168
161
|
:NP => "Nepal",
|
169
162
|
:NL => "Netherlands",
|
170
163
|
:AN => "Netherlands Antilles",
|
171
|
-
:NT => "Neutral Zone",
|
172
164
|
:NC => "New Caledonia",
|
173
165
|
:NZ => "New Zealand",
|
174
166
|
:NI => "Nicaragua",
|
@@ -176,21 +168,15 @@ module Sinatra
|
|
176
168
|
:NG => "Nigeria",
|
177
169
|
:NU => "Niue",
|
178
170
|
:NF => "Norfolk Island",
|
179
|
-
:KP => "North Korea",
|
180
|
-
:VD => "North Vietnam",
|
181
171
|
:MP => "Northern Mariana Islands",
|
182
172
|
:NO => "Norway",
|
183
173
|
:OM => "Oman",
|
184
|
-
:QO => "Outlying Oceania",
|
185
|
-
:PC => "Pacific Islands Trust Territory",
|
186
174
|
:PK => "Pakistan",
|
187
175
|
:PW => "Palau",
|
188
|
-
:PS => "Palestinian Territory",
|
176
|
+
:PS => "Palestinian Territory, Occupied",
|
189
177
|
:PA => "Panama",
|
190
|
-
:PZ => "Panama Canal Zone",
|
191
178
|
:PG => "Papua New Guinea",
|
192
179
|
:PY => "Paraguay",
|
193
|
-
:YD => "People's Democratic Republic of Yemen",
|
194
180
|
:PE => "Peru",
|
195
181
|
:PH => "Philippines",
|
196
182
|
:PN => "Pitcairn",
|
@@ -198,12 +184,12 @@ module Sinatra
|
|
198
184
|
:PT => "Portugal",
|
199
185
|
:PR => "Puerto Rico",
|
200
186
|
:QA => "Qatar",
|
201
|
-
:RE => "
|
187
|
+
:RE => "RÉunion",
|
202
188
|
:RO => "Romania",
|
203
|
-
:RU => "
|
189
|
+
:RU => "Russian Federation",
|
204
190
|
:RW => "Rwanda",
|
205
|
-
:BL => "Saint
|
206
|
-
:SH => "Saint Helena",
|
191
|
+
:BL => "Saint BarthÉlemy",
|
192
|
+
:SH => "Saint Helena, Ascension and Tristan Da Cunha",
|
207
193
|
:KN => "Saint Kitts and Nevis",
|
208
194
|
:LC => "Saint Lucia",
|
209
195
|
:MF => "Saint Martin",
|
@@ -215,7 +201,6 @@ module Sinatra
|
|
215
201
|
:SA => "Saudi Arabia",
|
216
202
|
:SN => "Senegal",
|
217
203
|
:RS => "Serbia",
|
218
|
-
:CS => "Serbia and Montenegro",
|
219
204
|
:SC => "Seychelles",
|
220
205
|
:SL => "Sierra Leone",
|
221
206
|
:SG => "Singapore",
|
@@ -225,7 +210,6 @@ module Sinatra
|
|
225
210
|
:SO => "Somalia",
|
226
211
|
:ZA => "South Africa",
|
227
212
|
:GS => "South Georgia and the South Sandwich Islands",
|
228
|
-
:KR => "South Korea",
|
229
213
|
:ES => "Spain",
|
230
214
|
:LK => "Sri Lanka",
|
231
215
|
:SD => "Sudan",
|
@@ -234,11 +218,12 @@ module Sinatra
|
|
234
218
|
:SZ => "Swaziland",
|
235
219
|
:SE => "Sweden",
|
236
220
|
:CH => "Switzerland",
|
237
|
-
:SY => "
|
238
|
-
:TW => "Taiwan",
|
221
|
+
:SY => "Syrian Arab Republic",
|
222
|
+
:TW => "Taiwan, Province of China",
|
239
223
|
:TJ => "Tajikistan",
|
240
|
-
:TZ => "Tanzania",
|
224
|
+
:TZ => "Tanzania, United Republic of",
|
241
225
|
:TH => "Thailand",
|
226
|
+
:TL => "Timor-leste",
|
242
227
|
:TG => "Togo",
|
243
228
|
:TK => "Tokelau",
|
244
229
|
:TO => "Tonga",
|
@@ -248,23 +233,20 @@ module Sinatra
|
|
248
233
|
:TM => "Turkmenistan",
|
249
234
|
:TC => "Turks and Caicos Islands",
|
250
235
|
:TV => "Tuvalu",
|
251
|
-
:PU => "U.S. Miscellaneous Pacific Islands",
|
252
|
-
:VI => "U.S. Virgin Islands",
|
253
236
|
:UG => "Uganda",
|
254
237
|
:UA => "Ukraine",
|
255
|
-
:SU => "Union of Soviet Socialist Republics",
|
256
238
|
:AE => "United Arab Emirates",
|
257
239
|
:GB => "United Kingdom",
|
258
240
|
:US => "United States",
|
259
241
|
:UM => "United States Minor Outlying Islands",
|
260
|
-
:ZZ => "Unknown or Invalid Region",
|
261
242
|
:UY => "Uruguay",
|
262
243
|
:UZ => "Uzbekistan",
|
263
244
|
:VU => "Vanuatu",
|
264
|
-
:VA => "Vatican",
|
265
|
-
:VE => "Venezuela",
|
266
|
-
:VN => "
|
267
|
-
:
|
245
|
+
:VA => "Vatican City State",
|
246
|
+
:VE => "Venezuela, Bolivarian Republic of",
|
247
|
+
:VN => "Viet Nam",
|
248
|
+
:VG => "Virgin Islands, British",
|
249
|
+
:VI => "Virgin Islands, U.S.",
|
268
250
|
:WF => "Wallis and Futuna",
|
269
251
|
:EH => "Western Sahara",
|
270
252
|
:YE => "Yemen",
|
@@ -272,18 +254,50 @@ module Sinatra
|
|
272
254
|
:ZW => "Zimbabwe"
|
273
255
|
}
|
274
256
|
|
275
|
-
|
276
|
-
|
277
|
-
|
257
|
+
# @example
|
258
|
+
#
|
259
|
+
# p Country.to_select
|
260
|
+
# [["Afghanistan", "AF"], ["Åland Islands", "AX"], ["Albania", "AL"],
|
261
|
+
# ["Algeria", "DZ"], ["American Samoa", "AS"], ... ["Zimbabwe", "ZW"]]
|
262
|
+
#
|
263
|
+
# @return [Array] a collection of pairs with the first element being
|
264
|
+
# country name and the last element being the code.
|
265
|
+
#
|
266
|
+
# @see Sinatra::Helpers#country_choices
|
267
|
+
def to_select
|
268
|
+
all.map { |code, name| [name, code.to_s] }
|
278
269
|
end
|
279
|
-
|
280
|
-
|
281
|
-
|
270
|
+
|
271
|
+
# Retrieves the country name given a country code.
|
272
|
+
# @example
|
273
|
+
#
|
274
|
+
# Sinatra::Helpers::Country["US"] == "United States"
|
275
|
+
# # => true
|
276
|
+
#
|
277
|
+
# Sinatra::Helpers::Country[:US] == "United States"
|
278
|
+
# # => true
|
279
|
+
#
|
280
|
+
# @param [#to_sym] code The country code in 2 letter all caps format.
|
281
|
+
# @return [String] The corresponding country name given the code.
|
282
|
+
# @return [nil] nil if no matching country code.
|
283
|
+
def [](code)
|
284
|
+
all[code.to_sym] if not code.to_s.empty?
|
282
285
|
end
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
+
|
287
|
+
# For use with seeding dummy data.
|
288
|
+
# @return [Symbol] a randomized country code.
|
289
|
+
def random
|
290
|
+
all.keys.shuffle.first
|
286
291
|
end
|
292
|
+
|
293
|
+
# Gives all countries in a Hash.
|
294
|
+
#
|
295
|
+
# @return [Hash] the code => name pairs of all countries.
|
296
|
+
def all
|
297
|
+
@all
|
298
|
+
end
|
299
|
+
|
300
|
+
module_function :all, :to_select, :[], :random
|
287
301
|
end
|
288
302
|
end
|
289
303
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module Sinatra
|
2
2
|
module Helpers
|
3
|
-
#
|
4
|
-
# Credit goes to citrusbyte.
|
3
|
+
# @see http://github.com/citrusbyte/reddit-clone
|
5
4
|
class HamlErrorPresenter < Ohm::Validations::Presenter
|
6
5
|
def on(error, message = (block_given? ? @context.capture_haml { yield } : raise(ArgumentError)))
|
7
6
|
handle(error) do
|
data/sinatra-helpers.gemspec
CHANGED
@@ -5,22 +5,22 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{sinatra-helpers}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Cyril David"]
|
12
|
-
s.date = %q{2010-05-
|
12
|
+
s.date = %q{2010-05-27}
|
13
13
|
s.description = %q{Includes month_choices, year_choices, country_choices}
|
14
14
|
s.email = %q{cyx.ucron@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
"README.
|
17
|
+
"README.markdown"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
21
|
".gitignore",
|
22
22
|
"LICENSE",
|
23
|
-
"README.
|
23
|
+
"README.markdown",
|
24
24
|
"Rakefile",
|
25
25
|
"VERSION",
|
26
26
|
"lib/sinatra/helpers.rb",
|
@@ -28,7 +28,9 @@ Gem::Specification.new do |s|
|
|
28
28
|
"lib/sinatra/helpers/country.rb",
|
29
29
|
"lib/sinatra/helpers/haml_error_presenter.rb",
|
30
30
|
"sinatra-helpers.gemspec",
|
31
|
-
"test/helper.rb"
|
31
|
+
"test/helper.rb",
|
32
|
+
"test/test_country.rb",
|
33
|
+
"test/test_sinatra_helpers.rb"
|
32
34
|
]
|
33
35
|
s.homepage = %q{http://github.com/sinefunc/sinatra-helpers}
|
34
36
|
s.rdoc_options = ["--charset=UTF-8"]
|
@@ -36,7 +38,9 @@ Gem::Specification.new do |s|
|
|
36
38
|
s.rubygems_version = %q{1.3.6}
|
37
39
|
s.summary = %q{Some generic helpers for the view layer}
|
38
40
|
s.test_files = [
|
39
|
-
"test/helper.rb"
|
41
|
+
"test/helper.rb",
|
42
|
+
"test/test_country.rb",
|
43
|
+
"test/test_sinatra_helpers.rb"
|
40
44
|
]
|
41
45
|
|
42
46
|
if s.respond_to? :specification_version then
|
@@ -44,12 +48,30 @@ Gem::Specification.new do |s|
|
|
44
48
|
s.specification_version = 3
|
45
49
|
|
46
50
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
51
|
+
s.add_runtime_dependency(%q<sinatra>, [">= 1.0"])
|
47
52
|
s.add_development_dependency(%q<contest>, [">= 0"])
|
53
|
+
s.add_development_dependency(%q<mocha>, [">= 0"])
|
54
|
+
s.add_development_dependency(%q<rack-test>, [">= 0"])
|
55
|
+
s.add_development_dependency(%q<nokogiri>, [">= 0"])
|
56
|
+
s.add_development_dependency(%q<ohm>, [">= 0"])
|
57
|
+
s.add_development_dependency(%q<haml>, [">= 0"])
|
48
58
|
else
|
59
|
+
s.add_dependency(%q<sinatra>, [">= 1.0"])
|
49
60
|
s.add_dependency(%q<contest>, [">= 0"])
|
61
|
+
s.add_dependency(%q<mocha>, [">= 0"])
|
62
|
+
s.add_dependency(%q<rack-test>, [">= 0"])
|
63
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
64
|
+
s.add_dependency(%q<ohm>, [">= 0"])
|
65
|
+
s.add_dependency(%q<haml>, [">= 0"])
|
50
66
|
end
|
51
67
|
else
|
68
|
+
s.add_dependency(%q<sinatra>, [">= 1.0"])
|
52
69
|
s.add_dependency(%q<contest>, [">= 0"])
|
70
|
+
s.add_dependency(%q<mocha>, [">= 0"])
|
71
|
+
s.add_dependency(%q<rack-test>, [">= 0"])
|
72
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
73
|
+
s.add_dependency(%q<ohm>, [">= 0"])
|
74
|
+
s.add_dependency(%q<haml>, [">= 0"])
|
53
75
|
end
|
54
76
|
end
|
55
77
|
|
data/test/helper.rb
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'test/unit'
|
3
3
|
require 'contest'
|
4
|
+
require 'mocha'
|
5
|
+
require 'rack/test'
|
6
|
+
require 'nokogiri'
|
7
|
+
require 'ohm'
|
8
|
+
require 'haml'
|
4
9
|
|
5
10
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
11
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
-
require 'sinatra
|
12
|
+
require 'sinatra/helpers'
|
8
13
|
|
9
14
|
class Test::Unit::TestCase
|
10
15
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class CountryTest < Test::Unit::TestCase
|
4
|
+
include Sinatra::Helpers
|
5
|
+
|
6
|
+
test "241 countries" do
|
7
|
+
assert_equal 246, Country.to_select.length
|
8
|
+
end
|
9
|
+
|
10
|
+
test "has a matching name for all keys" do
|
11
|
+
Country.all.each do |code, name|
|
12
|
+
assert_equal name, Country[code]
|
13
|
+
assert_equal name, Country[code.to_s]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
test "random returns a valid code" do
|
18
|
+
246.times {
|
19
|
+
assert Country[Country.random]
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
test "finding a country with wrong parameters" do
|
24
|
+
assert_nil Country[""]
|
25
|
+
assert_nil Country[nil]
|
26
|
+
assert_nil Country[:XX]
|
27
|
+
assert_nil Country["XX"]
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,298 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class SintatraHelpersTest < Test::Unit::TestCase
|
4
|
+
include Sinatra::Helpers
|
5
|
+
|
6
|
+
attr :settings
|
7
|
+
|
8
|
+
test "h" do
|
9
|
+
assert_equal "<Foo>", h("<Foo>")
|
10
|
+
assert_equal "<Foo bar='baz'>", h("<Foo bar='baz'>")
|
11
|
+
assert_equal "<Foo bar="baz">", h("<Foo bar=\"baz\">")
|
12
|
+
end
|
13
|
+
|
14
|
+
test "country_choices returns Country.to_select" do
|
15
|
+
assert_equal Country.to_select, country_choices
|
16
|
+
end
|
17
|
+
|
18
|
+
test "day_choices returns 1 to 31" do
|
19
|
+
assert_equal 31, day_choices.size
|
20
|
+
assert_equal [1, 1], day_choices.first
|
21
|
+
assert_equal [31, 31], day_choices.last
|
22
|
+
|
23
|
+
day_choices.each do |label, value|
|
24
|
+
assert_equal label, value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "month choices" do
|
29
|
+
setup do
|
30
|
+
@settings = stub("Settings", :default_month_names => Date::MONTHNAMES)
|
31
|
+
end
|
32
|
+
|
33
|
+
test "by default" do
|
34
|
+
assert_equal ["January", 1], month_choices[0]
|
35
|
+
assert_equal ["February", 2], month_choices[1]
|
36
|
+
assert_equal ["March", 3], month_choices[2]
|
37
|
+
assert_equal ["April", 4], month_choices[3]
|
38
|
+
assert_equal ["May", 5], month_choices[4]
|
39
|
+
assert_equal ["June", 6], month_choices[5]
|
40
|
+
assert_equal ["July", 7], month_choices[6]
|
41
|
+
assert_equal ["August", 8], month_choices[7]
|
42
|
+
assert_equal ["September", 9], month_choices[8]
|
43
|
+
assert_equal ["October", 10], month_choices[9]
|
44
|
+
assert_equal ["November", 11], month_choices[10]
|
45
|
+
assert_equal ["December", 12], month_choices[11]
|
46
|
+
end
|
47
|
+
|
48
|
+
test "given Date::ABBR_MONTHNAMES" do
|
49
|
+
month_choices = month_choices(Date::ABBR_MONTHNAMES)
|
50
|
+
|
51
|
+
assert_equal ["Jan", 1], month_choices[0]
|
52
|
+
assert_equal ["Feb", 2], month_choices[1]
|
53
|
+
assert_equal ["Mar", 3], month_choices[2]
|
54
|
+
assert_equal ["Apr", 4], month_choices[3]
|
55
|
+
assert_equal ["May", 5], month_choices[4]
|
56
|
+
assert_equal ["Jun", 6], month_choices[5]
|
57
|
+
assert_equal ["Jul", 7], month_choices[6]
|
58
|
+
assert_equal ["Aug", 8], month_choices[7]
|
59
|
+
assert_equal ["Sep", 9], month_choices[8]
|
60
|
+
assert_equal ["Oct", 10], month_choices[9]
|
61
|
+
assert_equal ["Nov", 11], month_choices[10]
|
62
|
+
assert_equal ["Dec", 12], month_choices[11]
|
63
|
+
end
|
64
|
+
|
65
|
+
test "when changing settings.default_month_names" do
|
66
|
+
settings.expects(:default_month_names).at_least_once.returns(Date::ABBR_MONTHNAMES)
|
67
|
+
|
68
|
+
assert_equal ["Jan", 1], month_choices[0]
|
69
|
+
assert_equal ["Feb", 2], month_choices[1]
|
70
|
+
assert_equal ["Nov", 11], month_choices[10]
|
71
|
+
assert_equal ["Dec", 12], month_choices[11]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "year choices" do
|
76
|
+
setup do
|
77
|
+
@settings = stub("Settings", :default_year_loffset => -60,
|
78
|
+
:default_year_uoffset => 0)
|
79
|
+
end
|
80
|
+
|
81
|
+
test "by default" do
|
82
|
+
assert_equal 61, year_choices.size
|
83
|
+
year_choices.each do |label, value|
|
84
|
+
assert_equal label, value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
test "allows to pass in a lower upper offset" do
|
89
|
+
assert_equal 1, year_choices(0, 0).size
|
90
|
+
assert_equal [Date.today.year, Date.today.year], year_choices(0, 0).first
|
91
|
+
|
92
|
+
Date.expects(:today).at_least_once.returns(Date.new(2010, 5, 5))
|
93
|
+
assert_equal [2005, 2005], year_choices(-5).first
|
94
|
+
assert_equal [2015, 2015], year_choices(0, 5).last
|
95
|
+
end
|
96
|
+
|
97
|
+
test "allows to customize via global settings" do
|
98
|
+
settings.expects(:default_year_loffset).at_least_once.returns(0)
|
99
|
+
settings.expects(:default_year_uoffset).at_least_once.returns(6)
|
100
|
+
|
101
|
+
expected = (2010..2016).to_a
|
102
|
+
expected = expected.zip(expected)
|
103
|
+
|
104
|
+
assert_equal expected, year_choices
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "in a real sinatra app" do
|
109
|
+
class App < Sinatra::Base
|
110
|
+
register Sinatra::Helpers
|
111
|
+
|
112
|
+
get '/years' do
|
113
|
+
year_choices.to_s
|
114
|
+
end
|
115
|
+
|
116
|
+
get '/months' do
|
117
|
+
month_choices.to_s
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
include Rack::Test::Methods
|
122
|
+
|
123
|
+
def app
|
124
|
+
App.new
|
125
|
+
end
|
126
|
+
|
127
|
+
test "returns the expected years" do
|
128
|
+
get '/years'
|
129
|
+
|
130
|
+
settings.stubs(:default_year_loffset).returns(-60)
|
131
|
+
settings.stubs(:default_year_uoffset).returns(0)
|
132
|
+
|
133
|
+
assert_equal year_choices.to_s, last_response.body
|
134
|
+
end
|
135
|
+
|
136
|
+
test "returns the expected months" do
|
137
|
+
get '/months'
|
138
|
+
|
139
|
+
settings.stubs(:default_month_names).returns(Date::MONTHNAMES)
|
140
|
+
assert_equal month_choices.to_s, last_response.body
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "select_options" do
|
145
|
+
test "displays the pairs" do
|
146
|
+
html = select_options([['One', 1], ['Two', 2]])
|
147
|
+
doc = Nokogiri(%(<body>#{html}</body>))
|
148
|
+
|
149
|
+
assert_equal 'One', doc.search('option[value="1"]').text
|
150
|
+
assert_equal 'Two', doc.search('option[value="2"]').text
|
151
|
+
end
|
152
|
+
|
153
|
+
test "marks option as selected" do
|
154
|
+
html = select_options([['One', 1], ['Two', 2]], 1)
|
155
|
+
doc = Nokogiri(%(<body>#{html}</body>))
|
156
|
+
|
157
|
+
assert_equal 'One', doc.search('option[value="1"][selected]').text
|
158
|
+
assert_equal 'Two', doc.search('option[value="2"]').text
|
159
|
+
end
|
160
|
+
|
161
|
+
test "produces a prompt properly" do
|
162
|
+
html = select_options([['One', 1], ['Two', 2]], 1, "- Choose -")
|
163
|
+
doc = Nokogiri(%(<body>#{html}</body>))
|
164
|
+
|
165
|
+
assert_equal '- Choose -', doc.search('option[value=""]').text
|
166
|
+
assert_equal 'One', doc.search('option[value="1"][selected]').text
|
167
|
+
assert_equal 'Two', doc.search('option[value="2"]').text
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe "tag" do
|
172
|
+
test "the basic no attr case" do
|
173
|
+
assert_equal '<div>Foobar</div>', tag('div', 'Foobar')
|
174
|
+
end
|
175
|
+
|
176
|
+
test "one attr case" do
|
177
|
+
assert_equal '<div class="baz">Foobar</div>',
|
178
|
+
tag('div', 'Foobar', :class => 'baz')
|
179
|
+
end
|
180
|
+
|
181
|
+
test "many attrs case" do
|
182
|
+
assert_equal '<div class="baz bar" style="display:none">Foobar</div>',
|
183
|
+
tag('div', 'Foobar', :class => 'baz bar', :style => 'display:none')
|
184
|
+
end
|
185
|
+
|
186
|
+
test "funky attrs case" do
|
187
|
+
assert_equal '<div class="baz 'bar'" ' +
|
188
|
+
'style="display:"none"">Foobar</div>',
|
189
|
+
tag('div', 'Foobar', :class => "baz 'bar'", :style => 'display:"none"')
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "errors_on" do
|
194
|
+
include Rack::Test::Methods
|
195
|
+
|
196
|
+
class App < Sinatra::Base
|
197
|
+
FORM = (<<-FORM).gsub(/^ {6}/, '')
|
198
|
+
- errors_on @post do |e|
|
199
|
+
- e.on [:email, :not_present], "Email is required."
|
200
|
+
- e.on [:name, :not_present], "Name is required."
|
201
|
+
FORM
|
202
|
+
|
203
|
+
register Sinatra::Helpers
|
204
|
+
|
205
|
+
class Post < Ohm::Model
|
206
|
+
attribute :email
|
207
|
+
attribute :name
|
208
|
+
|
209
|
+
def validate
|
210
|
+
assert_present :email
|
211
|
+
assert_present :name
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
get '/form' do
|
216
|
+
@post = Post.new
|
217
|
+
@post.valid?
|
218
|
+
|
219
|
+
haml FORM
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def app
|
224
|
+
App.new
|
225
|
+
end
|
226
|
+
|
227
|
+
test "produces proper errors" do
|
228
|
+
get '/form'
|
229
|
+
|
230
|
+
doc = Nokogiri(last_response.body)
|
231
|
+
|
232
|
+
assert_equal 1, doc.search('div.errors').length
|
233
|
+
|
234
|
+
assert_equal 'Email is required.',
|
235
|
+
doc.search('div.errors > ul > li:first-child').text
|
236
|
+
|
237
|
+
assert_equal 'Name is required.',
|
238
|
+
doc.search('div.errors > ul > li:last-child').text
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe "currency" do
|
243
|
+
setup do
|
244
|
+
settings.stubs(:default_currency_unit).returns('$')
|
245
|
+
settings.stubs(:default_currency_precision).returns(2)
|
246
|
+
settings.stubs(:default_currency_separator).returns(',')
|
247
|
+
end
|
248
|
+
|
249
|
+
test "nil" do
|
250
|
+
assert_nil currency(nil)
|
251
|
+
end
|
252
|
+
|
253
|
+
test "defaults" do
|
254
|
+
assert_equal "$ 10.00", currency(10)
|
255
|
+
end
|
256
|
+
|
257
|
+
test "with custom unit, precision" do
|
258
|
+
assert_equal "£ 10.0", currency(10, :unit => "£", :precision => 1)
|
259
|
+
end
|
260
|
+
|
261
|
+
test "with 0 precision" do
|
262
|
+
assert_equal "$ 10", currency(10, :precision => 0)
|
263
|
+
end
|
264
|
+
|
265
|
+
test "separators" do
|
266
|
+
assert_equal "$ 100.00", currency(100)
|
267
|
+
assert_equal "$ 1,000.00", currency(1_000)
|
268
|
+
assert_equal "$ 10,000.00", currency(10_000)
|
269
|
+
assert_equal "$ 100,000.00", currency(100_000)
|
270
|
+
assert_equal "$ 1,000,000.00", currency(1_000_000)
|
271
|
+
end
|
272
|
+
|
273
|
+
test "specified defaults" do
|
274
|
+
settings.stubs(:default_currency_unit).returns('P')
|
275
|
+
settings.stubs(:default_currency_precision).returns(3)
|
276
|
+
settings.stubs(:default_currency_separator).returns(' ')
|
277
|
+
|
278
|
+
assert_equal "P 100.000", currency(100)
|
279
|
+
assert_equal "P 1 000.000", currency(1_000)
|
280
|
+
assert_equal "P 10 000.000", currency(10_000)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
describe "percentage" do
|
285
|
+
test "nil" do
|
286
|
+
assert_nil percentage(nil)
|
287
|
+
end
|
288
|
+
|
289
|
+
test "various percentages" do
|
290
|
+
assert_equal '0.01%', percentage(0.01)
|
291
|
+
assert_equal '0.10%', percentage(0.10)
|
292
|
+
assert_equal '1%', percentage(1.00)
|
293
|
+
assert_equal '10.01%', percentage(10.01)
|
294
|
+
assert_equal '99.99%', percentage(99.99)
|
295
|
+
assert_equal '100%', percentage(100)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Cyril David
|
@@ -14,13 +14,26 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-27 00:00:00 +08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: sinatra
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 0
|
30
|
+
version: "1.0"
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: contest
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
24
37
|
requirements:
|
25
38
|
- - ">="
|
26
39
|
- !ruby/object:Gem::Version
|
@@ -28,7 +41,67 @@ dependencies:
|
|
28
41
|
- 0
|
29
42
|
version: "0"
|
30
43
|
type: :development
|
31
|
-
version_requirements: *
|
44
|
+
version_requirements: *id002
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: mocha
|
47
|
+
prerelease: false
|
48
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
segments:
|
53
|
+
- 0
|
54
|
+
version: "0"
|
55
|
+
type: :development
|
56
|
+
version_requirements: *id003
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: rack-test
|
59
|
+
prerelease: false
|
60
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id004
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: nokogiri
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
type: :development
|
80
|
+
version_requirements: *id005
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: ohm
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
type: :development
|
92
|
+
version_requirements: *id006
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: haml
|
95
|
+
prerelease: false
|
96
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
segments:
|
101
|
+
- 0
|
102
|
+
version: "0"
|
103
|
+
type: :development
|
104
|
+
version_requirements: *id007
|
32
105
|
description: Includes month_choices, year_choices, country_choices
|
33
106
|
email: cyx.ucron@gmail.com
|
34
107
|
executables: []
|
@@ -37,12 +110,12 @@ extensions: []
|
|
37
110
|
|
38
111
|
extra_rdoc_files:
|
39
112
|
- LICENSE
|
40
|
-
- README.
|
113
|
+
- README.markdown
|
41
114
|
files:
|
42
115
|
- .document
|
43
116
|
- .gitignore
|
44
117
|
- LICENSE
|
45
|
-
- README.
|
118
|
+
- README.markdown
|
46
119
|
- Rakefile
|
47
120
|
- VERSION
|
48
121
|
- lib/sinatra/helpers.rb
|
@@ -51,6 +124,8 @@ files:
|
|
51
124
|
- lib/sinatra/helpers/haml_error_presenter.rb
|
52
125
|
- sinatra-helpers.gemspec
|
53
126
|
- test/helper.rb
|
127
|
+
- test/test_country.rb
|
128
|
+
- test/test_sinatra_helpers.rb
|
54
129
|
has_rdoc: true
|
55
130
|
homepage: http://github.com/sinefunc/sinatra-helpers
|
56
131
|
licenses: []
|
@@ -83,3 +158,5 @@ specification_version: 3
|
|
83
158
|
summary: Some generic helpers for the view layer
|
84
159
|
test_files:
|
85
160
|
- test/helper.rb
|
161
|
+
- test/test_country.rb
|
162
|
+
- test/test_sinatra_helpers.rb
|
data/README.rdoc
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
= sinatra-helpers
|
2
|
-
|
3
|
-
Bare minimum, close to the metal helpers for your average sinatra application.
|
4
|
-
|
5
|
-
== Examples
|
6
|
-
|
7
|
-
%select(name='card[month'])
|
8
|
-
!= month_choices
|
9
|
-
|
10
|
-
%select(name='card[year'])
|
11
|
-
!= year_choices
|
12
|
-
|
13
|
-
%select(name='address[country]')
|
14
|
-
!= country_choices
|
15
|
-
|
16
|
-
# If you have an ohm model which you want to present the errors of:
|
17
|
-
# (this is taken from the reddit-clone courtesy of citrusbyte)
|
18
|
-
|
19
|
-
# This should be put in your HAML file
|
20
|
-
|
21
|
-
- errors_on @user do |e|
|
22
|
-
- e.on [:email, :not_present] "You must supply an email address"
|
23
|
-
- e.on [:password, :not_present] "A password is required"
|
24
|
-
- e.on [:password, :not_confirmed] "You must confirm your password"
|
25
|
-
|
26
|
-
== Note on Patches/Pull Requests
|
27
|
-
|
28
|
-
* Fork the project.
|
29
|
-
* Make your feature addition or bug fix.
|
30
|
-
* Add tests for it. This is important so I don't break it in a
|
31
|
-
future version unintentionally.
|
32
|
-
* Commit, do not mess with rakefile, version, or history.
|
33
|
-
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
34
|
-
* Send me a pull request. Bonus points for topic branches.
|
35
|
-
|
36
|
-
== Copyright
|
37
|
-
|
38
|
-
Copyright (c) 2010 Cyril David. See LICENSE for details.
|