How to output an Array as JSON? - ruby-on-rails

I have the following:
#array.inspect
["x1", "x2", "adad"]
I would like to be able to format that to:
client.send_message(s, m, {:id => "x1", :id => "x2", :id => "adad" })
client.send_message(s, m, ???????)
How can I have the #array output in the ??????? space as a ids?
Thanks

{:id => "x1", :id => "x2", :id => "adad" } is not a valid hash since you have a key collision
it should look like:
{
"ids": ["x1", "x2", "x3"]
}
Update:
#a = ["x1", "x2", "adad"]
#b = #a.map { |e| {:id => e} }
Then you can do b.to_json, assuming you have done require "json" already

Well ordinarily you could do something like this:
Hash[#array.collect{|i| [:id, i]}]
But that will result in {:id => "adad"} because the first element will punch all the rest: hashes in ruby have unique keys. So I don't think there's a super awesome way to do this offhand.

Related

create a specific hash (dynamic)

How I can create a hash like this in a cycle ?
User.items.each do |m|
......
Result:
test = [{:name => 'Unit 1', :price => "10.00"},
{:name => 'Unit 2', :price => "12.00"},
{:name => 'Unit 3', :price => "14.00"}]]
You can use map to return hashes that you build.
Assuming your Item resource responds to name and price, it would look like
test = User.items.map do |m|
{
name: m.name,
price: m.price
}
end
You also can do like this:
Item.connection.select_all("select name, price from items where user_id = xxxxx;")
you will get an array containing hash, like this:
[{"name"=>"xxx", "price"=> xxx},{}......]

Rails - Building a JSON object with multiple items

currently I am creating a JSON object as follows:
#comments = Array.new
comments.collect do |comment|
#comments << {
:id => comment.id,
:content => html_format(comment.content),
:created_at => comment.created_at
}
end
#comments.to_json
And this returns something like this:
[{"created_at":"2011-03-02T09:17:27-08:00","content":"<p>Random.......</p>","id":734}, {"created_at":"2011-03-02T09:17:27-08:00","content":"<p>asdasd.......</p>","id":714}, {"created_at":"2011-03-01T09:17:27-08:00","content":"<p>Random.......</p>","id":134}, {"created_at":"2011-03-01T02:17:27-08:00","content":"<p>dasdasdasdasd.......</p>","id":3124}]
Problem here is that I need to include a few other items that aren't arrays. What I would like is the JSON object to look something like this:
[comments: {"created_at":"2011-03-02T09:17:27-08:00","content":"<p>Random.......</p>","id":734}, {"created_at":"2011-03-02T09:17:27-08:00","content":"<p>asdasd.......</p>","id":714}, {"created_at":"2011-03-01T09:17:27-08:00","content":"<p>Random.......</p>","id":134}, {"created_at":"2011-03-01T02:17:27-08:00","content":"<p>dasdasdasdasd.......</p>","id":3124}, last_load: "123123123123", last_view: "zxczcxzxczxc"]
Any ideas on how I can take what I have above, and expand it to pass additional items other than the comments array?
Thank you!
Add your list to a hash, and then call to_json on the hash.
> a = [1,2,3]
=> [1, 2, 3]
> h = {:comments => a, :foo => "bar"}
=> {:foo=>"bar", :comments=>[1, 2, 3]}
> h.to_json
=> "{\"foo\":\"bar\",\"comments\":[1,2,3]}"

Finding unique hash value within array of hashes (Ruby)

a[0] = {:id => '1234', :value => '37'}
a[1] = {:id => '4321', :value => '50'}
a[2] = {:id => '1122', :value => '50'}
From here I want to be able to check to see if a hash exists with :id => '4321' without having to loop through the array manually. Is there anything where I can do something like this: a.exists?(:id => '4321') ? I've tried a few things but can't seem to figure it out. Thanks!
How about:
a.any? {|x| x[:id] == '4321' }
That will return true if the block returns true.

String to Array and Hash with Regexp

