ruby - Regex put in via formtastic gets altered (maybe by the controller) before it's put into Mongoid -
i have form put in hashes regular expression values. problem gets messed when travelling view, through controller , mongodb mongoid. how preserve regex'es?
input examples:
{:regex1 => "^something \(#\d*\)$"} {:regex2 => "\a[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z"}
my formtastic view form looks this:
= semantic_form_for resource, :html => {:class => "form-vertical"} |r| = r.inputs = r.input :value, :as => :text = r.actions = r.action :submit
my controller create action takes in params , handles this:
class emailtypescontroller < inheritedresources::base def create puts params[:email_type][:value] # => {:regex1 => "^something \(#\d*\)$"} , # {:regex2 => "\a[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z"} puts params[:email_type][:value].inspect # => "{:regex1 => \"^something \\(#\\d*\\)$\"}" , # "{:regex2 => \"\\a[\\w+\\-.]+@[a-z\\d\\-.]+\\.[a-z]+\\z\"}" params[:email_type][:value] = convert_to_hash(params[:email_type][:value]) puts params[:email_type][:value] # => {"regex1"=>"^something (#d*)$"} , # {"regex2"=>"a[w+-.]+@[a-zd-.]+.[a-z]+z"} create! |success, failure| success.html { redirect_to resource } failure.html { render :action => :new } end end def convert_to_hash(string) if string.match(/(.*?)=>(.*)\n*/) string = eval(string) else string = string_to_hash(string) end end def string_to_hash(string) values = string.split("\r\n") output = {} values.each |v| val = v.split("=") output[val[0].to_sym] = val[1] end output end end
firing console , inspecting values put in through mongoid:
loading development environment (rails 3.2.12) 1.9.3p385 :001 > emailtype.all.each |email_type| 1.9.3p385 :002 > puts email_type.value 1.9.3p385 :003?> end {"regex1"=>"^something (#d*)$"} {"regex2"=>"a[w+-.]+@[a-zd-.]+.[a-z]+z"} => true 1.9.3p385 :004 >
the problem lies in ruby's evaluation of strings, ignores useless escapes:
puts "^something \(#\d*\)$".inspect =>"^something (#d*)$"
that eval ignores backslash. note typically in ruby regexes aren't created using strings through own regex literal, that
/^something \(#\d*\)$/.inspect =>"/^something \\(#\\d*\\)$/"
notice double backslash instead of single. means eval has receive 2 backslashes instead of 1 in string, has eval'd single backslash character.
a quick , easy way run sub ob string before convert_to_hash call:
# little confusing due escapes, single backslashes replaced double. # second parameter confusing, appears string#sub requires few # escapes due backslashes being used backreference. # i.e. \n replaced nth regex group, replace string # "\n" yet escape backslash required, "\\n" replaced "\n". # therefore input of 8 blackslashes eval'd string of 4 backslashes, # sub interprets 2 backslashes. params[:email_type][:value].gsub!('\\', '\\\\\\\\')
this shouldn't problem unless using backslashes in hash keys @ point, in case more advanced matching needed extract regex's , perform substitution on them.
Comments
Post a Comment