I am saving one field as string in my model, so after that i tried via console
1.9.3-p547 :250 > s1 = s.send_details
=> "---\nnew_order: order\nprogress: order on d way\ndelivered:\n
message: delivered\n send_after: '1'\n"
1.9.3-p547 :255 > JSON.parse(s1)
JSON::ParserError: 757: unexpected token at '---
'
1.9.3-p547 :262 > s1.class
=> String
i am trying to convert this to json or hash, because i need to take the values from that, is there any way to do this?
Looks like your string is a YAML. You can easy decode it with YAML.load:
require 'yaml'
YAML.load("---\nnew_order: order\nprogress: order on d way\ndelivered:\n message: delivered\n send_after: '1'\n")
=> {"new_order"=>"order", "progress"=>"order on d way", "delivered"=>{"message"=>"delivered", "send_after"=>"1"}}
Related
In console of rails 4.2.7, I have the following test:
[45] pry(main)> '#$'
=> "\#$"
[46] pry(main)> '##'
=> "\##"
[47] pry(main)> '#!'
=> "#!"
[48] pry(main)> '#ab'
=> "#ab"
It seems rails will only put a "\" before the string when there is an # or $ after #.
The problem leads me to this test is that I have a erb file that render a data attribute with an array of json:
data-xx="<%= [{xx: '#$', yy: 'yy'}.to_json, {zz: 'zzz'}.to_json] %>"
Then in chrome console, it will give the unexpected result as
$("#entry_show_modal_template").data('xx')
"["{\"xx\":\"\#$\",\"yy\":\"yy\"}", "{\"zz\":\"zzz\"}"]"
And when I change xx value from #! or some other string, the result will be ok as an array
$("#entry_show_modal_template").data('xx')
["{"xx":"#!","yy":"yy"}", "{"zz":"zzz"}"]
Does someone know if it is true and why it has such difference?
And it there any way to tackle this problem?
This is not true.
In '#{...}' hash will also be escaped. This is done to prevent recursive/implicit string interpolation.
Look:
$a = 'hello'
"#$a"
#⇒ "hello"
The problem is already solved by ruby for you. Just use the produced string as is and don’t be fooled by the way it is printed out in console.
"\#$".length
#⇒ 2
"\#$" == '#$'
#⇒ true
"\#$"[0]
#⇒ "#"
#mudasobwa's explaination is correct
According to your situation you should try in this way
===> In rails console
json_values = [{xx: '#$', yy: 'yy'}, {zz: 'zzz'}].to_json
===> In chrome console
result = JSON.parse(json_values)
you will get expected array, its just ruby technique to handle string interpolation thing
I have a string that has been escaped, I want to parse this into JSON but I keep getting errors using rails
{\"content\":{\"Soass__text_plain__abc_of_study\":\"Some of Study\",\"Dodeeedd\":
...........
........lots more of the string then comes some \u002d1 etc
Parse error on line 160:
... "id": \u002d1
JSON::ParserError: 399: unexpected token at '{"spacer":"http://s.c.xxx.yyyy.com/scds/common/u/img/spacer.gif","i18n_get_discovered_upload":"\u003cstrong\u003eGet discovered\u003c/strong\u003e for your work! Add your videos, images, documents...","bg_promo_1":
How can I JSON parse this?
You can build your json with hashes or with arrays, its more simple and clean
hash_of_values = {'foo' => 1, 'bar' => 2}
array_of_values = [hash_of_values]
And then :
JSON.parse(hash_of_values) => "{\"foo\":1,\"bar\":2}"
JSON.parse(array_of_values) => "[{\"foo\":1,\"bar\":2}]"
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 ',', '.'
I'm developing a Sinatra app, which returns JSON, e.g.
get '/clients' do
# do stuff
response = {
"success" => "true",
"msg" => "Clients successfully retrieved",
"data" => {"clients" => #current_user.clients}
}
return response.to_json
end
The returned JSON looks something like this:
{"success":"true","msg":"Clients successfully retrieved","data":{"clients":[{"client":{"created_at":"2013-03-31T22:50:18Z","email":"test#test.com","first_name":"Marge","gender":"F","hairdresser_id":2,"id":1,"surname":"Simpson","updated_at":"2013-03-31T22:50:18Z"}}]}}
When I copy and paste it into a JSON parser, it works fine.
http://json.parser.online.fr/
But when I fire up irb and try to use it, I get a bunch of errors:
1.9.3-p286 :001 > a = {"success":"true","msg":"Clients successfully retrieved","data":{"clients":[{"client":{"created_at":"2013-03-31T22:50:18Z","email":"test#test.com","first_name":"Marge","gender":"F","hairdresser_id":2,"id":1,"surname":"Simpson","updated_at":"2013-03-31T22:50:18Z"}}]}}
SyntaxError: (irb):1: syntax error, unexpected ':', expecting tASSOC
a = {"success":"true","msg":"Clients success...
^
(irb):1: syntax error, unexpected ',', expecting $end
a = {"success":"true","msg":"Clients successfully r...
^
from /home/[me]/.rvm/rubies/ruby-1.9.3-p286/bin/irb:13:in `<main>'
1.9.3-p286 :002 >
Anyone able to offer any insight? Am I doing something wrong?
Thanks alot
Problem
JSON doesn't constitute a valid Ruby hash. It's a String that you need to parse with JSON#parse.
Solution
Parse JSON as a String by enclosing it in single quotes or a Ruby quote literal. For example:
JSON.parse %q/{"success":"true","msg":"Clients successfully retrieved","data":{"clients":[{"client":{"created_at":"2013-03-31T22:50:18Z","email":"test#test.com","first_name":"Marge","gender":"F","hairdresser_id":2,"id":1,"surname":"Simpson","updated_at":"2013-03-31T22:50:18Z"}}]}}/
=> {"success"=>"true",
"msg"=>"Clients successfully retrieved",
"data"=>
{"clients"=>
[{"client"=>
{"created_at"=>"2013-03-31T22:50:18Z",
"email"=>"test#test.com",
"first_name"=>"Marge",
"gender"=>"F",
"hairdresser_id"=>2,
"id"=>1,
"surname"=>"Simpson",
"updated_at"=>"2013-03-31T22:50:18Z"}}]}}
Your hash has key value pair denoted as { key : value } but ruby uses '=>' symbol to map key to a value.
Try replacing ':' to '=>' and it works fine.
eg) a = {"success" => "true"}
If you want to parse this Json to ruby has then use this snippet:
require 'json'
value = "{\"val\":\"test\",\"val1\":\"test1\",\"val2\":\"test2\"}"
puts JSON.parse(value) # => {"val"=>"test","val1"=>"test1","val2"=>"test2"}
I am getting TypeError: can't convert String into Integer, I found duplicate answer too, but I am facing this error for 'pack'.
Other confusion is, it is working fine with ruby 1.8.7, not with ruby 1.9.3, here is the code, I am using jruby1.7.2
irb(main):003:0> length=nil
=> nil
irb(main):004:0> token_string ||= ["A".."Z","a".."z","0".."9"].collect { |r| r.to_a }.join + %q(!$:*)
=> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!$:*"
irb(main):005:0> token = (0..(length ? length : 60)).collect { token_string[rand( token_string.size)]}.pack("c*")
TypeError: can't convert String into Integer
from (irb):5:in `pack'
from (irb):5
from /home/appandya/.rvm/rubies/ruby-1.9.3-p374/bin/irb:13:in `<main>'
irb(main):006:0>
Any Idea?
string[x] in Ruby 1.8 gives you a Fixnum (the character code) and in 1.9 it gives you a single character string.
Array#pack turns an array into a binary sequence. The "c*" template to pack converts an array of Ruby integers into a stream of 8-bit signed words.
Here are the solutions, those comes from the Google Groups
1.
Background
>> %w(a b c).pack('*c')
TypeError: can't convert String into Integer
from (irb):1:in `pack'
from (irb):1
from /usr/bin/irb:12:in `<main>'
>> [1, 2, 3].pack('*c')
=> "\x01"
>> %w(a b c).map(&:ord).pack('*c')
=> "a"
Solution
irb(main):001:0> length=nil
=> nil
irb(main):002:0> token_string ||= ["A".."Z","a".."z","0".."9"].collect { |r| r.to_a }.join + %q(!$:*)
=> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!$:*"
irb(main):003:0> (0..(length ? length : 60)).collect { token_string[rand( token_string.size)]}.map(&:ord).pack("c*")
=> "rd!:!LcxU3ON57*t2s520v*zvvdflSNAgU6uq14SiD00VUDlm9:4:tJz5Ri5o"
irb(main):004:0>
2.
The return type of String's [] function was Fixnum in 1.8 but is String in 1.9:
>JRUBY_OPTS=--1.9 ruby -e "puts 'a'[0].class"
String
>JRUBY_OPTS=--1.8 ruby -e "puts 'a'[0].class"
Fixnum
JRuby 1.7.x defaults to acting like Ruby 1.9.3. You need to set JRUBY_OPTS.
3.
try join instead of pack
irb(main):004:0> length=nil
=> nil
irb(main):005:0> token_string ||= ["A".."Z","a".."z","0".."9"].collect { |r| r.to_a }.join + %q(!$:*)
=> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!$:*"
irb(main):006:0> token = (0..(length ? length : 60)).collect { token_string[rand( token_string.size)]}.join("c*")
=> "Fc*Dc*1c*6c*ac*Kc*Tc*Qc*Hc*jc*Ec*Kc*kc*zc*sc*3c*ic*hc*kc*wc**c*Wc*$c*Kc*Ic*Uc*Cc*bc*Pc*1c*!c*mc*Bc*lc*dc*ic*Dc*sc*Ac*Bc*nc*Kc*mc*Lc*oc*Zc*Xc*jc*6c*2c*Uc*ec*Yc*Dc*vc*Ic*Uc*5c*Zc*3c*o"
irb(main):007:0>
4.
if you're just trying to make a string of random characters that are 8-bit clean you may want to look at Random#bytes and something like Base64.encode64.
5.
active_support/secure_random also has a nice API for these things
I would recommend you take a look at: Array Method Pack, essentially the .pack("c") expects the elements of the array to be integers. You could try .pack("a*")
Use token = (0..(length ? length : 60)).collect { token_string[rand( token_string.size)]}.pack("a"*61)
You get the same result. I am using 61 because, going from 0..60 has 61 elements.