csv file parse and upload giving error in ror - ruby-on-rails

This is the field on form, I am using
<%= f.file_field :file ,:url=>{:controller=>"retailers",:action=>"csv_import"}%>
The following is the controller code
def create
#retailer = Retailer.new(params[:retailer])
respond_to do |format|
if verify_recaptcha(:model =>#retailer ) && #retailer .save
# To notify newly registered user.
retailer_ids = [#retailer.id]
Emailer.on_notify_retailer(retailer_ids, 1, 0)
sign_in #retailer
format.html { redirect_to pages_about_path}
flash[:notice1] = "Thank you for registering with Chindi."
flash[:notice2] = "We will process your application and get back to you within 48 hours. Once approved, you will be able to create negotiable deals that Consumers can tailor to their needs."
flash[:notice3] = "You will be able to create, manage and administer your deals and your buyers in this easy to use control panel."
format.json { render json: pages_about_path, status: :created, location: #retailer }
else
#title = "Sign up"
format.html { render action: "new"}
flash[:notice1] = "Incorrect word verification. Are you sure you\'re human?"
format.json { render json: #retailer.errors, status: :unprocessable_entity }
end
end
csv_parse()
end
The above code is used to save the data into database. The CSV file #retailer.file_file_name is to be stored in database as well as it needs to be parsed and the values need to be stored in fields
csv_parse is used to parse the csvfile
I am able to save file in data
now i need to parse the csv file and store the individual fields in another database.
the code for csv_parse is as follows.
def csv_parse
#parsed_file=CSV.foreach(params[:dump][:file].original_filename)
n=0
#parsed_file.each do |row|
User_list.create(
:email=>row[0],
:first_name=>row[1],
:last_name=>row[2]).save
flash.now[:message]="CSV parse Successful, #{n} new records added to data base"
end
end
when I run this it gives the following error/s.
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]
please help me with the above error why is it throwing such an error
thanks in advance.

I just paste some peace of working for me code and hope it will help you:
first_line = true
file = File.open File.join(Rails.root, 'tmp/import/category.csv')
file.each do |line|
unless first_line
row = CSV::parse_line(line, ';')
category = Category.find_by_name(row[1]) || Category.create(:name => row[1], :target => 'basic')
category.update_attribute(:import_id, row[0])
else
first_line = false
end
end
I sometime wrote this code to import categories to my DB. Here you can change CSV file name and block for each iterator. Also first_line is description for fields and I was ignoring it.

def create
#retailer = Retailer.new(params[:retailer])
respond_to do |format|
# ... same as above
end
csv_parse(params[:retailer][:file].path)
private
def csv_parse(path)
rows = CSV.read(path)
rows.each do |row|
User_list.create(:email=> row[0], :first_name=>row[1], :last_name=>row[2])
end
flash.now[:message]= "CSV parse Successful, #{rows.size} new records added"
end
end

Related

How to display model error messages within notice in ruby

I did a date validation in model which should display a message on page, but for some reason it isn't. I need this message to be shown in notice on error. Currently I just see the message in controller (Order not registered) but I need to see the reason (Delivery date should be from now). How can I do that?
model
def delivery_date_from_now_only
if self.delivery_date.present? && self.delivery_date <= Date.today
self.errors.add(:delivery_date, messsage: 'Delivery date should be from now')
end
end
controller
def create
#order = Order.new(order_params)
#order.user = current_user
if #order.save
flash[:notice] = 'Order registered successfully'
return redirect_to #order
end
#warehouses = Warehouse.all.order(:name)
#suppliers = Supplier.all.order(:brand_name)
#users = User.all.order(:name)
flash.now[:alert] = 'Order not registered'
render :new, status: 422
end
if you call #order.valid? it will validate your model an also populate errors for that object. that means #order.errors.messages will be a hash with { :delivery_date => ["Delivery date should be from now"]} etc (other errors will be in there as well) which u can use to do some flashes.

Rails controller loop questions - update where exists

I have a form where people can either create one cardrequest or many via uploading a csv file with ids. I have it working to simply create the requests. There are two things left I need to do in this routine that I am not sure how to do and looking for advice on.
1.) I need to check the ids either from the file upload or the single form field against an active table. If they are not active alert the person of that.
2.) If a combination of empid and cardholdergroup already exist update that request with the new params that were passed through.
Here is my action. Any thoughts on how/where I should do those? Any advice is appreciated.
def create
if cardrequest_params[:file].present?
file_path = cardrequest_params[:file].path
#cardholdergroups = cardrequest_params[:cardholdergroup_ids].map do |cardholdergroup_id|
CSV.foreach(file_path) do |row|
#cardrequest = Cardrequest.create(empid: row[0], startdate: cardrequest_params[:startdate], enddate: cardrequest_params[:enddate], user_id: current_user.id, cardholdergroup_ids: cardholdergroup_id)
end
end
else
#cardholdergroups = cardrequest_params[:cardholdergroup_ids].map do |cardholdergroup_id|
#cardrequest = Cardrequest.create(empid: cardrequest_params[:empid], startdate: cardrequest_params[:startdate], enddate: cardrequest_params[:enddate], user_id: current_user.id, cardholdergroup_ids: cardholdergroup_id)
end
end
respond_to do |format|
if #cardrequest.save
format.html { redirect_to cardrequests_path, notice: "Cardrequest was successfully created." }
format.json { render :show, status: :created, location: #cardrequest }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #cardrequest.errors, status: :unprocessable_entity }
end
end
end
Well, there's a couple different ways you could go about this. If it were me, I would take the CSV parsing out of the server end entirely and do it with something like the JS library PapaParse. Have it send each of the fields to your create function one at a time. You could then easily use the find_or_create_by function or whatever logic you needed there to respond with a js message.
Then when they 'upload' with a csv file you could easily display a table of each of the csv line items and they're save/update results.
However, if you aren't a big javascript guy, I would at least separate the CSV upload from the create function into its own form.
# Cardrequest Controller
def csv_import
Cardrequest.import(params[:file])
end
Make a route for it...
Then put clean things up further by putting the CSV parse logic into the model:
# Cardrequest Model
def self.import(file)
# import logic here
CSV.foreach(file, headers: true) do |row|
row_hash = row.to_hash
match = Cardrequest.find_or_create_by(unique: row_hash["unique"])
match.update(#the rest of your data)
end
end
Hopefully this helps point you in the right direction.

Rails CSV export to server instead of download

I have a form which when submitted takes all the input and generates a csv. I am using CSV.open in my model so that the file is sent to the server. However, even with this, there is a separate CSV file with a random CSV code that is generated. It does not contain any form details, however, it would be ideal if no CSV is downloaded at all. I just want to CSV to get uploaded to the server.
Model:
def csv
attributes = %w{ first_name last_name }
CSV.open("#{Rails.root}/public/#{self.first_name}.csv", "wb") do |csv|
csv << attributes
csv << [ self.first_name, self.last_name ]
end
end
controller:
def method
if conditions
student = Student.find(params[:id])
respond_to do |format|
format.html {redirect_to students_path, :notice => "Success"}
format.csv { send_data student.csv }
end
else
redirect_to students_path, :notice => "Declined"
end
end
Please let me know whats wrong

Associate current_user with json response from API call in Rails

I need to tie the current user with the json response that I am capturing and storing in PostgreSql 9.4. I am using Rails 4. I am able to successfully store the json in a column 'return' of json data type. I have taken measures to create the model associations and updated the schema, and I have a user model with a record but the user_id remains nil in the Document record holding the json return. I list the controller as I'm nearly convinced that my problem is here.
require 'alchemyAPI/alchemyapi'
require 'json'
class AlchemyController < ApplicationController
def index
#documents = Document.all
end
def create
alchemyapi = AlchemyAPI.new()
response = alchemyapi.combined('url', params[:q], {'extract'=>'page-image, title, author, concept' })
puts JSON.pretty_generate(response)
if
Document.create(result: response)
flash[:notice] = "Input was successfully analyzed and persisted."
redirect_to action: 'index'
else
flash[:notice] = "Input was successfully analyzed and persisted."
redirect_to action: 'index'
end
end
end
Solution was for me to add the current user as depicted in the first two lines of the if block.
def create
alchemyapi = AlchemyAPI.new()
response = alchemyapi.combined('url', params[:q], {'extract'=>'page-image, title, author, concept' })
puts JSON.pretty_generate(response)
if
*#user = current_user*
*#user.documents.create(result: response)*
flash[:notice] = "Input was successfully analyzed and persisted."
redirect_to action: 'index'
else
flash[:error] = "There was a problem analyzing your input."
redirect_to action: 'index'
end
end

How can i use Rails' update_attributes with a file upload?

My update method of a Product controller is defined as follows:
def update
#product = Product.find(params[:id])
if params[:product][:image_path]
# Check if this product already has an image
File.delete(#product.full_image_path) if File.exist?(#product.full_image_path)
# Upload the new image
uploaded_img = params[:product][:image]
#product.image_path = Time.now.to_i.to_s + File.extname(uploaded_img.original_filename)
File.open(#product.full_image_path, 'w') do |file|
file.write(uploaded_img.read)
end
end
#product.name = params[:product][:name]
#product.description = params[:product][:description]
respond_to do |format|
if #product.errors.count == 0
format.html { redirect_to products_path, :notice => t(:product_updated) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #product.errors, :status => :unprocessable_entity }
end
end
end
This simply deletes the old image if already present, and uploads the new one. It also updates the Product attributes
How can I use #product.update_attributes(params[:product]) to avoid updating name and description attributes as I've done here?
If I do #product.update_attributes(params[:product]) I get an error because the params hash contains a value named "image" which is not an attribute of the object.
Thanks in advance
You could create an attribute setter for the image in the Product model called image=:
def image=(uploaded_img)
# Check if this product already has an image
File.delete(full_image_path) if File.exist?(full_image_path)
# Upload the new image
image_path = Time.now.to_i.to_s + File.extname(uploaded_img.original_filename)
File.open(full_image_path, 'w') do |file|
file.write(uploaded_img.read)
end
end
After that, remove the rest of the code in the controller and use #product.update_attributes(params[:product]).
I didn't tried it but I think it should work.
Do you know that you have some gems that allow to manage easily file upload like https://github.com/jnicklas/carrierwave or https://github.com/thoughtbot/paperclip
You should try to refactor your controller a bit, a controller should not be running any other tasks other than directing the traffic of your models and views. Try to move all your file operations to a separate helper.

Resources