Last active
December 19, 2015 00:09
-
-
Save mmrwoods/5866233 to your computer and use it in GitHub Desktop.
Make formtastic's cancel action return the user to the original referrer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Make formtastic's cancel action return the user to the original referrer | |
| # | |
| # By default, the cancel action in formtastic always goes to the previous | |
| # page, so hitting cancel after validation failures returns the user to | |
| # the form, not the original referring page. The code below modifies the | |
| # cancel action such that it by default returns to the original referrer. | |
| # It does so by simply keeping track of the referrer in a hidden field. | |
| # | |
| # See also https://github.com/justinfrench/formtastic/issues/780 | |
| require 'formtastic' | |
| Formtastic::Actions::LinkAction.class_eval do | |
| def to_html | |
| wrapper do | |
| hidden_field_html + template.link_to(text, url, button_html) | |
| end | |
| end | |
| def url | |
| return options[:url] if options.key?(:url) | |
| hidden_field_value || :back | |
| end | |
| private | |
| def hidden_field_name | |
| "#{object_name}_#{method}_action_url" | |
| end | |
| def hidden_field_value | |
| return unless template.respond_to?(:params) && template.params[hidden_field_name].present? | |
| deserialize_url(template.params[hidden_field_name]) | |
| end | |
| def hidden_field_html | |
| # note: encode url when writing to hidden form field to avoid false positives for remote file inclusion attacks | |
| return "".html_safe if options.key?(:url) | |
| template.hidden_field_tag(hidden_field_name, serialize_url(template.url_for(url))) | |
| end | |
| def serialize_url(value) | |
| # note: encode url as cgi query string to avoid false positives for xss attacks when using json | |
| ActiveSupport::JSON.decode(URI.parse(value).to_json).to_query | |
| end | |
| def deserialize_url(value) | |
| # build url from cgi query value | |
| URI::Generic.build( | |
| CGI.parse(value).tap do |h| | |
| # CGI.parse generates an array of values for each key, we just want the first | |
| h.each{|k,v| h[k] = v.first} | |
| # convert strings that represent integers to integers (e.g. port number) | |
| h.each{|k,v| h[k] = v.to_i if v.match(/^[0-9]+$/)} | |
| # convert empty strings to nil | |
| h.each{|k,v| h[k] = nil if v.blank?} | |
| end.symbolize_keys | |
| ).to_s | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment