parsing in rails using CSV - ruby-on-rails

So I am trying to parse a list of emails separated by a comma and inputted in a form using the built-in CSV library in rails 3.
Here is the code:
#variable = params[:body]
#csv = CSV.parse(#variable, :col_sep => ",")
#csv.each do |row|
user = User.where(:email => row)
However, the output is something like this:
- - test#hi.com
- ! ' hi#hi.com'
Therefore, each row in the #csv that I am trying to go over is an entire list of emails. How can I separate them? Thanks!

CSV::parse returns an array of arrays if you don't pass a block as an argument. So when you enumerate #csv using #each, the argument row will be an array of strings. Not a single string as your code suggests.
If the email address is the first column of each row in your CSV file, then you would replace
User.where(:email => row)
with
User.where(:email => row[0])
It's not exactly clear what the format of your CSV file is though. If you have multiple email addresses per row, or have the email address in a different column, you'll have to revise the code accordingly.

Related

New line in csv cell (rails)

I'd like multiple pieces of data on different lines within the same CSV cell like this:
"String" 2-15-2021 05:26pm
"String ..."
"String..."
I have tried the following and ended up with \n in the cell and not an actual new line, like this "2-15-2021 05:26pm \nHi, it's ...".
["\n", time, text.body].join("\n")
[time, text.body, "\n"].join("\n")
[time, text.body].join("\n")
The input data is an array of hashes. The output of a row is a hash with keys and values, one of the values is a list of strings (or this can be a list of lists of string, I am playing with what I can get to work). The list of strings is where I am trying to add line breaks.
I am using this to create the csv:
CSV.open("data.csv", "wb") do |csv|
csv << list.first.keys
list.each do |hash|
csv << hash.values
end
end
I ended up needing a list of strings that I could then join and add new lines onto.
values = []
values.push("#{time}, #{text.body}")
# And then in the hash for the csv, setting the value for that column like this:
{ message: values.join("\n\n")}

Rails open xls(excel) file

I have a file b.xls from excel I need to import it to my rails app
I have tried to open it
file = File.read(Rails.root.to_s+'/b.xls')
I have got this
file.encoding => #Encoding:UTF-8
I have few questions:
how to open without this symbols(normal language)?
how to convert this file to a hash?
File pretty large about 5k lines
You must have array of all rows then you can convert it to some hash if you like so.
I would recommend to use a batch_factory gem.
The gem is very simple and relies on the roo gem under the hood.
Here is the code example
require 'batch_factory'
factory = BatchFactory.from_file(
Rails.root.join('b.xlsx'),
keys: [:column1, :column2, ..., :what_ever_column_name]
)
Then you can do
factory.each do |row|
puts row[:column1]
end
You can also omit specifying keys. Then batch_factory will automatically fetch headers from the first row. But your keys would be in russian. Like
factory.each do |row|
puts row['Товар']
end
If you want to hash with product name as key you can do
factory.inject({}) do |hash, row|
hash.merge(row['Товар'] => row)
end

Converting a string to integer in CSV import on Rails

I've a rake task where I import CSV data into a database via Rails.
I want a specific column (specifically, row[6] below) to be rendered as an integer. However, everything I try returns that value as a string.
Below is the rake task:
require 'csv'
namespace :import_site_csv do
task :create_sites => :environment do
CSV.foreach('../sites.csv', :headers => true) do |row|
row[6] = row[6].to_i
Site.create!(row.to_hash)
end
end
end
Does anyone have an idea how I might do this? Thanks!
You are making one small (but important) mistake here.
When you call CSV.foreach('../sites.csv') each of the rows will be an array of the values in that particular row. That would allow you to access the data you need, in the way you do it now - row[6].
But, when you add the :headers => true option to CSV.foreach, you will not get an array of values (row will not be an array). Instead, it will be a CSV::Row object (docs). As you can read in the documentation:
A CSV::Row is part Array and part Hash. It retains an order for the fields and allows duplicates just as an Array would, but also allows you to access fields by name just as you could if they were in a Hash.
For example, if you have a column with the name Title in the CSV, to get the title in each of the rows, you need to do something like:
CSV.foreach('file.csv', :headers => true) do |row|
puts row['Title']
end
Since I do not know the structure of your CSV, I cannot tell you which key you should use to get the data and convert it to an Integer, but I think that this should give you a good idea of how to proceed.

Ruby on Rails Mongoid to csv

I would like to ask if any one know how correctly transfer Mongoid data in to CSV document?
I got a model Record and I want every row from Record to become row in CSV document. I got 90 columns (keys) in the Record and I want to exclude some of the them from CSV document but I do not wont manually type every key which I want to be on CSV document. My code is
#all_rows = Record.all
CSV.open(Rails.root.join('public', 'downloads', "file.csv"), "w") do |csv|
#allrows.all.each do |record|
csv << record
end
But it does not work I am getting error
undefined method `map' for #<Record:0x007f9cd9e242f8>
if i adding record.to_s
i am gating document full of records like this #<Record:0x007f801ba60d68>
If any one can please help me to fix it! Thank you!
You are using << method on csv (documentation), which expects to be called with array as an argument. That is why it tries to perform map method on your record.
Solution for your problem is adding array of attributes instead of record object. There is method attributes that will return hash with all attributes.
ignored_attributes = ["attribute_you_dont_want", "another_attribute"]
#all_rows = Record.all
CSV.open(Rails.root.join('public', 'downloads', "file.csv"), "w") do |csv|
#all_rows.each do |record|
csv << record.attributes.delete_if{ |attr, value| ignored_attributes.include?(attr) }.values
end
end
Note that I wrote #all_rows.each, you shouldn't call all method again.
This code will perform delete_if method on attributes hash and will remove any attributes with names included in ignored_attributes array. delete_if returns hash on which you can call values method to return only array of values.

How to convert a string "560,000" into an integer 560000 when importing from csv into database in Rails

just started learning Rails and have managed to import a csv file into a database, but the price field in the csv has quotes and a comma like this: "560,000"
But if I make the price field as t.integer in the migration file, then add the data, the price gets imported as 560. So, how do I remove the quotes and the comma before importing it? thanks, Adam
edit: here's the rake file:
require 'csv'
task :csv_to_properties => [:environment] do
CSV.foreach("lib/assets/cbmb_sale.csv", :headers => true) do |row|
Property.create!(row.to_hash)
end
end
Try something like:
csvvalue = csvvalue.gsub!(/,/,'').to_i
Cheers!
Thanks for posting your code. I don't do a ton with converting csv's to hashes but something like this will probably work:
Property.create!(row.to_hash.each_pair{|k,v| row.store(k,v.gsub(/,/,'').to_i)})
Pretty ugly but probably pretty close to what you want.
In your code example, assuming the price field is in row element 4:
CSV.foreach("lib/assets/cbmb_sale.csv", :headers => true) do |row|
row[price=4].gsub!(/,/,'')
Property.create!(row.to_hash)
end
The price=4 is just a handy way to document the index value of the price element, it creates a variable called price assigns the value 4 to it, then immediately uses it as the array index.
Since Property.create! is already taking care of the string to integer conversion, we can perform an in-place substitution for the regular expression that contains a comma /,/ for an empty string ''.
Try:
"220,000".scan(/\d+/).join().to_i

Resources