I'm attempting to import a tab separated file using FasterCSV. I've tried various things and get varying errors. In it's current state i'm getting a "undefined method `tempfile'" error.
I've added the fastercsv code to my create action as bulk import is the only way data will be added to this model.
Here's my code. Can anyone help please? Any assistance would be really appreciated!!
My Model:
class AppleSale < ActiveRecord::Base
end
My Controller:
require 'fastercsv'
require 'tempfile'
class AppleSalesController < ApplicationController
def new
#apple_sale = AppleSale.new
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #apple_sale }
end
end
def create
file = params[:tsv_file]
FasterCSV.new(file.tempfile, {:headers => true, :quote_char=>'"', :col_sep =>"\t"}) do |row_data|
new_record = AppleSale.first_or_new(
'provider' => row_data['provider'],
'provider_country' => row_data['provider_country'],
'vendor_identifier' => row_data['vendor_identifier'],
'upc' => row_data['upc'],
'isrc' => row_data['isrc'],
'artist_show' => row_data['artist_show'],
'title' => row_data['title'],
'label_studio_network' => row_data['label_studio_network'],
'product_type_identifier' => row_data['product_type_identifier'],
'units' => row_data['units'],
'royalty_price' => row_data['royalty_price'],
'download_date' => row_data['download_date'],
'order_id' => row_data['order_id'],
'postal_code' => row_data['postal_code'],
'customer_identifier' => row_data['customer_identifier'],
'report_date' => row_data['report_date'],
'sale_return' => row_data['sale_return'],
'customer_currency' => row_data['customer_currency'],
'country_code' => row_data['country_code'],
'royalty_currency' => row_data['royalty_currency'],
'preorder' => row_data['preorder'],
'isan' => row_data['isan'],
'customer_price' => row_data['customer_price'],
'apple_identifier' => row_data['apple_identifier'],
'cma' => row_data['cma'],
'asset_content_flavor' => row_data['asset_content_flavor'],
'vendor_order_code' => row_data['vendor_order_code'],
'grid' => row_data['grid'],
'promo_code' => row_data['promo_code'],
'parent_identifier' => row_data['parent_identifier'],
'apple_identifier' => row_data['apple_identifier']
)
new_record.save
end
end
end
My Form View:
<%= form_for(#apple_sale, :multipart => true) do |f| -%>
<%= f.file_field :tsv_file %>
<%= f.submit "Upload >>", :class => "submit" %>
<% end %>
My Gemfile contains:
gem 'fastercsv'
Thanks in advance!!
UPDATE FOR OTHERS THAT MIGHT NEED THIS, I CAN'T ANSWER MY OWN QUESTION YET:
It was all in the controller, have changed to the following. This seems to work perfectly.
def create
uploaded_io = params[:apple_sale][:tsv_file]
File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'w') do |file|
file.write(uploaded_io.read)
end
FasterCSV.foreach(uploaded_io.original_filename, {:headers => true, :col_sep =>"\t"}) do |row_data|
new_record = AppleSale.new(
'provider' => row_data[0],
'provider_country' => row_data[1],
'vendor_identifier' => row_data[2],
'upc' => row_data[3],
'isrc' => row_data[4],
'artist_show' => row_data[5],
'title' => row_data[6],
'label_studio_network' => row_data[7],
'product_type_identifier' => row_data[8],
'units' => row_data[9],
'royalty_price' => row_data[10],
'download_date' => row_data[11],
'order_id' => row_data[12],
'postal_code' => row_data[13],
'customer_identifier' => row_data[14],
'report_date' => row_data[15],
'sale_return' => row_data[16],
'customer_currency' => row_data[17],
'country_code' => row_data[18],
'royalty_currency' => row_data[19],
'preorder' => row_data[20],
'isan' => row_data[21],
'customer_price' => row_data[22],
'apple_identifier' => row_data[23],
'cma' => row_data[24],
'asset_content_flavor' => row_data[25],
'vendor_order_code' => row_data[26],
'grid' => row_data[27],
'promo_code' => row_data[28],
'parent_identifier' => row_data[29]
)
new_record.save
end
respond_to do |format|
format.html { redirect_to apple_sales_path, :notice => "Successfully imported sales." }
end
end
1: I don't think FasterCSV accepts a block with new.
2: According to the Rails 3.1 docs - when you implement a file upload form:
http://guides.rubyonrails.org/form_helpers.html#uploading-files
...the resulting param is an IO object, which is not necessarily a plain file.
Looking at the FasterCSV source it looks like parse accepts an IO object + a block,
so I think something like this should do it:
FasterCSV.parse(file, ...) do |row_data|
...
end
Related
I am using sitemap_generator for my rails app. I was able to generate sitemap for everything except for video links on the website. Following is my
sitemap.rb
Equipment.find_each do |e|
add search_equipments_path(e), :changefreq => 'weekly'
end
Equipment.find_each do |more|
add equipment_details_path(more), :changefreq => 'weekly'
end
Category.find_each do |c|
add search_equipments_path(:category_id=>c.id), :changefreq => 'weekly'
end
Category.find_each do |sub|
add search_equipments_path(:sub_category=>sub.id), :changefreq => 'weekly'
end
Service.find_each do |s|
add service_details_path(s), :changefreq => 'weekly'
end
WantedEquipment.find_each do |f|
add wanted_equipments_path(f), :changefreq => 'weekly'
end
StaticPage.find_each do |t|
add benefits_for_buyers_path(t), :changefreq => 'weekly'
end
StaticPage.find_each do |sel|
add benefits_for_sellers_path(sel), :changefreq=> 'weekly'
end
StaticPage.find_each do |ser|
add benefits_for_service_providers_path(ser), :changefreq=> 'weekly'
end
add '/about-us'
add '/terms-and-conditions'
add '/pricing-plans'
add '/how-it-work'
This what is given on the documentation on the gem page for generating video sitemap:
SitemapGenerator::Sitemap.create do
add('/index.html', :video => {
:thumbnail_loc => 'http://www.example.com/video1_thumbnail.png',
:title => 'Title',
:description => 'Description',
:content_loc => 'http://www.example.com/cool_video.mpg',
:tags => %w[one two three],
:category => 'Category'
})
end
I am not able to understand how to pass these values dynamically.
If you want to generate video contents on basis of dynamic data, try this:
Model.all.each do |e|
video = VideoInfo.new(e.video_url)
add("https://example.com/views/#{e.slug}", :video => {
:thumbnail_loc => "#{video.thumbnail_medium}",
:title => "#{video.title}",
:description => "#{video.description}",
:content_loc => "#{e.video_url}",
:tags => e.slug.split('-'),
:player_loc => video.embed_url
})
end
Here VideoInfo is gem used for getting video meta info.
Can you use this sample but change it to your model name:
SitemapGenerator::Sitemap.create do
add '/contact_us', 'changefreq': 'weekly'
Article.find_each do |article|
add article_path(article), lastmod: article.updated_at
end
end
As you can see he makes find_each on articles model. So you can do the same on your video model.
I'm trying to create a line graph of weights for a user off of the lazy high charts gem.
I currently have in my users_controller
def show
#user = User.find(params[:id])
#weights = Weight.where(user_id: #user.id)
#weight_hash = #weights.to_json
#chart = LazyHighCharts::HighChart.new('graph') do |f|
f.title(:text => "Historical Weights")
f.xAxis(:type => 'datetime', :title => {:text =>'Date'})
f.yAxis(:title => {:text => "pounds"})
f.series(:name => 'Weight', :data => #weight_hash)
f.chart({defaultSeriesType => 'line'})
end
end
Within my weight model I have:
class Weight < ActiveRecord::Base
belongs_to :user
def as_json(*args)
{
:weight => self.weight,
:date => self.date
}
end
end
Then in my users/show.html.erb I have
<%= high_chart("Weight", #chart) %>
but i'm getting the error
undefined local variable or method `defaultSeriesType' for
#
I'm not sure how this method should be declared as it is part of the gem. Could anyone please explain what is going on?
In this line:
f.chart({defaultSeriesType => 'line'})
It looks like you forgot to add a colon to defaultSeriesType to make it a symbol, so Ruby thinks it's a variable/method. Try changing it to:
f.chart({:defaultSeriesType => 'line'})
...like the other hashes.
I have this render expression in a Ruby on Rails 4 controller:
render :json => #account_preferences, :include => {:payment_methods => {:include => {:payment_type => {:only => [:id, :name]}}}}
Can I filter the payment_methods somehow in this expression to get only the payment_methods with state = 'Confirmed'?
I don't believe you can do this conditionally in the render :json.
But something like this would work:
class AccountPreference < ActiveRecord::Base
has_many :confirmed_payment_methods,-> { where state: 'Confirmed' }, class_name: 'PaymentMethod'
end
and call that association in your to_json
render :json => #account_preferences, :include => {:confirmed_payment_methods => {:include => {:payment_type => {:only => [:id, :name]}}}}
If you do a lot of includes and conditionals I'd recommend using jbuilder to do this kind of stuff.
Did you take a look at that?
https://github.com/rails/jbuilder
It's included in your Gemfile by default in a rails 4 project.
I'm converting an application from rails 2 to rails 3 and could somebody please help me regarding this small bit of code. The link_to is not working , could some one point me how to use link_to instead of the link_to_remote in rails 3.1 properly?
Rails 2 code
<%= link_to_remote package_item.getId(),
:url => { :controller => 'cmn/popup',
:action => "show_popup",
:frame_url => admin_url(
:ctrl => controller,
:app_action => 'package.item.edit',
:id => package_item.getId().to_s,
:remote => true
),
:frame_width => '570px',
:frame_height => '355px'
}
%>
Rails 3.1 code
<%= link_to package_item.getId(),
:url => { :controller => 'cmn/popup',
:action => "show_popup",
:frame_url => admin_url(
:ctrl => controller,
:app_action => 'package.item.edit',
:id => package_item.getId().to_s
),
:frame_width => '570px',
:frame_height => '355px',
:remote => true
}
%>
I replace all .rjs file with .js.erb. This is the URL I'm getting in Rails 3:
3
This is in Rails 2:
2
my controller
def show_popup
#content_data = {}
#content_data.merge!(params)
render(:template => 'cmn/popup/show_popup', :nolayout => 1)
end
Please look at the syntax of link_to in Rails 3:
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to
You have all your parameters in a :url hash, but you don't need to name it :url, just pass in the options in a hash, like this:
<%= link_to package_item.getId(),
{
:controller => 'cmn/popup',
:action => "show_popup",
:frame_url => admin_url(
:ctrl => controller,
:app_action => 'package.item.edit',
:id => package_item.getId().to_s
),
:frame_width => '570px',
:frame_height => '355px'
},
:remote => true
%>
Remember to get :remote out of the url hash.
Let me know if this works.
It is the first time I see a string defining a path as a :controller param.
I mean de :controller => 'cmn/popup'. This is new to me, and it feels strange.
Are you sure this works and the request is being received by the correct controller and action?
Another thing i think it can be tricky is the render call on the controller. Just call
render :layout => false
or maybe dont call anything at all.
If the template has the same name than the action and it is placed in a directory named like the controller, rails knows what template needs to be rendered and the extension (js/html/xml) based on the request type. Maybe render :template => .... forces to render an html template.
The :nolayout option i think it is invalid. Anyway, if the request is for a javascript file, it never renders layout.
I have this in my controller:
#statics = [{'home' => 'about'},
{'home' => 'termsandconditions'},
{'home' => 'information'},
{'news' => 'archives'}]
and in my view:
#statics.each do |controller, action|
xml.loc url_for(:only_path => false, :controller => controller, :action => action)
xml.lastmod w3c_date(Time.now)
xml.changefreq "weekly"
xml.priority 0.8
end
the URLs aren't what I would expect, e.g.
http://localhost:3000/homeinformation
instead of
http://localhost:3000/information
However, I just did this manually, I get the right URL:
url_for(:only_path => false, :controller => 'brownies', :action => 'index') #works!
What am I missing here?
#statics is an array with one hash entry, so you'll need your each block to take just a single parameter and split it up inside the block.