After setting up the apache server When we choose the .csv file to be imported I get the following error message:
TypeError in ProductImportsController#create:
no implicit conversion of ActiveSupport::HashWithIndifferentAccess into String
My product_imports_controller.rb:
require 'csv'
class ProductImportsController < ApplicationController
def new
#product_import = ProductImport.new
end
def create
csv_text = File.read(params[:product_import])
csv = CSV.parse(csv_text, :headers => true)
csv.each do |row|
ProductImport.create!(row.to_hash)
end
end
end
Try this:
The issue is that there is a security aspect with hashes in Controllers.
You try row.to_hash.permit! but i'll doubt that it will work
Create it in the model:
require 'csv'
class ProductImportsController < ApplicationController
def new
#product_import = ProductImport.new
end
def create
csv_text = File.read(params[:product_import])
csv = CSV.parse(csv_text, :headers => true)
csv.each do |row|
ProductImport.create_from_csv(row.to_hash)
end
end
end
class ProductImport < ActiveRecord::Base
def self.create_from_csv(data)
self.create!(data)
end
end
Related
I'm trying to load my csv file to my rails database using postgresql engine.However, it returns an empty array when I test with postman to GET the data from my database.
My ruby code implemented in my lib directory:
require 'csv'
CSV.foreach('lib/seeds/glints.csv', headers: true, encoding: 'ISO-8859-1', col_sep: ';') do |row|
new_empty_aaray = []
new_empty_aaray << row.to_h
puts new_empty_aaray
end
puts "There are now #{AllRestaurant.count} rows in the all_restaurants table"
I then run rails db:seed to seed the data to database
my controller:
class AllRestaurantsController < ApplicationController
before_action :find_all_restaurant, only: [:show]
def index
#all_restaurants = AllRestaurant.all
render json: #all_restaurants
end
def show
render json: #all_restaurant
end
private
def find_all_resstaurant
#all_restaurant = AllRestaurant.find(params[:id])
end
end
path to the csv file in the lib folder lib/seeds/glints.csv
I really don't know what I'm missing
I am trying to open a file on rails user model with ruby and call it from user controller but it kept throwing me back wrong number of arguments (given 0, expected 1..3).
This is my file directory 'app' ,'assets', 'files', 'test_list.txt'
'app' ,'controllers', 'users controller'
can you help?thanks
class User < ApplicationRecord
def self.my_method
my_array = []
file = File.join(Rails.root, 'app' 'models','assets', 'files', 'test_list.txt')
File.open.each do |line|
my_array << line.gsub!(/\n?/, "")
end
return my_array.to_s
end
end
class UsersController < ApplicationController
require 'open-uri'
require 'net/http'
def show
# uri = URI('https://gist.githubusercontent.com/Kalagan/3b26be21cbf65b62cf05ab549433314e/raw')
# data = Net::HTTP.get(uri)
# anagrams = data.split(/\n/)
#vari = User.my_method
#query = params[:query]
#results = anagrams.select { |word| #query.split('').sort.join == word.split('').sort.join }
end
end
You're passing nothing to the open method. Pass the filename
Change
File.open
to
File.open(file)
open method needs to know at least the filename it has to open
I think you missed a comma.You can write the below code.
file = File.join(Rails.root, 'app', 'models','assets', 'files', 'test_list.txt')
and for reading the content
File.read(file) do |file|
file.each do |line|
p line
end
end
So I have the controller who scrapes the entire html of a page and stores it into mysql database. Before I store the data I want to encode it using the htmlentities gem. My issue is that with some websites it works ok e.g https://www.lookagain.co.uk/ but with others I get invalid byte sequence in UTF-8 such as https://www.google.co.uk/ and I do not know why. At first I though it might be something wrong with the database so I have changed all the fields to LONGTEXT but the problem still persists
Controller:
class PageScraperController < ApplicationController
require 'nokogiri'
require 'open-uri'
require 'diffy'
require 'htmlentities'
def scrape
#url = watched_link_params[:url].to_s
puts "LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOG#{#url}"
#page = Nokogiri::HTML(open(#url))
coder = HTMLEntities.new
#encodedHTML = coder.encode(#page)
create
end
def index
#savedHTML = ScrapedPage.all
end
def show
#savedHTML = ScrapedPage.find(id)
end
def new
#savedHTML = ScrapedPage.new
end
def create
#savedHTML = ScrapedPage.create(domain: #url, html: #encodedHTML, css: '', javascript: '')
if #savedHTML.save
puts "ADDED TO THE DATABASE"
redirect_to(root_path)
else
puts "FAILED TO ADD TO THE DATABASE"
end
end
def edit
end
def upadate
end
def delete
#watched_links = ScrapedPage.find(params[:id])
end
def destroy
#watched_links = ScrapedPage.find(params[:id])
#watched_links.destroy
redirect_to(root_path)
end
def watched_link_params
params.require(:default).permit(:url)
end
end
Having followed the RailsCast on importing CSV (http://railscasts.com/episodes/396-importing-csv-and-excel), I am trying to validate that the file being uploaded is a CSV file.
I have used the gem csv_validator to do so, as documented here https://github.com/mattfordham/csv_validator
And so my model looks like this:
class Contact < ActiveRecord::Base
belongs_to :user
attr_accessor :my_csv_file
validates :my_csv_file, :csv => true
def self.to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
all.each do |contact|
csv << contact.attributes.values_at(*column_names)
end
end
end
def self.import(file, user)
allowed_attributes = ["firstname","surname","email","user_id","created_at","updated_at", "title"]
CSV.foreach(file.path, headers: true) do |row|
contact = find_by_email_and_user_id(row["email"], user) || new
contact.user_id = user
contact.attributes = row.to_hash.select { |k,v| allowed_attributes.include? k }
contact.save!
end
end
end
But my system still allows me to select to import non-CSV files (such as .xls), and I receive the resulting error: invalid byte sequence in UTF-8.
Can someone please tell me why and how to resolve this?
Please note that I am using Rails 4.2.6
You can create a new class, let's say ContactCsvRowValidator:
class ContactCsvRowValidator
def initialize(row)
#row = row.with_indifferent_access # allows you to use either row[:a] and row['a']
#errors = []
end
def validate_fields
if #row['firstname'].blank?
#errors << 'Firstname cannot be empty'
end
# etc.
end
def errors
#errors.join('. ')
end
end
And then use it like this:
# contact.rb
def self.import(file, user)
allowed_attributes = ["firstname","surname","email","user_id","created_at","updated_at", "title"]
if file.path.split('.').last.to_s.downcase != 'csv'
some_method_which_handle_the_fact_the_file_is_not_csv!
end
CSV.foreach(file.path, headers: true) do |row|
row_validator = ContactCsvRowValidator.new(row)
errors = row_validator.errors
if errors.present?
some_method_to_handle_invaid_row!(row)
return
end
# other logic
end
end
This pattern can easily be modified to fit your needs. For example, if you need to have import on several different models, you could create a base CsvRowValidator to provide basic methods such as validate_fields, initialize and errors. Then, you could create a class inheriting from this CsvRowValidator for each model you want, having its own validations implemented.
I am going to create an rail application to import a csv file and showing its content in webpage. Everything is working fine except one thing. If the csv file contains quoted strings such as "", ",'' then the program is not working.
My app/models/user.rb file is :-
class User < ActiveRecord::Base
require 'csv'
def self.import(file)
CSV.foreach(file.path, headers:true) do |row|
User.create! row.to_hash
end
end
end
You can create a rescue for this error use code like this -
may be it works for you!
def self.import(file)
quote_chars = %w(" | ~ ^ & *)
begin
CSV.foreach(file, headers: :first_row, quote_char: quote_chars.shift) do |row|
User.create! row.to_hash
end
rescue CSV::MalformedCSVError
quote_chars.empty? ? raise : retry
end
end