How do I convert an array of strings into a comma-separated string? - ruby-on-rails

I have an array:
array = ["10", "20", "50", "99"]
And I want to convert it into a simple comma-separated string list like this:
"10", "20", "50", "99"

array.join(',') will almost do what you want; it will not retain the quotes around the values nor the spaces after.
For retaining quotes and spaces: array.map{|item| %Q{"#{item}"}}.join(', ')
This will print "\"10\", \"20\", \"50\", \"99\"". The escaped quotes are necessary assuming the question does in fact call for a single string.
Documentation on the %Q: string literals.
You could use inspect as suggested in another answer, I'd say that's personal preference. I wouldn't, go look at the source code for that and choose for yourself.
Useful aside: array.to_sentence will give you a "1, 2, 3 and 4" style output, which can be nice!

["10", "20", "50","99"].map(&:inspect).join(', ') # => '"10", "20", "50", "99"'

Here:
array.map {|str| "\"#{str}\""}.join(',')

Several answers have offered solutions using #map, #inspect, #join. All of them fail to get certain details of CSV encoding correct for edge cases involving embedded commas and/or string delimiters in the elements.
It's probably a better idea to use the stdlib class CSV then to roll your own.
irb> require 'csv'
=> true
irb> a = [10,'1,234','J.R. "Bob" Dobbs',3.14159]
=> [10, "1,234", "J.R. \"Bob\" Dobbs", 3.14159]
irb> puts a.to_csv
10,"1,234","J.R. ""Bob"" Dobbs",3.14159
The map.join solutions are sufficient if this encoding doesn't need to care about embedded delimiters, or is intended for some internal representation only, but they will fail if generating data for exchange with other programs that expect Comma Separated Values (CSV) as a generally understood representation.

The simplest solution is to use the built in ".to_sentence" method.
So
["fred", "john", "amy"].to_sentence outputs "fred, john, and amy"

This is a slightly alternative solution, particularly handy if you need to convert an array with double quoted strings to a single quoted list (for say SQL queries):
"'#{["John Oliver", "Sam Tom"].join("','")}'"
to
'John Oliver', 'Sam Tom'
Attribution: https://alok-anand-ror.blogspot.com/2014/04/ruby-join-array-elements-with-single.html

