actionpack 1.5.0 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

@@ -8,10 +8,10 @@ module ActionView
8
8
  # The following is an example of a complete form for a person object that works for both creates and updates built
9
9
  # with all the form helpers. The <tt>@person</tt> object was assigned by an action on the controller:
10
10
  # <form action="save_person" method="post">
11
- # Name:
11
+ # Name:
12
12
  # <%= text_field "person", "name", "size" => 20 %>
13
13
  #
14
- # Password:
14
+ # Password:
15
15
  # <%= password_field "person", "password", "maxsize" => 20 %>
16
16
  #
17
17
  # Single?:
@@ -26,12 +26,12 @@ module ActionView
26
26
  # ...is compiled to:
27
27
  #
28
28
  # <form action="save_person" method="post">
29
- # Name:
30
- # <input type="text" id="person_name" name="person[name]"
29
+ # Name:
30
+ # <input type="text" id="person_name" name="person[name]"
31
31
  # size="20" value="<%= @person.name %>" />
32
32
  #
33
- # Password:
34
- # <input type="password" id="person_password" name="person[password]"
33
+ # Password:
34
+ # <input type="password" id="person_password" name="person[password]"
35
35
  # size="20" maxsize="20" value="<%= @person.password %>" />
36
36
  #
37
37
  # Single?:
@@ -43,7 +43,15 @@ module ActionView
43
43
  # </textarea>
44
44
  #
45
45
  # <input type="submit" value="Save">
46
- # </form>
46
+ # </form>
47
+ #
48
+ # If the object name contains square brackets the id for the object will be inserted. Example:
49
+ #
50
+ # <%= textfield "person[]", "name" %>
51
+ #
52
+ # ...becomes:
53
+ #
54
+ # <input type="text" id="person_<%= @person.id %>_name" name="person[<%= @person.id %>][name]" value="<%= @person.name %>" />
47
55
  #
48
56
  # If the helper is being used to generate a repetitive sequence of similar form elements, for example in a partial
49
57
  # used by render_collection_of_partials, the "index" option may come in handy. Example:
@@ -51,10 +59,10 @@ module ActionView
51
59
  # <%= text_field "person", "name", "index" => 1 %>
52
60
  #
53
61
  # becomes
54
- #
62
+ #
55
63
  # <input type="text" id="person_1_name" name="person[1][name]" value="<%= @person.name %>" />
56
64
  #
57
- # There's also methods for helping to build form tags in link:classes/ActionView/Helpers/FormOptionsHelper.html,
65
+ # There's also methods for helping to build form tags in link:classes/ActionView/Helpers/FormOptionsHelper.html,
58
66
  # link:classes/ActionView/Helpers/DateHelper.html, and link:classes/ActionView/Helpers/ActiveRecordHelper.html
59
67
  module FormHelper
60
68
  # Returns an input tag of the "text" type tailored for accessing a specified attribute (identified by +method+) on an object
@@ -64,7 +72,7 @@ module ActionView
64
72
  # Examples (call, result):
65
73
  # text_field("post", "title", "size" => 20)
66
74
  # <input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" />
67
- def text_field(object, method, options = {})
75
+ def text_field(object, method, options = {})
68
76
  InstanceTag.new(object, method, self).to_input_field_tag("text", options)
69
77
  end
70
78
 
@@ -95,12 +103,12 @@ module ActionView
95
103
  def text_area(object, method, options = {})
96
104
  InstanceTag.new(object, method, self).to_text_area_tag(options)
97
105
  end
98
-
106
+
99
107
  # Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+) on an object
100
108
  # assigned to the template (identified by +object+). It's intended that +method+ returns an integer and if that
101
109
  # integer is above zero, then the checkbox is checked. Additional options on the input tag can be passed as a
102
110
  # hash with +options+. The +checked_value+ defaults to 1 while the default +unchecked_value+
103
- # is set to 0 which is convenient for boolean values. Usually unchecked checkboxes don't post anything.
111
+ # is set to 0 which is convenient for boolean values. Usually unchecked checkboxes don't post anything.
104
112
  # We work around this problem by adding a hidden value with the same name as the checkbox.