I would like to turn a string with opening hours like this:
"Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
Into this:
[ {:period => "Monday-Friday", :hours => "10:00-18:00"}, {:period => "Saturday", :hours => "12:00-17:00"}, {:period => "Sunday", :hours => "12:00-15:00"} ]
I'm trying it with the String.scan() method but can't figure out the Regexp.
Also if you have any suggestions of how to do it in reverse the best way (i.e. when getting the opening hours from a form.)
Update - Thank you all found perfect solutions! Right now I'm using (thanks kejadlen):
str.scan(/([\w-]+)>([\d:-]+)-([\d:]+)/).map { |(p,o,c)| {:period => p, :opens => o, :closes => c} }
But now how about reversing it =) So given:
[ {:opens=>"10:00", :closes=>"18:00", :period=>"Monday-Friday"},
{:opens=>"12:00", :closes=>"17:00", :period=>"Saturday"},
{:opens=>"12:00", :closes=>"15:00", :period=>"Sunday"} ]
I want to merge it to:
"Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
If you prefer one-liners:
s = "Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
s.split(/;/).map{|i| Hash[[[:period, :hours], i.split(/>/)].transpose]}
# or
s.split(/;/).map{|i| p, h = i.split(/>/); {:period => p, :hours => h}}
#=> [{:period=>"Monday-Friday", :hours=>"10:00-18:00"}, {:period=>"Saturday", :hours=>"12:00-17:00"}, {:period=>"Sunday", :hours=>"12:00-15:00"}]
Edit:
Regarding the reverse, this should do the job:
a.map{|i| "#{i[:period]}>#{i[:opens]}-#{i[:closes]}"}.join(';')
=> "Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
this is how I would do it
str="Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
periods = str.split(';')
#=> ["Monday-Friday>10:00-18:00", "Saturday>12:00-17:00", "Sunday>12:00-15:00"]
period_array=[]
periods.each do |period|
period_with_hours = period.split('>')
period_array << {:period => period_with_hours.first, :hours => period_with_hours.last}
end
period_array
#=> [{:period=>"Monday-Friday", :hours=>"10:00-18:00"}, {:period=>"Saturday", :hours=>"12:00-17:00"}, {:period=>"Sunday", :hours=>"12:00-15:00"}]
Try this:
String S = ([^\>]*)\>([^\;]*)\;
String T = " {:period => $1, :hours => $2}, "
originalString.replaceAll(S,T);
Might have to play with the regexp a little more but that should about do it.
Edit - Well, you asked for the answer in the context of ruby and I gave you the Java answer but the regular expression should work anyway...
This looks like it works
the_input.split(';').collect{|pair|
period, hours = pair.split('>')
{:period => period, :hours => hours}
}
=> [{:hours=>"10:00-18:00", :period=>"Monday-Friday"}, {:hours=>"12:00-17:00", :
period=>"Saturday"}, {:hours=>"12:00-15:00", :period=>"Sunday"}]
str.scan(/([\w-]+)>([\d:-]+)/).map {|(p,h)| {:period => p, :hours => h }}

rails active record - complicated conditions clause

this works:
ids = [1,2]
varietals = Varietal.find(:all, :conditions => [ "id IN (?)",ids])
But what I want to do is that plus have a condition of: deleted => false
varietals = Varietal.find(:all, :conditions =>{ :deleted => false})
any ideas?
am i going to have to use find_by_sql?
I would handle this with a named_scope to communicate intent and foster re-use:
named_scope :undeleted,
:conditions => { :deleted => false }
Then you can simply use:
varietals = Varietal.undeleted.find([1,2])
You can do it a few ways, but this is the most straight forward:
varietals = Varietal.find( [1,2], :conditions => { :deleted => false })
You can see in the docs that the first parameter of find can take an integer or an array.
ids = [1,2]
varietals = Varietal.find(:all, :conditions => {:id => ids, :deleted => false})
This should work, haven't tested it though.
From the docs:
An array may be used in the hash to
use the SQL IN operator:
Student.find(:all, :conditions => { :grade => [9,11,12] })

Resources