This is how you can send push notifications using FCM for Android devices.
Assuming you want notify followers when ever a user posts something on their status this is how you do it. This is done in Rails 5.2.6 for Rest Apis--- But still you can use the same for web push notifications. This is for sending to many devices with registration_ids to target followers with notifications.
Gem : fcm
in your controller:
require "fcm"
def create_vibe(user)
#vibe = user.vibes.new(content: #content, picture: #picture, video: #video, isvideofile: #isvideofile, video_thumbnail: #video_thumbnail, source: #source, background_color: #background_color)
#followed = user.followers
if #followed.present?
#registration = #followed.map { |s| s.registration_id }
end
if #vibe.save
fcm = FCM.new("") # set your FCM_SERVER_KEY
options = {
data: {
notification_type: 1,
title: "#{#vibe.user.username} " "has posted a new Vibe",
body: "#{#vibe.content}",
user_data: {
vibe_id: #vibe.id,
user_id: #vibe.user.id,
background_color: #background_color,
},
},
}
response = fcm.send(#registration, options)
puts response
render :status => 200,
:json => { :success => true,
:info => "Vibe posted successfully",
:vibe_info => {
:content => #content,
:picture => #picture,
:video => #video,
:video_thumbnail => #video_thumbnail,
:isvideofile => #isvideofile,
:source => #source,
:fcm => options,
} }
else
render :status => 200, :json => { :success => false, :result => "Vibe can't be blank" }
end
end

Related

How to get value from a nested hash [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have this nested hash with three answer parts:
I want to get:
q2a.text= "Purchasing experience"
q2a.answer="4"
q2b.text= "Design on the product"
q2b.answer="4"
q2c.text="Quality of the product"
q2c.answer="4"
but I don't know how to do it.
{
:question_text => "Please rate the following based on your overall experience:",
:question_export_value => nil,
:question_type => "10",
:answer => [
[0] {
:answer_part => "Purchasing experience",
:answer_column => "4",
:answer_text => "4",
:answer_other => nil,
:answer_export_value => nil,
:answer_comment => nil
},
[1] {
:answer_part => "Design on the product",
:answer_column => "4",
:answer_text => "4",
:answer_other => nil,
:answer_export_value => nil,
:answer_comment => nil
},
[2] {
:answer_part => "Quality of the product",
:answer_column => "4",
:answer_text => "4",
:answer_other => nil,
:answer_export_value => nil,
:answer_comment => nil
}
],
:question_score => "0",
:question_code => nil,
:question_number => "2"
}
When in doubt consult the docs. Also, in the future, please use code snippets instead of screen shots, that way I can copy paste from your example.
I'll give you a brief overview of ruby hashes. First of all lets create your hash. I will use a shortened version because I don't want to retype your entire hash.
my_hash = {
question_text: "Please rate the following based on your overall experience",
question_export_value: nil,
question_type: 10,
answer: [
{
answer_part: "Purchasing experience",
answer_column: "4",
answer_text: "4"
}
]
}
To get the the answers you need to access you hash with the appropraite key: my_hash[:answer].my_hash[:answer] actually points to an array of hashes, notice the brackets instead of the braces. So to get to the first answer you would use my_hash[:answer].first. This points to the first hash in the answers array. You may pull values out of this hash using the desired value's key. to get to "Purchasing experience" you would use
my_hash[:answer].first[:answer_part]
to get the answer text "4"
my_hash[:answer].first[:answer_text]
Sorry, but the question is a little confusing since the payload in your screenshot and the bit of code you pasted don't really match at all. Think you'll want to learn some basic Ruby syntax with hashes and arrays:
http://ruby-doc.org/core/Array.html
http://ruby-doc.org/core/Hash.html
Specifically check out the [] methods.
I'm going to try and respond based off of the payload. But basically you're working with a hash where one of the values in the hash is an array, and each of the elements in an array is another hash.
So, starting from the main hash you have something like this
answers = payload[:answer] # where payload is the hash you posted
q2a = answers[0]
q2b = answers[1]
q2c = answers[2]
puts q2a[:answer_part], q2a[:answer_text] # prints "Purchasing experience" and "4"
puts q2b[:answer_part], q2b[:answer_text] # prints "Design of the product" and "4"
puts q2c[:answer_part], q2c[:answer_text] # prints "Quality of the product" and "4"
So to sum up, grab the array with the key :answer from the hash, index into the array for the data you want, and then use the proper keys to grab your data.

How do you use the Gibbon Gem to automatically add subscribers to specific interest groups in MailChimp?

I'm trying to figure out how I can use the Gibbon gem in Rails to automatically add subscribers to specific interest groups in MailChimp?
I've found this article which details a non-Rails method for doing so: http://roman.tao.at/uncategorized/mailchimp-api-listsubscribe-listbatchsubscribe-and-groups/
I'd like to figure out how to implement that functionality using the Gibbon gem: https://github.com/amro/gibbon
FYI, I'm also a novice with both MailChimp and Rails.
Finally, after hours of perusing through code. I've found the example I'm looking for!
Thanks to TJ Moretto for providing this on a Google Groups thread:
I'm using the gibbon gem, but ran into the same types of issues.
Here's how I had to format the parameters to finally get this to work:
gb.list_subscribe({:id => "#{list.id}",
:email_address => user.email,
:update_existing => true,
:double_optin => false,
:send_welcome => false,
:merge_vars => {'FNAME' => "#{user.first_name}",
'LNAME' => "#{user.last_name}",
'GROUPINGS' => {0 => {'id' => grouping.id, 'groups' => "#{challenge.name}"}}}
})
Hope that helps.
Mailchimp Team - based on the number of issues that everyone runs into
when trying to do this (across all programming languages), I suggest
you update the API documentation to be more clear.
Update for version 2.0 of the MailChimp API and version 1.0 of Gibbon (For #Calin and posterity). Here are the necessary changes from the previous version. The API object is accessed like this now:
gb = Gibbon::API.new
And list methods like so:
gb.lists.subscribe(params)
Finally the :email_address parameter has been replaced by the :email parameter, which should be given a value of the following form: The value should itself be a hash with one key, either 'email' or 'leid', and the value should be either the email address of the subscriber or MC's unique identifier (LEID) for the subscriber.
So a full subscription call might look something like this:
gb = Gibbon::API.new
gb.lists.subscribe(:id => "ed6d1dfef4",
:email =>
{ "email" => "example#domain.com" },
:merge_vars =>
{:groupings =>
{
0 => { :id => "95", :groups => ["Some Group", "Another Group"]},
1 => { :id => "34", :groups => ["A Third Group"]}
}
},
:update_existing => "true",
:double_optin => "false",
:replace_interests => "false")

How to format scientific data into proper data series for graph display in Ruby (Rails 3.1.x)?

Needing some guidance about how to properly graph data that is very small and stored as BigDecimal.
If anyone has had experience using BigDecimals in any graphing scenario I believe your input on how you placed these into a usable sequence would be invaluable.
Presently I'm using lazy_high_charts and it really seems that this is going to work out exceptionally well, however I've run into a hitch where I've not dealt with data on the minute BigDecimal scale hitherto.
Given my queries, I'll be pulling out about a 1,000 data points for a few different series of data ranging in accuracy from about 0.100E-9 to about 0.100E-1.
What would be the best way to prep these data series for presentation in such a graph that has a scientific application and therefore precision is important? I'm not sure if I could or should continue in BigDecimal or something else?
I'm presently querying the database with a line similar to:
series_a = dataset.order("date").select('data_set.data1').limit(1000).all.zip
I'd appreciate some guidance of going from this result (again, the output is an array of BigDecimals) to the appropriate format for what will go into the chart series.
An contextual example of the code I'm using to build the chart in my controller is:
#h = LazyHighCharts::HighChart.new('graph') do |f|
series_a = dataset.order("date").select('data_set.data1').limit(1000).all.zip
series_b = dataset.order("date").select('data_set.data3').limit(1000).all.zip
f.series(:name => 'Data 1', :data => series_a)
f.series(:name => 'Data 2', :data => series_b)
f.chart({:defaultSeriesType => "line" })
f.yAxis [
{:title => { :text => "Left Y Label", :margin => 10} },
{:title => { :text => "Right Y Label"}, :opposite => true }
]
f.xAxis(:title => { :text => "X Label"} )
f.title(:text => "Graph Title")
f.legend(:align => 'right', :verticalAlign => 'top', :y => 75, :x => -50, :layout => 'vertical')
end
I think I'm a bit further along in my understanding of this having decided to convert the BigDecimals to strings as per "How to access fields by attribute name from ActiveRecord row results?" However it appears ultimately this fails and gives erratic results as the series functions :data field expects, I think, numeric input. I am thinking that this ultimately emits json to highcharts, however I'm still stuck for the moment in my attempt to pass these values on in correctly.
When you do this:
series_a = dataset.order("date").select('data_set.data1').limit(1000).all.zip
you'll end up with an array of arrays as we already discussed elsewhere. If you get rid of the zip, you should end up with an array of objects in series_a. I'd guess that chart would be happier with an array of numbers so:
series_a = dataset.order("date").
select('data_set.data1').
limit(1000).
all.
map(&:data1)
or, if data1 is a BigDecimal (due to using a fixed precision type in the database) then maybe you'd want this:
series_a = dataset.order("date").
select('data_set.data1').
limit(1000).
all.
map { |o| o.data1.to_f }
to get an array of floating point values that the chart should know what to do with.
I'm not familiar with Highcharts so there is some guesswork here.

What is the best way to test export to excel or csv using rspec?

I'm using ruby CSV library to export reporting data from Ruby On Rails application.
And i am wondering what would be the best way to test such operation?
Thanks in advance
Hi I was using Ruby 1.9.2 which has Faster CSV, but the concept should be similar. I actually have my factories in a helper method, but put it all together to make it easier to see here. I'd also love to know if there is a better way, but this worked for me.
I generated the report, and then opened it to compare it with my expected results. I wanted to make sure the file existed. You could do something similar without actually saving the file.
describe "Rsvp Class" do
created = "#{Time.now.to_formatted_s(:db)} -0800"
before(:each) do
[{:first_name => "fred", :last_name => "flintstone", :state => "CA", :zip => "12345", :created_at => created},
{:first_name => "barny", :last_name => "rubble", :state => "CA", :zip => "12345", :created_at => created}].each do |person|
rsvp = Factory.build(:rsvp)
rsvp.first_name = person[:first_name]
rsvp.last_name = person[:last_name]
rsvp.state = person[:state]
rsvp.zip = person[:zip]
rsvp.created_at = person[:created_at]
rsvp.save
end
end
it "should generate a report csv file" do
response = "first name, last name, email, address, address line 1, city, state, zip, variation code, tracking code, created at\nfred, flintstone, fred#example.com, , , , CA, 12345, , , #{created}\nbarny, rubble, fred#example.com, , , , CA, 12345, , , #{created}\n"
Rsvp.generate_report
string = ""
CSV.foreach("#{::Rails.root.to_s}/reports/rsvp_report.csv", :quote_char => '"', :col_sep =>',', :row_sep =>:auto) do |row|
string << "#{row.join(", ")}\n"
end
string.should == response
end
end

output formated json with rails 3

I use rails 3.0.3
A javascript auto complete needs data like this
{
query:'Li',
suggestions:['Liberia','Libyan Arab Jamahiriya','Liechtenstein','Lithuania'],
data:['LR','LY','LI','LT']
}
My action is
def autocomplete
#query = params[:query]
#customers = Customer.where('firstname like ?', "%#{#query}%")
render :partial => "customers/autocomplete.json"
end
My view is
{
query:'<%= #query %>',
suggestions: <%= raw #customers.map{|c| "#{c.firstname} #{c.lastname}" } %>,
data: <%= raw #customers.to_json %>
}
it returns
{
query:'e',
suggestions: ["customer 1", "customer 2"],
data: [1, 3]
}
it's not working because the data for suggestions/data should be between simple quote...
I cannot use the to_json method, because it'll returns all the content of my object.
Any suggestion?
cheers
Note: this is way out of date, Jbuilder is by far a better option.
There are two ways you can approach this. If you simply need a subset of the fields in an object, you can use :only or :except to exclude what you don't want.
#customer.to_json(:only => [:id, :name])
in your example it looks like you need to return json in a specific format, so simply serializing an array of results won't work. The easiest way to create a custom json response is with the Hash object:
render :json => {
:query => 'e',
:suggestions => #customers.collect(&:name),
:data => #customers.collect(&:id)
}
I've tried using partials to build json responses, but that doesn't work nearly as well as simply using Hash to do it.
Formatting the first and last names as a single string is something you are likely to do a lot in your views, I would recommend moving that to a function:
class Customer < ActiveRecord::Base
...
def name
"#{first_name} #{last_name}"
end
def name=(n)
first_name, last_name = n.split(' ', 2)
end
end
Just some convenience functions that makes your life a little easier, and your controllers/views cleaner.
If Adam's response won't work for you, this may do it (admittedly not the most elegant solution):
{
query:'<%= #query %>',
suggestions: [<%= raw #customers.map{|c| "'#{c.firstname} #{c.lastname}'" }.join(", ") %>],
data: [<%= raw #customers.map{|c| "'#{c.id}'" }.join(", ") %>]
}
I've seen something like this in a .erb:
<%= raw
{
:query => #query,
:suggestions => #customers.map{|c| "#{c.firstname} #{c.lastname}" },
:data => #customers
}.to_json
%>
If thinking of preparing data to be consumed by other programs as presentation logic, this might make sense to you.
FWIW I like it.

Resources