105
113
  #
106
114
  # Example (call, result). Imagine that @post.validated? returns 1:
@@ -119,13 +127,13 @@ module ActionView
119
127
  # Returns a radio button tag for accessing a specified attribute (identified by +method+) on an object
120
128
  # assigned to the template (identified by +object+). If the current value of +method+ is +tag_value+ the
121
129
  # radio button will be checked. Additional options on the input tag can be passed as a
122
- # hash with +options+.
130
+ # hash with +options+.
123
131
  # Example (call, result). Imagine that @post.category returns "rails":
124
132
  # radio_button("post", "category", "rails")
125
133
  # radio_button("post", "category", "java")
126
134
  # <input type="radio" id="post_category" name="post[category] value="rails" checked="checked" />
127
135
  # <input type="radio" id="post_category" name="post[category] value="java" />
128
- #
136
+ #
129
137
  def radio_button(object, method, tag_value, options = {})
130
138
  InstanceTag.new(object, method, self).to_radio_button_tag(tag_value, options)
131
139
  end
@@ -135,9 +143,10 @@ module ActionView
135
143
  include Helpers::TagHelper
136
144
 
137
145
  attr_reader :method_name, :object_name
138
-
139
- DEFAULT_FIELD_OPTIONS = { "size" => 30 } unless const_defined?("DEFAULT_FIELD_OPTIONS")
140
- DEFAULT_TEXT_AREA_OPTIONS = { "wrap" => "virtual", "cols" => 40, "rows" => 20 } unless const_defined?("DEFAULT_TEXT_AREA_OPTIONS")
146
+
147
+ DEFAULT_FIELD_OPTIONS = { "size" => 30 }.freeze unless const_defined?(:DEFAULT_FIELD_OPTIONS)
148
+ DEFAULT_TEXT_AREA_OPTIONS = { "wrap" => "virtual", "cols" => 40, "rows" => 20 }.freeze unless const_defined?(:DEFAULT_TEXT_AREA_OPTIONS)
149
+ DEFAULT_DATE_OPTIONS = { :discard_type => true }.freeze unless const_defined?(:DEFAULT_DATE_OPTIONS)
141
150
 
142
151
  def initialize(object_name, method_name, template_object, local_binding = nil)
143
152
  @object_name, @method_name = object_name, method_name
@@ -146,50 +155,69 @@ module ActionView
146
155
  @auto_index = @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}").id
147
156
  end
148
157
  end
149
-
158
+
150
159
  def to_input_field_tag(field_type, options = {})
151
- html_options = DEFAULT_FIELD_OPTIONS.merge(options)
152
- html_options.merge!({ "size" => options["maxlength"]}) if options["maxlength"] && !options["size"]
153
- html_options.delete("size") if field_type == "hidden"
154
- html_options.merge!({ "type" => field_type})
155
- html_options.merge!({ "value" => value_before_type_cast }) if options["value"].nil? && field_type != "file"
156
- add_default_name_and_id(html_options)
157
- tag("input", html_options)
158
- end
159
-
160
- def to_radio_button_tag(tag_value, options={})
161
- html_options = DEFAULT_FIELD_OPTIONS.merge(options)
162
- html_options.merge!({ "checked" => "checked" }) if value == tag_value
163
- html_options.merge!({ "type" => "radio", "value"=> tag_value.to_s })
164
-
165
- add_default_name_and_id(html_options)
166
- tag("input", html_options)
167
- end
168
-
160
+ options = options.stringify_keys
161
+ if field_type == "hidden"
162
+ options.delete("size")
163
+ else
164
+ options["size"] ||= options["maxlength"] || DEFAULT_FIELD_OPTIONS["size"]
165
+ end
166
+ options["type"] = field_type
167
+ options["value"] ||= value_before_type_cast unless field_type == "file"
168
+ add_default_name_and_id(options)
169
+ tag("input", options)
170
+ end
171
+
172
+ def to_radio_button_tag(tag_value, options = {})
173
+ options = DEFAULT_FIELD_OPTIONS.merge(options.stringify_keys)
174
+ options["type"] = "radio"
175
+ options["value"] = tag_value
176
+ options["checked"] = "checked" if value == tag_value
177
+ add_default_name_and_id(options)
178
+ tag("input", options)
179
+ end
180
+
169
181
  def to_text_area_tag(options = {})
