Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 1437

Show
Ignore:
Timestamp:
06/16/05 06:17:51 (3 years ago)
Author:
david
Message:

Added button_to as a form-based solution to deal with harmful actions that should be hidden behind POSTs. This makes it just as easy as link_to to create a safe trigger for actions like destroy, although it's limited by being a block element, the fixed look, and a no-no inside other forms. #1371 [tom@moertel.com]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionpack/CHANGELOG

    r1434 r1437  
    11*SVN* 
     2 
     3* Added button_to as a form-based solution to deal with harmful actions that should be hidden behind POSTs. This makes it just as easy as link_to to create a safe trigger for actions like destroy, although it's limited by being a block element, the fixed look, and a no-no inside other forms. #1371 [tom@moertel.com] 
    24 
    35* Fixed image_tag so an exception is not thrown just because the image is missing and alt value can't be generated #1395 [Marcel] 
  • trunk/actionpack/lib/action_view/helpers/url_helper.rb

    r1056 r1437  
    3434      end 
    3535 
     36      # Generates a form containing a sole button that submits to the 
     37      # URL given by _options_.  Use this method instead of +link_to+ 
     38      # for actions that do not have the safe HTTP GET semantics 
     39      # implied by using a hypertext link. 
     40      # 
     41      # The parameters are the same as for +link_to+.  Any _html_options_ 
     42      # that you pass will be applied to the inner +input+ element. 
     43      # In particular, pass 
     44      #  
     45      #   :disabled => true/false 
     46      # 
     47      # as part of _html_options_ to control whether the button is 
     48      # disabled.  The generated form element is given the class 
     49      # 'button-to', to which you can attach CSS styles for display 
     50      # purposes. 
     51      # 
     52      # Example 1: 
     53      # 
     54      #   # inside of controller for "feeds" 
     55      #   button_to "Edit", :action => 'edit', :id => 3 
     56      # 
     57      # Generates the following HTML (sans formatting): 
     58      # 
     59      #   <form method="post" action="/feeds/edit/3" class="button-to"> 
     60      #     <div><input value="Edit" type="submit" /></div> 
     61      #   </form> 
     62      # 
     63      # Example 2: 
     64      # 
     65      #   button_to "Destroy", { :action => 'destroy', :id => 3 }, 
     66      #             :confirm => "Are you sure?" 
     67      # 
     68      # Generates the following HTML (sans formatting): 
     69      # 
     70      #   <form method="post" action="/feeds/destroy/3" class="button-to"> 
     71      #     <div><input onclick="return confirm('Are you sure?');" 
     72      #                 value="Destroy" type="submit" /> 
     73      #     </div> 
     74      #   </form> 
     75      # 
     76      # *NOTE*: This method generates HTML code that represents a form. 
     77      # Forms are "block" content, which means that you should not try to 
     78      # insert them into your HTML where only inline content is expected. 
     79      # For example, you can legally insert a form inside of a +div+ or 
     80      # +td+ element or in between +p+ elements, but not in the middle of 
     81      # a run of text, nor can you place a form within another form. 
     82      # (Bottom line: Always validate your HTML before going public.) 
     83 
     84      def button_to(name, options = {}, html_options = nil) 
     85        html_options = (html_options || {}).stringify_keys 
     86        convert_boolean_attributes!(html_options, %w( disabled )) 
     87        convert_confirm_option_to_javascript!(html_options) 
     88        url, name = options.is_a?(String) ?  
     89          [ options,  name || options ] : 
     90          [ url_for(options), name || url_for(options) ] 
     91        html_options.merge!("type" => "submit", "value" => name) 
     92        "<form method=\"post\" action=\"#{h url}\" class=\"button-to\"><div>" + 
     93          tag("input", html_options) + "</div></form>" 
     94      end 
     95 
     96 
    3697      # This tag is deprecated. Combine the link_to and AssetTagHelper::image_tag yourself instead, like: 
    3798      #   link_to(image_tag("rss", :size => "30x45", :border => 0), "http://www.example.com") 
     
    158219          end 
    159220        end 
     221 
     222        # Processes the _html_options_ hash, converting the boolean 
     223        # attributes from true/false form into the form required by 
     224        # HTML/XHTML.  (An attribute is considered to be boolean if 
     225        # its name is listed in the given _bool_attrs_ array.) 
     226        # 
     227        # More specifically, for each boolean attribute in _html_options_ 
     228        # given as: 
     229        # 
     230        #     "attr" => bool_value 
     231        # 
     232        # if the the associated _bool_value_ evaluates to true, it is 
     233        # replaced with the attribute's name; otherwise the attribute is 
     234        # removed from the _html_options_ hash.  (See the XHTML 1.0 spec, 
     235        # section 4.5 "Attribute Minimization" for more: 
     236        # http://www.w3.org/TR/xhtml1/#h-4.5) 
     237        # 
     238        # Returns the updated _html_options_ hash, which is also modified 
     239        # in place. 
     240        # 
     241        # Example: 
     242        # 
     243        #   convert_boolean_attributes!( html_options, 
     244        #                                %w( checked disabled readonly ) ) 
     245 
     246        def convert_boolean_attributes!(html_options, bool_attrs) 
     247          bool_attrs.each { |x| html_options[x] = x if html_options.delete(x) } 
     248          html_options 
     249        end 
     250 
    160251    end 
    161252  end 
  • trunk/actionpack/test/template/url_helper_test.rb

    r1056 r1437  
    2222 
    2323  # todo: missing test cases 
     24  def test_button_to_with_straight_url 
     25    assert_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com") 
     26  end 
     27 
     28  def test_button_to_with_javascript_confirm 
     29    assert_equal( 
     30      "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input onclick=\"return confirm('Are you sure?');\" type=\"submit\" value=\"Hello\" /></div></form>", 
     31      button_to("Hello", "http://www.example.com", :confirm => "Are you sure?") 
     32    ) 
     33  end 
     34 
     35  def test_button_to_enabled_disabled 
     36    assert_equal( 
     37      "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", 
     38      button_to("Hello", "http://www.example.com", :disabled => false) 
     39    ) 
     40    assert_equal( 
     41      "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input disabled=\"disabled\" type=\"submit\" value=\"Hello\" /></div></form>", 
     42      button_to("Hello", "http://www.example.com", :disabled => true) 
     43    ) 
     44  end 
     45 
    2446  def test_link_tag_with_straight_url 
    2547    assert_equal "<a href=\"http://www.example.com\">Hello</a>", link_to("Hello", "http://www.example.com")