sinatra-helpers 0.1.1 → 0.2.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/.gitignore CHANGED
@@ -19,3 +19,6 @@ rdoc
19
19
  pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
+ /.yardoc
23
+ /doc
24
+ /.rvmrc
@@ -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.1
1
+ 0.2.0
@@ -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
- def month_choices
14
- Date::MONTHNAMES.map.
15
- with_index { |month, idx| ["%d - %s" % [idx, month], idx] }.
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
- def year_choices(loffset = -20, uoffset = +20)
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 => "&pound;") == "&pound; 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, '&pound;'
198
+ # set :default_currency_precision, 3
199
+ # set :default_currency_separator, ' '
200
+ #
201
+ # currency(100) == "&pound; 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("") { |a, (k, v)|
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
- %(<#{ tag } #{ tag_atts }>#{ content }</#{ tag }>)
251
+ def escape_attr(str)
252
+ str.to_s.gsub("'", "&#39;").gsub('"', "&quot;")
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
- class Country
6
- LOOKUP = {
5
+ # A simple module containing all countries as of 2010.
6
+ module Country
7
+ @all = {
7
8
  :AF => "Afghanistan",
8
- :AX => "Aland Islands",
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
- :VG => "British Virgin Islands",
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 - Brazzaville",
60
- :CD => "Congo - Kinshasa",
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
- :QU => "European Union",
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-Bissau",
99
+ :GW => "Guinea-bissau",
106
100
  :GY => "Guyana",
107
101
  :HT => "Haiti",
108
- :HM => "Heard Island and McDonald Islands",
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 => "Laos",
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 => "Libya",
132
+ :LY => "Libyan Arab Jamahiriya",
138
133
  :LI => "Liechtenstein",
139
134
  :LT => "Lithuania",
140
135
  :LU => "Luxembourg",
141
- :MO => "Macau",
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
- :MI => "Midway Islands",
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 => "Reunion",
187
+ :RE => "RÉunion",
202
188
  :RO => "Romania",
203
- :RU => "Russia",
189
+ :RU => "Russian Federation",
204
190
  :RW => "Rwanda",
205
- :BL => "Saint Barthélemy",
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 => "Syria",
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 => "Vietnam",
267
- :WK => "Wake Island",
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
- def self.random_code
276
- @to_a ||= LOOKUP.to_a
277
- @to_a[rand(@to_a.size)].first
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
- def self.to_select
281
- LOOKUP.map { |code, name| [name, code] }
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
- def self.[](code)
285
- LOOKUP[code.to_sym] if not code.to_s.empty?
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
- # Taken from http://github.com/citrusbyte/reddit-clone
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
@@ -5,22 +5,22 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{sinatra-helpers}
8
- s.version = "0.1.1"
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-06}
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.rdoc"
17
+ "README.markdown"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
21
  ".gitignore",
22
22
  "LICENSE",
23
- "README.rdoc",
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
 
@@ -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-helpers'
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 "&lt;Foo&gt;", h("<Foo>")
10
+ assert_equal "&lt;Foo bar=&#39;baz&#39;&gt;", h("<Foo bar='baz'>")
11
+ assert_equal "&lt;Foo bar=&quot;baz&quot;&gt;", 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 &#39;bar&#39;" ' +
188
+ 'style="display:&quot;none&quot;">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 "&pound; 10.0", currency(10, :unit => "&pound;", :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
- - 1
8
- - 1
9
- version: 0.1.1
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-06 00:00:00 +08:00
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: contest
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: *id001
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.rdoc
113
+ - README.markdown
41
114
  files:
42
115
  - .document
43
116
  - .gitignore
44
117
  - LICENSE
45
- - README.rdoc
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
@@ -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.