Changeset 1006
- Timestamp:
- 11/15/07 20:22:02 (1 year ago)
- Files:
-
- plugins/merb_helpers/lib/form_helpers.rb (modified) (12 diffs)
- plugins/merb_helpers/specs/merb_helpers_spec.rb (modified) (12 diffs)
- plugins/merb_helpers/specs/spec_helper.rb (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
plugins/merb_helpers/lib/form_helpers.rb
r1002 r1006 1 module Merb 1 module Merb #:nodoc: 2 3 # Merb helpers include several helpers used for simplifying view creation. 4 # The available helpers currently include form tag helpers for both resource based and generic HTML form tag creation 2 5 module Helpers 6 # Provides a number of methods for creating form tags which may be used either with or without the presence of ORM specific models. 7 # There are two types of form helpers: those that specifically work with model attributes and those that don't. 8 # This helper deals with both model attributes and generic form tags. Model attributes generally end in "_control" such as +text_control+, 9 # and generic tags end with "_field", such as +text_field+ 10 # 11 # The core method of this helper, +form_for+, gives you the ability to create a form for a resource. 12 # For example, let's say that you have a model <tt>Person</tt> and want to create a new instance of it: 13 # 14 # <% form_for :person, :action => url(:people) do %> 15 # <%= text_control :first_name, :label => 'First Name' %> 16 # <%= text_control :last_name, :label => 'Last Name' %> 17 # <%= submit_button 'Create' %> 18 # <% end %> 19 # 20 # The HTML generated for this would be: 21 # 22 # <form action="/people/create" method="post"> 23 # <input id="person_first_name" name="person[first_name]" size="30" type="text" /> 24 # <input id="person_last_name" name="person[last_name]" size="30" type="text" /> 25 # <input name="commit" type="submit" value="Create" /> 26 # </form> 27 # 28 # You may also create a normal form using form_tag 29 # <% form_tag({url(:controller => "foo", :action => "bar", :id => 1)} do %> 30 # <%= text_field :name => 'first_name', :label => 'First Name' %> 31 # <%= submit_button 'Create' %> 32 # <% end %> 33 # 34 # The HTML generated for this would be: 35 # 36 # <form action="/foo/bar/1" method="post"> 37 # <input id="first_name" name="first_name" size="30" type="text" /> 38 # <input name="commit" type="submit" value="Create" /> 39 # </form> 3 40 module Form 4 41 42 # Provides a HTML formatted display of resource errors in an unordered list with a h2 form submission error 43 # ==== Options 44 # +html_class+:: Set for custom error div class default is <tt>submittal_failed<tt> 45 # 46 # ==== Example 47 # 48 # <%= error_messages_for :person %> 5 49 def error_messages_for(obj, error_li = nil, html_class='submittal_failed') 6 50 return "" if obj.errors.empty? … … 18 62 end 19 63 20 def obj_from_ivar_or_sym(obj) 64 def obj_from_ivar_or_sym(obj) #:nodoc: 21 65 obj.is_a?(Symbol) ? instance_variable_get("@#{obj}") : obj 22 66 end 23 24 def tag(tag_name, contents, attrs = {}) 25 open_tag(tag_name, attrs) + contents + "</#{tag_name}>" 26 end 27 67 68 # Creates a generic HTML tag 69 def tag(tag_name, contents, attrs = {}) #:nodoc: 70 open_tag(tag_name, attrs) + contents.to_s + "</#{tag_name}>" 71 end 72 73 # Generates a form tag, which accepts a block that is not directly based on resource attributes 74 # 75 # <% form_tag({url(:controller => "foo", :action => "bar", :id => 1)} do %> 76 # <%= text_field :name => 'first_name', :label => 'First Name' %> 77 # <%= submit_button 'Create' %> 78 # <% end %> 79 # 80 # The HTML generated for this would be: 81 # 82 # <form action="/foo/bar/1" method="post"> 83 # <input id="first_name" name="first_name" size="30" type="text" /> 84 # <input name="commit" type="submit" value="Create" /> 85 # </form> 28 86 def form_tag(attrs = {}, &block) 29 87 attrs.merge!( :enctype => "multipart/form-data" ) if attrs.delete(:multipart) … … 35 93 end 36 94 95 # Generates a resource specific form tag which accepts a block, this also provides automatic resource routing. 96 # <% form_for :person, :action => url(:people) do %> 97 # <%= text_control :first_name, :label => 'First Name' %> 98 # <%= text_control :last_name, :label => 'Last Name' %> 99 # <%= submit_button 'Create' %> 100 # <% end %> 101 # 102 # The HTML generated for this would be: 103 # 104 # <form action="/people/create" method="post"> 105 # <input id="person_first_name" name="person[first_name]" size="30" type="text" /> 106 # <input id="person_last_name" name="person[last_name]" size="30" type="text" /> 107 # <input name="commit" type="submit" value="Create" /> 108 # </form> 37 109 def form_for(obj, attrs={}, &block) 38 110 obj = obj_from_ivar_or_sym(obj) … … 44 116 end 45 117 118 # Creates a scope around a specific resource object like form_for, but doesnt create the form tags themselves. 119 # This makes fields_for suitable for specifying additional resource objects in the same form. 120 # 121 # ==== Examples 122 # 123 # <% form_for :person, :action => url(:people) do %> 124 # <%= text_control :first_name, :label => 'First Name' %> 125 # <%= text_control :last_name, :label => 'Last Name' %> 126 # <% fields_for :permission do %> 127 # <%= checkbox_control :is_admin, :label => 'Administrator' %> 128 # <% end %> 129 # <%= submit_button 'Create' %> 130 # <% end %> 46 131 def fields_for(obj, attrs=nil, &block) 47 132 obj = obj_from_ivar_or_sym(obj) … … 55 140 end 56 141 57 def control_name(col) 142 def control_name(col) #:nodoc: 58 143 "#{@_object_name}[#{col}]" 59 144 end 60 145 61 def control_value(col) 146 def control_id(col) #:nodoc: 147 "#{@_object_name}_#{col}" 148 end 149 150 def control_value(col) #:nodoc: 62 151 @_obj.send(col) 63 152 end 64 153 65 def control_name_value(col, attrs) 154 def control_name_value(col, attrs) #:nodoc: 66 155 {:name => control_name(col), :value => control_value(col)}.merge(attrs) 67 156 end 68 157 158 # Provides a HTML text input tag based on a resource attribute. 159 # 160 # ==== Example 161 # <% form_for :person, :action => url(:people) do %> 162 # <%= text_control :first_name, :label => 'First Name' %> 163 # <% end %> 69 164 def text_control(col, attrs = {}) 70 165 errorify_field(attrs, col) … … 72 167 end 73 168 169 # Provides a generic HTML text input tag 170 # Provides a HTML text input tag based on a resource attribute. 171 # 172 # ==== Example 173 # <%= text_field :fav_color, :label => 'Your Favorite Color' %> 174 # => <label for="fav_color">Your Favorite Color</label><input type="text" name="fav_color" id="fav_color"/> 74 175 def text_field(attrs = {}) 75 176 attrs.merge!(:type => "text") … … 77 178 end 78 179 180 # Provides a HTML password input based on a resource attribute. 181 # This is generally used within a resource block such as +form_for+ 182 # ==== Example 183 # <%= password_control :password, :label => 'New Password' %> 79 184 def password_control(col, attrs = {}) 80 185 attrs.merge!(:name => control_name(col)) … … 91 196 # translate column values from the db to boolean 92 197 # nil, false, 0 and '0' are false. All others are true 93 def col_val_to_bool(val) 198 def col_val_to_bool(val) #:nodoc: 94 199 !(val == "0" || val == 0 || !val) 95 200 end … … 111 216 end 112 217 218 # Returns a hidden input tag tailored for accessing a specified attribute (identified by +col+) on an object 219 # resource within a +form_for+ resource block. Additional options on the input tag can be passed as a 220 # hash with +attrs+. These options will be tagged onto the HTML as an HTML element attribute as in the example 221 # shown. 222 # 223 # ==== Examples 224 # 225 # <%= hidden_control :identifier %> 226 # # => <input id="person_identifier" name="person[identifier]" type="hidden" value="#{@person.identifier}" /> 227 # 113 228 def hidden_control(col, attrs = {}) 114 229 attrs.delete(:label) … … 165 280 tag("label", name.to_s + contents, attrs) 166 281 end 167 282 283 def select_field(attrs = {}) 284 collection = attrs.delete(:collection) 285 option_attrs = { 286 :prompt => attrs.delete(:prompt), 287 :selected => attrs.delete(:selected), 288 :include_blank => attrs.delete(:include_blank), 289 :text_method => attrs.delete(:text_method), 290 :value_method => attrs.delete(:value_method) 291 } 292 optional_label(attrs) { open_tag('select', attrs) + options_for_select(collection, option_attrs) + "</select>"} 293 end 294 295 def select_control(col, attrs = {}) 296 attrs.merge!(:name => attrs[:name] || control_name(col)) 297 attrs.merge!(:id => attrs[:id] || control_id(col)) 298 errorify_field(attrs, col) 299 optional_label(attrs) { select_field(attrs) } 300 end 301 302 # Accepts a collection (hash, array, enumerable, your type) and returns a string of option tags. 303 # Given a collection where the elements respond to first and last (such as a two-element array), 304 # the "lasts" serve as option values and the "firsts" as option text. Hashes are turned into 305 # this form automatically, so the keys become "firsts" and values become lasts. If selected is 306 # specified, the matching "last" or element will get the selected option-tag. Selected may also 307 # be an array of values to be selected when using a multiple select. 308 # 309 # ==== Examples 310 # <%= options_for_select( [['apple','Apple Pie'],['orange','Orange Juice']], :selected => 'orange' ) 311 # => <option value="apple">Apple Pie</option><option value="orange" selected="selected">Orange Juice</option> 312 # 313 # <%= options_for_select( [['apple','Apple Pie'],['orange','Orange Juice']], :selected => ['orange','apple'], :prompt => 'Select One' ) 314 # => <option value="">Select One</option><option value="apple" selected="selected">Apple Pie</option><option value="orange" selected="selected">Orange Juice</option> 315 # 316 # ==== Options 317 # +selected+:: The value of a selected object, may be either a string or an array. 318 # +prompt+:: Adds an addtional option tag with the provided string with no value. 319 # +include_blank+:: Adds an additional blank option tag with no value. 320 def options_for_select(collection, attrs = {}) 321 prompt = attrs.delete(:prompt) 322 blank = attrs.delete(:include_blank) 323 selected = attrs.delete(:selected) 324 returning '' do |ret| 325 ret << tag('option', prompt, :value => '') if prompt 326 ret << tag("option", '', :value => '') if blank 327 unless collection.blank? 328 if collection.is_a?(Hash) 329 collection.each do |label,group| 330 ret << open_tag("optgroup", :label => label.to_s.titleize) + options_for_select(group, :selected => selected) + "</optgroup>" 331 end 332 else 333 collection.each do |value,text| 334 options = selected.to_a.include?(value) ? {:selected => 'selected'} : {} 335 ret << tag( 'option', text, {:value => value}.merge(options) ) 336 end 337 end 338 end 339 end 340 end 341 342 # Returns a string of option tags that have been compiled by iterating over the collection and 343 # assigning the the result of a call to the value_method as the option value and the text_method 344 # as the option text. If selected_value is specified, the element returning a match on 345 # the value_method option will get the selected option tag. 346 # 347 # This method also also supports the automatic generation of optgroup tags by using a hash. 348 # ==== Examples 349 # If we had a collection of people within a @project object, and want to use 'id' as the value, and 'name' 350 # as the option content we could do something similar to this; 351 # 352 # <%= options_from_collection_for_select(@project.people, :text_method => "id", :value_method => "name") %> 353 # The iteration of the collection would create options in this manner; 354 # => <option value="#{person.id}">#{person.name}</option> 355 # 356 # <% @people = Person.find(:all).group_by( &:state ) 357 # <%= options_for_select(@people, :text_method => 'full_name', :value_method => 'id', :selected => 3) %> 358 # => <optgroup label="Washington"><option value="1">Josh Martin</option><option value="2">John Doe</option></optgroup> 359 # => <optgroup label="Idaho"><option value="3" selected="selected">Jane Doe</option> 360 # 361 # ==== Options 362 # +text_method+:: Defines the method which will be used to provide the text of the option tags (required) 363 # +value_method+:: Defines the method which will be used to provide the value of the option tags (required) 364 # +selected+:: The value of a selected object, may be either a string or an array. 365 def options_from_collection_for_select(collection, attrs = {}) 366 if collection.is_a?(Hash) 367 returning '' do |ret| 368 collection.each do |label, group| 369 ret << open_tag("optgroup", :label => label.to_s) + options_from_collection_for_select(group, attrs) + "</optgroup>" 370 end 371 end 372 else 373 text_method = attrs[:text_method] 374 value_method = attrs[:value_method] 375 selected_value = attrs[:selected] 376 options_for_select( 377 collection.inject([]) { |options, object| options << [ object.send(value_method), object.send(text_method) ] }, 378 :selected => selected_value 379 ) 380 end 381 end 382 383 # Provides the ability to create quick fieldsets as blocks for your forms. 384 # 385 # ==== Example 386 # <% fieldset :legend => 'Customer Options' do -%> 387 # ...your form elements 388 # <% end -%> 389 # 390 # => <fieldset><legend>Customer Options</legend>...your form elements</fieldset> 391 # 392 # ==== Options 393 # +legend+:: The name of this fieldset which will be provided in a HTML legend tag. 394 def fieldset(attrs = {}, &block) 395 legend = attrs.delete(:legend) 396 open_tag( 'fieldset', attrs ) + ( tag('legend', legend) if legend ) + yield + "</fieldset>" 397 end 398 168 399 ## file input control 169 400 def file_control(col, attrs = {}) … … 197 428 if label 198 429 title = label.is_a?(Hash) ? label.delete(:title) : label 199 label(title, yield, label.is_a?(Hash) ? label : {}) 430 named = attrs[:name].blank? ? {} : {:for => attrs[:name]} 431 label(title, '', label.is_a?(Hash) ? label : named) + yield 200 432 else 201 433 yield 202 434 end 203 end 435 end 204 436 205 437 def errorify_field(attrs, col) … … 211 443 end 212 444 213 class Merb::ViewContext 445 class Merb::ViewContext #:nodoc: 214 446 include Merb::Helpers::Form 215 447 end plugins/merb_helpers/specs/merb_helpers_spec.rb
r1002 r1006 162 162 end 163 163 164 it "should wrap the field in a label if the :label option is passed to the text_field" do164 it "should provide an additional label tag if the :label option is passed in" do 165 165 result = text_field(:label => "LABEL" ) 166 result.should match(/<label>LABEL< input type="text"\s*\/><\/label>/)166 result.should match(/<label>LABEL<\/label><input type="text"\s*\/>/) 167 167 end 168 168 end … … 183 183 end 184 184 185 it "should wrap the text_control in a labelif the :label option is passed in" do185 it "should provide an additional label tag if the :label option is passed in" do 186 186 form_for :obj do 187 187 _buffer << text_control(:foo, :label => "LABEL") 188 188 end 189 _buffer.should match(/<label >LABEL<input/)189 _buffer.should match(/<label.*>LABEL<\/label><input/) 190 190 res = _buffer.scan(/<[^>]*>/) 191 191 res[2].should_not match_tag(:input, :label => "LABEL") … … 200 200 end 201 201 202 it "should wrap the field in a label if the :label option is passed to the text_field" do202 it "should provide an additional label tag if the :label option is passed in" do 203 203 result = password_field(:label => "LABEL" ) 204 result.should match(/<label >LABEL<input type="password"\s*\/><\/label>/)204 result.should match(/<label.*>LABEL<\/label><input type="password"\s*\/>/) 205 205 end 206 206 end … … 221 221 end 222 222 223 it "should wrap the text_control in a labelif the :label option is passed in" do223 it "should provide an additional label tag if the :label option is passed in" do 224 224 form_for :obj do 225 225 _buffer << password_control(:foo, :label => "LABEL") 226 226 end 227 _buffer.should match(/<label >LABEL<input/)227 _buffer.should match(/<label.*>LABEL<\/label><input/) 228 228 res = _buffer.scan(/<[^>]*>/) 229 229 res[2].should_not match_tag(:input, :label => "LABEL") … … 236 236 end 237 237 238 it "should wrap the checkbox_field in a labelif the :label option is passed in" do238 it "should provide an additional label tag if the :label option is passed in" do 239 239 result = checkbox_field(:label => "LABEL" ) 240 result.should match(/<label>LABEL< input/)240 result.should match(/<label>LABEL<\/label><input/) 241 241 res = result.scan(/<[^>]*>/) 242 242 res[2].should_not match_tag(:input, :label => "LABEL") … … 280 280 end 281 281 282 it "should wrap the checkbox_control in a label if thelabel option is passed in" do282 it "should provide an additional label tag if the :label option is passed in" do 283 283 form_for :obj do 284 284 _buffer << checkbox_control(:foo, :label => "LABEL") 285 285 end 286 _buffer.should match( /<label >LABEL<input/ )286 _buffer.should match( /<label.*>LABEL<\/label><input/ ) 287 287 res = _buffer.scan(/<[^>]*>/) 288 288 res[2].should_not match_tag(:input, :label => "LABEL") … … 333 333 end 334 334 335 it "should render a label when the labelis passed in" do335 it "should provide an additional label tag if the :label option is passed in" do 336 336 result = radio_field(:name => "foo", :value => "bar", :label => "LABEL") 337 result.should match(/<label >LABEL<input/)337 result.should match(/<label.*>LABEL<\/label><input/) 338 338 res = result.scan(/<[^>]*>/) 339 339 res[2].should_not match_tag(:input, :label => "LABEL") … … 348 348 form_for :obj do 349 349 radio = radio_group_control(:foo, [:foowee, :baree]).scan(/<[^>]*>/) 350 radio[ 1].should match_tag(:input, :type => "radio", :name => "fake_model[foo]", :value => "foowee", :selected => "selected")351 radio[ 4].should match_tag(:input, :type => "radio", :name => "fake_model[foo]", :value => "baree")352 radio[ 2].should not_match_tag(:selected => "selected")353 end 354 end 355 356 it "should wrap the each radio button in the group in a label corresponding to the options" do350 radio[2].should match_tag(:input, :type => "radio", :name => "fake_model[foo]", :value => "foowee", :selected => "selected") 351 radio[5].should match_tag(:input, :type => "radio", :name => "fake_model[foo]", :value => "baree") 352 radio[3].should not_match_tag(:selected => "selected") 353 end 354 end 355 356 it "should provide an additional label tag if the :label option is passed in" do 357 357 form_for :obj do 358 358 radio = radio_group_control(:foo, [:foowee, :baree]) 359 radio.scan( /<label >(foowee|baree)<input/ ).size.should == 2359 radio.scan( /<label.*?>(foowee|baree)<\/label><input/ ).size.should == 2 360 360 radio = radio.scan(/<[^>]*>/) 361 361 radio[1].should_not match_tag(:input, :label => "LABEL") … … 380 380 it "should render a label when the label is passed in" do 381 381 result = text_area_field( "CONTENT", :name => "foo", :value => "bar", :label => "LABEL") 382 result.should match(/<label >LABEL<textarea/)382 result.should match(/<label.*>LABEL<\/label><textarea/) 383 383 res = result.scan(/<[^>]*>/) 384 384 res[1].should_not match_tag(:textarea, :label => "LABEL") … … 386 386 end 387 387 388 describe "text area (data bound)" do 389 it_should_behave_like "FakeBufferConsumer" 390 391 it "should return a bound text area" do 392 form_for :obj do 393 ta = text_area_control(:foo) 394 tab = text_area_control(:foobad) 395 ta.should match_tag(:textarea, :name => "fake_model[foo]") 396 tab.should match_tag(:textarea, :name => "fake_model[foobad]", :class => "error") 397 ta.should include("foowee") 398 end 399 end 400 401 it "should handle a nil content value" do 402 @obj.nothing.should be_nil 403 form_for :obj do 404 text_area_control(:nothing).should match_tag(:textarea, :name => "fake_model[nothing]") 405 end 406 end 407 408 it "should handle a nil attribute hash" do 409 form_for :obj do 410 text_area_control(:nothing, nil).should match_tag(:textarea, :name => "fake_model[nothing]") 411 end 412 end 413 414 it "should render a label when the label is passed in" do 415 form_for :obj do 416 result = text_area_control( :foo, :label => "LABEL") 417 result.should match(/<label>LABEL<textarea/) 418 res = result.scan(/<[^>]*>/) 419 res[1].should_not match_tag(:textarea, :label => "LABEL") 420 end 421 end 422 423 end 424 425 describe "form helper supporting methods for controls" do 426 it_should_behave_like "FakeBufferConsumer" 427 428 it "should give class_name[colname] for control_name" do 429 form_for :obj do 430 text_control( :foo ).should match_tag( :input, :type => "text", :name => "fake_model[foo]") 431 end 432 end 433 434 it "should provide value=method_value for the control_value method" do 435 form_for :obj do 436 text_control( :foo ).should match_tag( :input, :type => "text", :value => "foowee") 437 end 438 end 439 440 it "should give name and value for a call to control_name_value" do 441 form_for :obj do 442 control_name_value(:foo, :attribute => "ATTRIBUTE" ).should == { :name => "fake_model[foo]", 443 :value => "foowee", 444 :attribute => "ATTRIBUTE"} 445 end 446 end 447 end 448 449 describe "submit_button" do 450 it_should_behave_like "FakeBufferConsumer" 388 describe "select (data bound)" do 389 390 it_should_behave_like "FakeBufferConsumer" 391 392 it "should render the select tag with the correct id and name" do 393 form_for :obj do 394 content = select_control( :foo ) 395 content.should match_tag( :select, :id => "fake_model_foo", :name => "fake_model[foo]" ) 396 end 397 end 398 399 it "should include a blank option" do 400 form_for :obj do 401 content = select_control( :foo, :include_blank => true ) 402 content.should match_tag( :option, :value => '') 403 end 404 end 405 406 it "should render a prompt option without a value" do 407 form_for :obj do 408 content = select_control( :foo, :prompt => "Choose" ) 409 end 410 end 411 412 it "should render a select tag with options" do 413 form_for :obj do 414 content = select_control( :foo, :class => 'class1 class2', :title => 'This is the title' ) 415 content.should match_tag( :select, :class => "class1 class2", :title=> "This is the title" ) 416 end 417 end 418 419 it "should render a select tag with options and a blank option" do 420 form_for :obj do 421 content = select_control( :foo, :title => "TITLE", :include_blank => true ) 422 content.should match_tag( :select, :title => "TITLE" ) 423 content.should match_tag( :option, :value => '' ) 424 end 425 end 426 427 it "should render the text as the value if no text_method is specified" do 428 form_for :obj do 429 content = select_control( :foo, :collection => [FakeModel] ) 430 content.should match_tag( :option, :value => "FakeModel" ) 431 end 432 end 433 434 end 435 436 describe "option tag generation (data bound)" do 437 it_should_behave_like "FakeBufferConsumer" 438 439 it "should use text_method and value_method for tag generation" do 440 content = options_from_collection_for_select( [FakeModel.new, FakeModel2.new], :text_method => 'foo', :value_method => 'bar' ) 441 content.should match_tag( :option, :content => "foowee", :value => "7" ) 442 content.should match_tag( :option, :content => "foowee2", :value => "barbar" ) 443 end 444 445 it "should render a hash of arrays as a grouped select box" do 446 @model1 = FakeModel.new ; @model1.make = "Ford" ; @model1.model = "Mustang" ; @model1.vin = '1' 447 @model2 = FakeModel.new ; @model2.make = "Ford" ; @model2.model = "Falcon" ; @model2.vin = '2' 448 @model3 = FakeModel.new ; @model3.make = "Holden" ; @model3.model = "Commodore" ; @model3.vin = '3' 449 450 collection = [@model1, @model2, @model3].group_by( &:make ) 451 content = options_from_collection_for_select(collection, :text_method => 'model', :value_method => 'vin', :selected => '1') 451 452 452 it "should produce a simple submit button" do 453 submit_button("Foo").should == "<button type=\"submit\">Foo</button>" 454 end 455 end 456 457 describe "label helpers" do 458 it_should_behave_like "FakeBufferConsumer" 459 460 it "should add a label to arbitrary markup in a template" do 461 result = label("Name:", text_field(:name => "name_value")) 462 result.should == "<label>Name:<input type=\"text\" name=\"name_value\"/></label>" 453 content.should match_tag( :optgroup, :label => "Ford" ) 454 content.should match_tag( :option, :selected => "selected", :value => "1", :content => "Mustang" ) 455 content.should match_tag( :option, :value => "2", :content => "Falcon" ) 456 content.should match_tag( :optgroup, :label => "Holden" ) 457 content.should match_tag( :option, :value => "3", :content => "Commodore" ) 458 end 463 459 464 end 465 460 it "should humanize and titlize keys in the label for the option group" do 461 collection = { :some_snake_case_key => [FakeModel] } 462 form_for :obj do 463 content = select_control( :foo, :collection => collection ) 464 content.should match_tag( :optgroup, :label => "Some Snake Case Key" ) 465 end 466 end 467 468 469 end 470 471 describe "option tags generation (basic)" do 472 it_should_behave_like "FakeBufferConsumer" 473 474 before do 475 @collection = [['rabbit','Rabbit'],['horse','Horse'],['bird','Bird']] 476 end 477 478 it "should provide an option tag for each item in the collection" do 479 result = options_for_select( @collection ) 480 doc = Hpricot( result ) 481 (doc/"option").size.should == 3 482 end 483 484 it "should provide a blank option" do 485 content = options_for_select(@collection, :include_blank => true ) 486 content.should match_tag( :option, :value => '' ) 487 end 488 489 it "should provide a prompt option" do 490 content = options_for_select( [], :prompt => 'Choose' ) 491 content.should match_tag( :option, :value => '', :content => 'Choose' ) 492 end 493 494 it "should provide selected options by value" do 495 content = options_for_select( [['rabbit','Rabbit'],['chicken','Chicken']], :selected => 'rabbit' ) 496 content.should match_tag( :option, :value => 'rabbit', :selected => 'selected', :content => 'Rabbit' ) 497 content.should_not match_tag( :option, :value => 'chicken', :selected => nil, :content => 'Chicken' ) 498 end 499 500 it "should render a hash of options as optgroup" do 501 collection = { :fruit => [['orange','Orange'],['banana','Banana']], :vegatables => [['corn','Corn']]} 502 content = options_for_select(collection, :selected => 'banana') 503 content.should match_tag( :optgroup, :label => 'Fruit' ) 504 content.should match_tag( :optgroup, :label => 'Vegatables' ) 505 content.should match_tag( :option, :value => 'banana', :selected => 'selected', :content => 'Banana' ) 506 end 507 508 end 509 510 describe "fieldset generation (basic)" do 511 it_should_behave_like "FakeBufferConsumer" 512 513 it "should provide legend option" do 514 form_tag do 515 _buffer << "CONTENT" 516 end 517 _buffer.should match_tag(:form, :method => "post") 518 _buffer.should include("CONTENT") 519 end 466 520 end 467 521 … … 475 529 it "should wrap the field in a label if the :label option is passed to the file_field" do 476 530 result = file_field(:label => "LABEL" ) 477 result.should match(/<label>LABEL< input type="file"\s*\/><\/label>/)531 result.should match(/<label>LABEL<\/label><input type="file"\s*\/>/) 478 532 end 479 533 end … … 498 552 _buffer << text_control(:foo, :label => "LABEL") 499 553 end 500 _buffer.should match(/<label >LABEL<input/)554 _buffer.should match(/<label.*>LABEL<\/label><input/) 501 555 res = _buffer.scan(/<[^>]*>/) 502 556 res[2].should_not match_tag(:input, :label => "LABEL") plugins/merb_helpers/specs/spec_helper.rb
r746 r1006 6 6 7 7 class FakeModel 8 9 attr_accessor :vin, :make, :model 10 8 11 def self.columns 9 12 [FakeColumn.new(:foo, :string), 10 FakeColumn.new(:foobad, :string), 13 FakeColumn.new(:foobad, :string), 14 FakeColumn.new(:desc, :string), 11 15 FakeColumn.new(:bar, :integer), 12 16 FakeColumn.new(:barbad, :integer), … … 33 37 "foowee" 34 38 end 35 36 39 alias_method :foobad, :foo 37 40 … … 57 60 58 61 class FakeModel2 < FakeModel 59 62 60 63 def foo 61 64 "foowee2" 62 65 end 63 66 alias_method :foobad, :foo 67 68 def bar 69 "barbar" 70 end 64 71 65 72 def new_record? … … 83 90 class FakeColumn 84 91 attr_accessor :name, :type 92 85 93 def initialize(name, type) 86 94 @name, @type = name, type 87 95 end 96 88 97 end 89 98 90 91 92 93 99 describe "FakeBufferConsumer", :shared => true do 94 95 100 before :each do 96 101 @obj = FakeModel.new
