I have a string like
"car\"
which I will be storing in postgres db. I want to remove the backslash from the string before saving. Is there a way I can do that in ruby or in postgres? When I try to remove it in ruby, it considers the quote after the backslash as an escape character.
See following code:
1.9.3p125 :022 > s = "cat\\"
=> "cat\\"
1.9.3p125 :023 > puts s
cat\
=> nil
1.9.3p125 :024 > s.chomp("\\")
=> "cat"
1.9.3p125 :025 >
People don't do this much, but Ruby's String class supports:
irb(main):002:0> str = 'car\\'
=> "car\\"
irb(main):003:0> str[/\\$/] = ''
=> ""
irb(main):004:0> str
=> "car"
It's a conditional search for a trailing '\', and replacement with an empty string.
To remove a trailing backslash:
"car\\".gsub!(/\\$/, "")
Note that the backslash has to be escaped itself with a backslash.
puts '"car\"'.gsub(/\\(")?$/, '\1')
that will do it,
but, is the trailing slash always at the en followed by a quote?
See what says the
str.dump
operation, and then try to operate on that.
Related
I have this code
str = #universal_claim_form.errors.full_messages.join
str.gsub('Patient Contact Information: Value', 'Patient phone number') if str =~ /Patient Contact Information/
debugger
str.gsub("\\n", "<br/>")
debugger
flash.now[:error] = "Form has errors and was unable to be submitted.<br/> " << str
the first gsub replaces an unwanted message and the second gsub it meant to replace all the newline characters with html line breaks
at the first debugger line str = "PMP Validation failed. This happens when something you entered does not pass PMP specific validations.\\nPatient phone number: Value must be a 10 digit number"
and at the second debugger the line hasn't changed
what's even more weird is that I did this in irb at the command line and it worked
2.1.1 :001 > s = 'test'
=> "test"
2.1.1 :002 > s
=> "test"
2.1.1 :003 > s += '\ntest'
=> "test\\ntest"
2.1.1 :004 > s.gsub('\\n', '<br/>')
=> "test<br/>test"
2.1.1 :005 >
You can call gsub! to mutate the string you are calling it on (instead of returning a new string).
The reason gsub "works" in irb is because it is outputting the result - irb does not do any assignment or mutation (beyond what one enters), e.g.
irb(main):001:0> foo = 4
=> 4
irb(main):002:0> foo + 6
=> 10
foo is getting assigned 4 so it outputs the result of that assignment, likewise with foo + 6 it outputs the result but the value of foo is unchanged.
When you call gsub it returns a new string with the substitution(s), this is why you feel it "works" in irb (this is no different then it printing "4" above).
Context
I have Rails (4.0.1 + Ruby 2.0.0) connected to a PostgreSQL database filled with strings like "€ 289,95". The values have been scraped from a website using Nokogiri. I want to convert the strings to floating points.
What I've tried
Rails console:
listing = Listing.find(1)
=> #<Listing id: 1, title: #, subtitle: #, name: #, price: "€ 289,95", url: #, created_at: #, updated_at: #>
listing_price = listing.price
=> "€ 289,95"
listing_price_1 = listing_price.gsub(/,/, ".")
=> "€ 289.95"
listing_price_2 = listing_price_1.gsub(/€\s/, "")
=> "€ 289.95"
listing_price_3 = listing_price_2.to_f
=> 0.0
Problem
The code works in irb but doesn't work in the rails console.
What I want to know
How to convert a string "€ 289,95" to a float "289.95" in Rails?
The step where your technique is failing is when trying to strip away € and the space from € 289.95 with the regexp /€\s/, but this is not matching, leaving the string unchanged.
The space character in € 289,95 is probably a non-breaking space (U+00A0) rather than a “normal” space, and would be used in the web page so that the € and the value are not separated.
In Ruby the non-breaking space is not matched by \s in a regexp, so your call to gsub doesn’t replace anything:
2.0.0p353 :001 > s = "€\u00a0289.95"
=> "€ 289.95"
2.0.0p353 :002 > s.gsub(/€\s/, "")
=> "€ 289.95"
Non-breaking space is matched by the POSIX bracket expression [[:space:]], or by the character property \{Blank}:
2.0.0p353 :003 > s.gsub /€[[:space:]]/, ""
=> "289.95"
2.0.0p353 :004 > s.gsub /€\p{Blank}/, ""
=> "289.95"
So if you wanted a more specific regexp than in the other answer you could use one of these.
"€ 289,95".sub(/\A\D+/, "").sub(",", ".").to_f
# => 289.95
listing.price.delete('€ ') # => "289,95"
listing.price.delete('€ ').tr(',', '.') # => "289.95"
listing.price.delete('€ ').tr(',', '.').to_f # => 289.95
String's 'delete' method is good for removing all occurrences of the target strings.
and 'tr' method takes a string of characters to search for, and a string of characters used to replace them.
Better probably than the accepted answer is:
"€ 289,95"[/[\d,.]+/].tr ',', '.'
How can I replace double-quotes to "e; in a string?
This is what I have tried:
1.9.3-p362 :009 > a = "\"That's it\", she said."
=> "\"That's it\", she said."
1.9.3-p362 :010 > a.tr('"', ""e;")
=> "&That's it&, she said."
As you see instead of "es; I only get &, any idea?
use gsub instead
a.gsub(/\"/, ""e;")
# without regex as noted by hirolau
a.gsub("\"", ""e;")
# => ""e;That's it"e;, she said."
I have a check of the following type
validates :callback_handle, :format => { :with => /[_0-9a-zA-Z]+/ix }, :unless => "callback.nil?"
I do not want any non 0-9, a-z A-Z characters to pass. So i set callback_handle to
"!alksjda" (note ! at the begining).
This test does not fail. What am I doing wrong?
I tried a few things on irb: This is what I got:
1.9.2-p320 :001 > a = "!askldjlad"
=> "!askldjlad"
1.9.2-p320 :002 > a =~ /[_0-9a-zA-Z]+/ix
=> 1
1.9.2-p320 :003 > a = "askldjlad"
=> "askldjlad"
1.9.2-p320 :004 > a =~ /[_0-9a-zA-Z]+/ix
=> 0
I thought it would return false or nil on failure to find the match.
Can someone tell me what is wrong here in my understanding?
EDIT:
I figured out that =~ will return position of a match.
So the question becomes How do I not allow something that has any other character to not match?
Your regular expression is still able to match, because there is at least 1 character in your string that is alpha-numeric. If you want to make sure that the entire string matches then you should define the beginning and end of the match.
Old:
a =~ /[_0-9a-zA-Z]+/ix
This is saying "match at least one of these characters somewhere in a.
New:
a =~ /\A[_0-9a-zA-Z]+\z/ix
This is saying "start at the beginning of the string, then match at least 1 of only these characters, followed by the end of the string" in a.
Your regex just asks that your string contains 1 or more valid characters ... this should fix it :
validates :callback_handle, :format => { :with => /^[_0-9a-zA-Z]+$/ix }, :unless => "callback.nil?"
I have the following expression that I have tested in Rubular and that successfully matches against a snippet of HTML:
Official Website<\/h3>\s*<p><a href="([^"]*)"
However, when I run the expression in Ruby, using the following code, it returns no matches. I've reduced it down to "Official\s*Website" and it matches that, but nothing further.
Are there any additional options I need to set, or anything else that I need to do to configure Ruby/Rails to start tracking Rubular?
matches = sidebar.match(/Official\s*Website<\/h3>\s*<p><a href="([^"]*)"/)
if matches.nil?
puts "no matches"
else
puts "matches"
end
This is the relevant part of the snippet I'm matching against:
<h3>Official Website</h3><p>website.com</p>
your regular expression is correct. rubular should be working the same way your code does.
i tested it against ruby 1.8.7 and 1.9.3
irb(main):006:0> sidebar = ' <h3>Official Website</h3><p>website.com</p>'
=> " <h3>Official Website</h3><p>website.com</p>"
irb(main):007:0> sidebar.match(/Official\s*Website<\/h3>\s*<p><a href="([^"]*)"/)
=> #<MatchData "Official Website</h3><p><a href=\"http://website.com\"" 1:"http://website.com">
-
1.9.3p0 :005 > sidebar = ' <h3>Official Website</h3><p>website.com</p>'
=> " <h3>Official Website</h3><p>website.com</p>"
1.9.3p0 :006 > sidebar.match(/Official\s*Website<\/h3>\s*<p><a href="([^"]*)"/)
=> #<MatchData "Official Website</h3><p><a href=\"http://website.com\"" 1:"http://website.com">
if you want to quickly check why stuff is not working, you should try it in IRB or in your rails console. most of the times it's typo or bad encoding.