170
- options = DEFAULT_TEXT_AREA_OPTIONS.merge(options)
182
+ options = DEFAULT_TEXT_AREA_OPTIONS.merge(options.stringify_keys)
171
183
  add_default_name_and_id(options)
172
184
  content_tag("textarea", html_escape(value_before_type_cast), options)
173
185
  end
174
186
 
175
187
  def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0")
176
- options.merge!({ "checked" => "checked" }) if !value.nil? && ((value.is_a?(TrueClass) || value.is_a?(FalseClass)) ? value : value.to_i > 0)
177
- options.merge!({ "type" => "checkbox", "value" => checked_value })
188
+ options = options.stringify_keys
189
+ options["type"] = "checkbox"
190
+ options["value"] = checked_value
191
+ checked = case value
192
+ when TrueClass, FalseClass
193
+ value
194
+ when NilClass
195
+ false
196
+ when Integer
197
+ value != 0
198
+ else
199
+ value.to_i != 0
200
+ end
201
+ if checked
202
+ options["checked"] = "checked"
203
+ else
204
+ options.delete("checked")
205
+ end
178
206
  add_default_name_and_id(options)
179
- tag("input", options) << tag("input", ({ "name" => options['name'], "type" => "hidden", "value" => unchecked_value }))
207
+ tag("input", options) << tag("input", "name" => options["name"], "type" => "hidden", "value" => unchecked_value)
180
208
  end
181
209
 
182
210
  def to_date_tag()
183
- defaults = { "discard_type" => true }
211
+ defaults = DEFAULT_DATE_OPTIONS.dup
184
212
  date = value || Date.today
185
- options = Proc.new { |position| defaults.update({ :prefix => "#{@object_name}[#{@method_name}(#{position}i)]" }) }
186
-
213
+ options = Proc.new { |position| defaults.merge(:prefix => "#{@object_name}[#{@method_name}(#{position}i)]") }
187
214
  html_day_select(date, options.call(3)) +
188
- html_month_select(date, options.call(2)) +
215
+ html_month_select(date, options.call(2)) +
189
216
  html_year_select(date, options.call(1))
190
217
  end
191
218
 
192
219
  def to_boolean_select_tag(options = {})
220
+ options = options.stringify_keys
193
221
  add_default_name_and_id(options)
194
222
  tag_text = "<select"
195
223
  tag_text << tag_options(options)
@@ -210,7 +238,7 @@ module ActionView
210
238
 
211
239
  def value_before_type_cast
212
240
  unless object.nil?
213
- object.respond_to?(@method_name + "_before_type_cast") ?
241
+ object.respond_to?(@method_name + "_before_type_cast") ?
214
242
  object.send(@method_name + "_before_type_cast") :
215
243
  object.send(@method_name)
216
244
  end
@@ -218,23 +246,23 @@ module ActionView
218
246
 
219
247
  private
220
248
  def add_default_name_and_id(options)
221
- if options.has_key? "index"
222
- options['name'] = tag_name_with_index(options["index"]) unless options.has_key? "name"
223
- options['id'] = tag_id_with_index(options["index"]) unless options.has_key? "id"
249
+ if options.has_key?("index")
250
+ options["name"] ||= tag_name_with_index(options["index"])
251
+ options["id"] ||= tag_id_with_index(options["index"])
224
252
  options.delete("index")
225
253
  elsif @auto_index
226
- options['name'] = tag_name_with_index(@auto_index) unless options.has_key? "name"
227
- options['id'] = tag_id_with_index(@auto_index) unless options.has_key? "id"
254
+ options["name"] ||= tag_name_with_index(@auto_index)
255
+ options["id"] ||= tag_id_with_index(@auto_index)
228
256
  else
