I can't seem to figure this out. I have the following class:
class CSV_Email
attr_accessor :client_array, :email_array
def load(file)
#file = file
#Parse csv file into ruby arrays...
#Column Headers - Email, Client
#client_array = []
#email_array = []
CSV.foreach(file, :col_sep => ",", :headers => :first_row, :return_headers => false) do |column|
client_array << column[0]
email_array << column[1]
end
end
end
Now I need to access client_id_array and email_array. I tried this:
test = CSV_Email.new
test.load("Email_Test.csv")
puts client_array
But I receive a undefined local variable client_array error. How can I access that variable?
I am using ruby 1.9.3.
You need to use the object you created:
puts test.client_array
Related
I am trying to create a database using mongoid but it fails to find the create method. I am trying to create 2 databases based on csv files:
extract_data class:
class ExtractData
include Mongoid::Document
include Mongoid::Timestamps
def self.create_all_databases
#cbsa2msa = DbForCsv.import!('./share/private/csv/cbsa_to_msa.csv')
#zip2cbsa = DbForCsv.import!('./share/private/csv/zip_to_cbsa.csv')
end
def self.show_all_database
ap #cbsa2msa.all.to_a
ap #zip2cbsa.all.to_a
end
end
the class DbForCSV works as below:
class DbForCsv
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Attributes::Dynamic
def self.import!(file_path)
columns = []
instances = []
CSV.foreach(file_path, encoding: 'iso-8859-1:UTF-8') do |row|
if columns.empty?
# We dont want attributes with whitespaces
columns = row.collect { |c| c.downcase.gsub(' ', '_') }
next
end
instances << create!(build_attributes(row, columns))
end
instances
end
private
def self.build_attributes(row, columns)
attrs = {}
columns.each_with_index do |column, index|
attrs[column] = row[index]
end
ap attrs
attrs
end
end
I am not aware of all fields and it may change in time. that's why I have create database and generic mehtods.
I have also another issue after having fixed the 'create!' issue.
I am using the encoding to make sure only UTF8 char are handled but I still see:
{
"zip" => "71964",
"cbsa" => "31680",
"res_ratio" => "0.086511098",
"bus_ratio" => "0.012048193",
"oth_ratio" => "0.000000000",
"tot_ratio" => "0.082435345"
}
when doing 'ap attrs' in the code. how to make sure that 'zip' -> 'zip'
Thanks
create! is a class method but you're trying to call it as an instance method. Your import! method shouldn't be an instance method either, it should be a class method since it produces instances of your class:
def self.import!(file_path)
#-^^^^
# everything else would be the same...
end
You'd also make build_attributes a class method since it is just a helper method for another class method:
def self.build_attributes
#...
end
And then you don't need that odd looking new call when using import!:
def self.create_all_databases
#cbsa2msa = DbForCsv.import!('./share/private/csv/cbsa_to_msa.csv')
#zip2cbsa = DbForCsv.import!('./share/private/csv/zip_to_cbsa.csv')
end
I am trying to import a CSV with addresses. I am requiring 'csv' at the controller. However I get this error:
NoMethodError in AddressesController#import_addresses
undefined method `path' for "testimport.csv":String
Address.import(params[:file].path)
Address Controller
class AddressesController < ApplicationController
require 'csv'
def import_addresses
Address.import(params[:file].path)
redirect_to root_url, notice: "Addresses imported."
end
Address Model
def self.import(file)
CSV.foreach(file, headers: true) do |row|
Address.create! row.to_hash
end
end
Reference: http://ruby-doc.org/stdlib-1.9.3/libdoc/csv/rdoc/CSV.html
Please try this
form_tag(import_addresses_path, :multipart => true) do
The multipart option is not part of the url_for options. so you have to make them explicitly separate*
The form_tag isn't generated right and string is sent to controller, not the object.
You have written Address Model as this :-
def self.import(file)
CSV.foreach(file, headers: true) do |row|
Address.create! row.to_hash
end
end
I think if you change a bit like the following,it should work :-
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
Address.create! row.to_hash
end
end
Hope it works !
This is your code:
Address.import( params[:file].path )
I added a couple of spaces... do you see the problem?
params[:file] is a String
The String class does not have a path method
That's the error you are seeing.
Just remove .path and it should work
I'm using Ruby 2.1.1 When I run this code:
<CSV.foreach("public/data/original/example_data.csv",headers: true, converters: :numeric) do |info|
I get an error:
No such file or directory # rb_sysopen
It works if I place example_data.csv in the same directory as shown below, but my boss said it can't be that way he wants all *.csv files in a different directory:
<CSV.foreach("example_data.csv",headers: true, converters: :numeric) do |info|
I had to use a workaround that bypassed File Utilities. Using thoughtbot/paperclip generated a directory called csvcontroller. I placed the csv file in that directory folder.
class Uploader < ActiveRecord::Base
attr_accessible :purchase_name, :item_description, :item_price, :purchase_count,
:merchant_address, :merchant_name, :csvdata
has_attached_file :csvdata, :url => "/csvcontroller/:basename.:extension",
:path => ":rails_root/csvcontroller/:basename.:extension"
#:default_url => "/controllers/original/example_data.csv"
validates_attachment_content_type :csvdata, :content_type => ["text/csv"]
end
Then I placed my parser in that directory to avoid using FileUtils
require 'csv'
#total_cost = 0
#errors out FileUtils.move '/public/data/original/example_data.csv', '/controllers'
#errors out require File.expand_path('../app/public/data/original/', __FILE__)
# errors outCSV.foreach("any_path_name_outside_the_same_directory/example_data.csv",
#headers: true, converters: :numeric) do |info|
CSV.foreach("example_data.csv", headers: true, converters: :numeric) do |info|
a =(info["item price"]).to_f
b = (info["purchase count"]).to_i
#total_cost += a * b
#store = []
customer = []
customer << info["purchaser name"]
#store << info["item description"]
#store << (info["item price"]).to_f
#store << (info["purchase count"]).to_i
#store << info["merchant address"]
#store << info["merchant name"]
puts #customer
puts #store
puts #total_cost
end
It looks ugly but that is what it is.
I could not get the FileUtils:: class to work properly. This is a Ruby bug for 2.1.1
I have a class already mapped out and in a database through DataMapper and now I'm trying to make my first resource into the database.
I have a class that handles the form data and file stuff. In that class, I'm creating the first resource with #variables passed in from the params. All other args passed into this resource come from #variables that have values from the form. In this case, #url, the variable in question, is set to a value only a few lines before. Now when I put in the URL:
rec = Post.new(
# more args
:filename_ogg => #url
)
rec.save
This is the killer: Every other line of code in this file is able to access #url, through a global variable ($upload = Upload.new(file)), except for this resource creator. When it comes to saving the resource, it doesn't go through. BUT, when I replace #url with a static string like "RANDOM URL.", it works perfectly. Why?
This had been tested under both MRI 1.9.3 and JRuby 1.6.7.2 (1.9 mode) under Ubuntu 12.04:
# #{user} edited out
class Upload
attr_accessor :file, :filename, :filename_ogg, :status, :title, :desc, :url
def initialize(file)
#file = file
#filename = #file[:filename].gsub(" ", "")
#filename_ogg = "#{#filename}.ogg"
##url = "http://s3.amazonaws.com/#{user}/#{#filename_ogg}"
end
def downandup
# code
end
def convert(file, file_ogg)
# code
end
def upload(file_ogg)
# code
#url = "http://s3.amazonaws.com/#{user}/#{file_ogg}"
# title and desc are accessed through $upload.title/$upload.desc
rec = Post.new(
:title => #title,
:description => #desc,
:author_id => Random.rand(5),
:time_uploaded => Time.now,
:filename_ogg => #url,
:comments_table => Random.rand(10),
)
rec.save
end
end
The file runs through fine, but when it comes for DataMapper to put it in the database, it won't go in, but when replaced with the static string, the data gets stored.
I wrote this ruby script to scrape product info from the manufacturer website. The scraping and storage of the product objects in an array works, but I can't figure out how to export the array data to a csv file. This error is being thrown:
scraper.rb:45: undefined method `send_data' for main:Object (NoMethodError)
I do not understand this piece of code. What's this doing and why isn't it working right?
send_data csv_data,
:type => 'text/csv; charset=iso-8859-1; header=present',
:disposition => "attachment; filename=products.csv"
Full code:
#!/usr/bin/ruby
require 'rubygems'
require 'anemone'
require 'fastercsv'
productsArray = Array.new
class Product
attr_accessor :name, :sku, :desc
end
# Scraper Code
Anemone.crawl("http://retail.pelicanbayltd.com/") do |anemone|
anemone.on_every_page do |page|
currentPage = Product.new
#Product info parsing
currentPage.name = page.doc.css(".page_headers").text
currentPage.sku = page.doc.css("tr:nth-child(2) strong").text
currentPage.desc = page.doc.css("tr:nth-child(4) .item").text
if currentPage.sku =~ /#\d\d\d\d/
currentPage.sku = currentPage.sku[1..-1]
productsArray.push(currentPage)
end
end
end
# CSV Export Code
products = productsArray.find(:all)
csv_data = FasterCSV.generate do |csv|
# header row
csv << ["sku", "name", "desc"]
# data rows
productsArray.each do |product|
csv << [product.sku, product.name, product.desc]
end
end
send_data csv_data,
:type => 'text/csv; charset=iso-8859-1; header=present',
:disposition => "attachment; filename=products.csv"
If you are new to Ruby, you should be using Ruby 1.9 or later, in which case you can use the built-in CSV output which builds in fast csv plus l18n support:
require 'csv'
CSV.open('filename.csv', 'w') do |csv|
csv << [sku, name, desc]
end
http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV.html
File.open('filename.csv', 'w') do |f|
f.write(csv_data)
end
It probably makes more sense to do:
#csv = FasterCSV.open('filename.csv', 'w')
and then write to it as you go along:
#csv << [sku, name, desc]
that way if your script crashes halfway through you've at least got half of the data.