229
- options['name'] = tag_name unless options.has_key? "name"
230
- options['id'] = tag_id unless options.has_key? "id"
257
+ options["name"] ||= tag_name
258
+ options["id"] ||= tag_id
231
259
  end
232
260
  end
233
-
261
+
234
262
  def tag_name
235
263
  "#{@object_name}[#{@method_name}]"
236
264
  end
237
-
265
+
238
266
  def tag_name_with_index(index)
239
267
  "#{@object_name}[#{index}][#{@method_name}]"
240
268
  end
@@ -25,7 +25,7 @@ module ActionView
25
25
 
26
26
  # Create a select tag and a series of contained option tags for the provided object and method.
27
27
  # The option currently held by the object will be selected, provided that the object is available.
28
- #
28
+ #
29
29
  # This can be used to provide a default set of options in the standard way: before rendering the create form, a
30
30
  # new model instance is assigned the default options and bound to @model_name. Usually this model is not saved
31
31
  # to the database. Instead, a second model object is created when the create request is received.
@@ -34,17 +34,17 @@ module ActionView
34
34
  def select(object, method, choices, options = {}, html_options = {})
35
35
  InstanceTag.new(object, method, self).to_select_tag(choices, options, html_options)
36
36
  end
37
-
37
+
38
38
  # Return select and option tags for the given object and method using options_from_collection_for_select to generate the list of option tags.
39
39
  def collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
40
40
  InstanceTag.new(object, method, self).to_collection_select_tag(collection, value_method, text_method, options, html_options)
41
41
  end
42
-
42
+
43
43
  # Return select and option tags for the given object and method, using country_options_for_select to generate the list of option tags.
44
44
  def country_select(object, method, priority_countries = nil, options = {}, html_options = {})
45
45
  InstanceTag.new(object, method, self).to_country_select_tag(priority_countries, options, html_options)
46
46
  end
47
-
47
+
48
48
  # Return select and option tags for the given object and method, using
49
49
  # #time_zone_options_for_select to generate the list of option tags.
50
50
  #
@@ -57,11 +57,11 @@ module ActionView
57
57
  InstanceTag.new(object, method, self).to_time_zone_select_tag(priority_zones, options, html_options)
58
58
  end
59
59
 
60
- # Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container
60
+ # Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container
61
61
  # where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and
62
62
  # the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values
63
63
  # become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag. +Selected+
64
- # may also be an array of values to be selected when using a multiple select.
64
+ # may also be an array of values to be selected when using a multiple select.
65
65
  #
66
66
  # Examples (call, result):
67
67
  # options_for_select([["Dollar", "$"], ["Kroner", "DKK"]])
@@ -79,8 +79,8 @@ module ActionView
79
79
  # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.
80
80
  def options_for_select(container, selected = nil)
81
81
  container = container.to_a if Hash === container
82
-
83
- options_for_select = container.inject([]) do |options, element|
82
+
83
+ options_for_select = container.inject([]) do |options, element|
84
84
  if element.respond_to?(:first) && element.respond_to?(:last)
85
85
  is_selected = ( (selected.respond_to?(:include?) ? selected.include?(element.last) : element.last == selected) )
86
86
  if is_selected
@@ -93,11 +93,11 @@ module ActionView
93
93
  options << ((is_selected) ? "<option selected=\"selected\">#{html_escape(element.to_s)}</option>" : "<option>#{html_escape(element.to_s)}</option>")
94
94
  end
95
95
  end
96
-
96
+
97
97
  options_for_select.join("\n")
98
98
  end
99
99
 
100
- # Returns a string of option tags that has been compiled by iterating over the +collection+ and assigning the
100
+ # Returns a string of option tags that has been compiled by iterating over the +collection+ and assigning the
101
101
  # the result of a call to the +value_method+ as the option value and the +text_method+ as the option text.
102
102
  # If +selected_value+ is specified, the element returning a match on +value_method+ will get the selected option tag.
103
103
  #
@@ -108,7 +108,7 @@ module ActionView
108
108
  # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.
109
109
  def options_from_collection_for_select(collection, value_method, text_method, selected_value = nil)
110
110
  options_for_select(
111
- collection.inject([]) { |options, object| options << [ object.send(text_method), object.send(value_method) ] },
111
+ collection.inject([]) { |options, object| options << [ object.send(text_method), object.send(value_method) ] },
112
112
  selected_value
113
113
  )
114
114
  end
@@ -135,18 +135,18 @@ module ActionView
135
135
  #
136
136
  # with objects of the following classes:
137
137
  # class Continent
138
- # def initialize(p_name, p_countries) @continent_name = p_name; @countries = p_countries; end
139
- # def continent_name() @continent_name; end
140
- # def countries() @countries; end
138
+ # def initialize(p_name, p_countries) @continent_name = p_name; @countries = p_countries; end
139
+ # def continent_name() @continent_name; end
140
+ # def countries() @countries; end
141
141
  # end
142
142
  # class Country
143
- # def initialize(id, name) @id = id; @name = name end
144
- # def country_id() @id; end
145
- # def country_name() @name; end
143
+ # def initialize(id, name) @id = id; @name = name end
144
+ # def country_id() @id; end
145
+ # def country_name() @name; end
146
146
  # end
147
147
  #
148
148
  # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.
149
- def option_groups_from_collection_for_select(collection, group_method, group_label_method,
149
+ def option_groups_from_collection_for_select(collection, group_method, group_label_method,
150
150
  option_key_method, option_value_method, selected_key = nil)
151
151
  collection.inject("") do |options_for_select, group|
152
152
  group_label_string = eval("group.#{group_label_method}")
@@ -154,16 +154,16 @@ module ActionView
154
154
  options_for_select += options_from_collection_for_select(eval("group.#{group_method}"), option_key_method, option_value_method, selected_key)
155
155
  options_for_select += '</optgroup>'
156
156
  end
157
- end
158
-
159
- # Returns a string of option tags for pretty much any country in the world. Supply a country name as +selected+ to
157
+ end
158
+
159
+ # Returns a string of option tags for pretty much any country in the world. Supply a country name as +selected+ to
160
160
  # have it marked as the selected option tag. You can also supply an array of countries as +priority_countries+, so
161
161
  # that they will be listed above the rest of the (long) list.
162
162
  #
163
163
  # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.
164
164
  def country_options_for_select(selected = nil, priority_countries = nil)
165
165
  country_options = ""
166
-
166
+
167
167
  if priority_countries
168
168
  country_options += options_for_select(priority_countries, selected)
169
169
  country_options += "<option>-------------</option>\n"
@@ -264,23 +264,27 @@ module ActionView
264
264
  include FormOptionsHelper
265
265
 
266
266
  def to_select_tag(choices, options, html_options)
267
+ html_options = html_options.stringify_keys
267
268
  add_default_name_and_id(html_options)
268
269
  content_tag("select", add_blank_option(options_for_select(choices, value), options[:include_blank]), html_options)
269
270
  end
270
271
 
271
272
  def to_collection_select_tag(collection, value_method, text_method, options, html_options)
273
+ html_options = html_options.stringify_keys
272
274
  add_default_name_and_id(html_options)
273
275
  content_tag(
274
276
  "select", add_blank_option(options_from_collection_for_select(collection, value_method, text_method, value), options[:include_blank]), html_options
275
277
  )
276
278
  end
277
-
279
+
278
280
  def to_country_select_tag(priority_countries, options, html_options)
281
+ html_options = html_options.stringify_keys
279
282
  add_default_name_and_id(html_options)
280
283
  content_tag("select", add_blank_option(country_options_for_select(value, priority_countries), options[:include_blank]), html_options)
281
284
  end
282
285
 
283
286
  def to_time_zone_select_tag(priority_zones, options, html_options)
287
+ html_options = html_options.stringify_keys
284
288
  add_default_name_and_id(html_options)
285
289
  content_tag("select",
286
290
  add_blank_option(
@@ -6,21 +6,20 @@ module ActionView
6
6
  # Provides a number of methods for creating form tags that doesn't rely on conventions with an object assigned to the template like
7
7
  # FormHelper does. With the FormTagHelper, you provide the names and values yourself.
8
8
  module FormTagHelper
9
- # Starts a form tag that points the action to an url configured with <tt>url_for_options</tt> just like
9
+ # Starts a form tag that points the action to an url configured with <tt>url_for_options</tt> just like
10
10
  # ActionController::Base#url_for. The method for the form defaults to POST.
11
11
  #
12
12
  # Options:
13
13
  # * <tt>:multipart</tt> - If set to true, the enctype is set to "multipart/form-data".
14
14
  def form_tag(url_for_options = {}, options = {}, *parameters_for_url)
15
- html_options = { "method" => "post" }.merge(options)
16
-
15
+ html_options = { "method" => "post" }.merge(options.stringify_keys)
16
+
17
17
  if html_options[:multipart]
18
18
  html_options["enctype"] = "multipart/form-data"
19
19
  html_options.delete(:multipart)
20
20
  end
21
-
21
+
22
22
  html_options["action"] = url_for(url_for_options, *parameters_for_url)
23
-
24
23
  tag("form", html_options, true)
25
24
  end
26
25
 
@@ -32,48 +31,49 @@ module ActionView
32
31
  end
33
32
 
34
33
  def select_tag(name, option_tags = nil, options = {})
35
- content_tag("select", option_tags, { "name" => name, "id" => name }.update(options))
34
+ content_tag("select", option_tags, { "name" => name, "id" => name }.update(options.stringify_keys))
36
35
  end
37
36
 
38
37
  def text_field_tag(name, value = nil, options = {})
39
- tag("input", {"type" => "text", "name" => name, "id" => name, "value" => value}.update(options))
38
+ tag("input", { "type" => "text", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys))
40
39
  end
41
40
 
42
41
  def hidden_field_tag(name, value = nil, options = {})
43
- text_field_tag(name, value, options.update("type" => "hidden"))
42
+ text_field_tag(name, value, options.stringify_keys.update("type" => "hidden"))
44
43
  end
45
44
 
46
45
  def file_field_tag(name, options = {})
47
- text_field_tag(name, nil, options.update("type" => "file"))
46
+ text_field_tag(name, nil, options.stringify_keys.update("type" => "file"))
48
47
  end
49
48
 
50
49
  def password_field_tag(name = "password", value = nil, options = {})
51
- text_field_tag(name, value, options.update("type" => "password"))
50
+ text_field_tag(name, value, options.stringify_keys.update("type" => "password"))
52
51
  end
53
52
 
54
53
  def text_area_tag(name, content = nil, options = {})
55
- if options[:size]
56
- options["cols"], options["rows"] = options[:size].split("x")
57
- options.delete(:size)
54
+ options = options.stringify_keys
55
+ if options["size"]
56
+ options["cols"], options["rows"] = options["size"].split("x")
57
+ options.delete("size")
58
58
  end
59
-
60
- content_tag("textarea", content, { "name" => name, "id" => name }.update(options))
59
+
60
+ content_tag("textarea", content, { "name" => name, "id" => name }.update(options.stringify_keys))
61
61
  end
62
62
 
63
63
  def check_box_tag(name, value = "1", checked = false, options = {})
64
- html_options = {"type" => "checkbox", "name" => name, "id" => name, "value" => value}.update(options)
64
+ html_options = { "type" => "checkbox", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys)
65
65
  html_options["checked"] = "checked" if checked
66
66
  tag("input", html_options)
67
67
  end
68
68
 
69
69
  def radio_button_tag(name, value, checked = false, options = {})
70
- html_options = {"type" => "radio", "name" => name, "id" => name, "value" => value}.update(options)
70
+ html_options = { "type" => "radio", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys)
71
71
  html_options["checked"] = "checked" if checked
72
72
  tag("input", html_options)
73
73
  end
74
74
 
75
75
  def submit_tag(value = "Save changes", options = {})
76
- tag("input", {"type" => "submit", "name" => "submit", "value" => value}.update(options))
76
+ tag("input", { "type" => "submit", "name" => "submit", "value" => value }.update(options.stringify_keys))
77
77
  end
78
78
  end
79
79
  end