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.
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 following the tutorial http://www.funonrails.com/2012/01/csv-file-importexport-in-rails-3.html]for upload files in rails 3, because I need that my app's user could upload csv files but when I tried to save the file I get: uninitialized constant CustomersController::CSV message, before change my routes to get "customers/import" to post "customers/import" I had other error No route matches [POST] "/customers/import" what Im doing wrong? thanks in advance.
MY CONTROLLER:
class CustomersController < ApplicationController
def import
if request.post? && params[:file].present?
infile = params[:file].read
n, errs = 0, []
CSV.parse(infile) do |row|
n += 1
# SKIP: header i.e. first row OR blank row
next if n == 1 or row.join.blank?
# build_from_csv method will map customer attributes &
# build new customer record
customer = Customer.build_from_csv(row)
# Save upon valid
# otherwise collect error records to export
if customer.valid?
customer.save
else
errs << row
end
end
# Export Error file for later upload upon correction
if errs.any?
errFile ="errors_#{Date.today.strftime('%d%b%y')}.csv"
errs.insert(0, Customer.csv_header)
errCSV = CSV.generate do |csv|
errs.each {|row| csv << row}
end
send_data errCSV,
:type => 'text/csv; charset=iso-8859-1; header=present',
:disposition => "attachment; filename=#{errFile}.csv"
else
flash[:notice] = I18n.t('customer.import.success')
redirect_to import_url #GET
end
end
end
end
MY MODEL:
class Customer < ActiveRecord::Base
scope :active, where(:active => true)
scope :latest, order('created_at desc')
def self.csv_header
"First Name,Last Name,Email,Phone,Mobile, Address, FAX, City".split(',')
end
def self.build_from_csv(row)
# find existing customer from email or create new
cust = find_or_initialize_by_email(row[2])
cust.attributes ={:first_name => row[0],
:last_name => row[1],
:email => row[3],
:phone => row[4],
:mobile => row[5],
:address => row[6],
:fax => row[7],
:city => row[8]}
return cust
end
def to_csv
[first_name, last_name, email, phone, mobile, address, fax, city]
end
end
*MY VIEW:
<h1>Subir Archivos</h1>
<%= form_tag('import', :multipart => true) do %>
<p>
File:<br />
<%= file_field_tag 'file' %><br />
</p>
<p>
<%= submit_tag "subir" %>
</p>
<% end %>
MY ROUTES:
Pruebaupcsv::Application.routes.draw do
post "customers/import"
You need to add a require 'csv' before you use it, either in an initializer, or at the top of your controller.
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
I am trying to create a unique json data structure, and I have run into a problem that I can't seem to figure out.
In my controller, I am doing:
favorite_ids = Favorites.all.map(&:photo_id)
data = { :albums => PhotoAlbum.all.to_json,
:photos => Photo.all.to_json(:favorite => lambda {|photo| favorite_ids.include?(photo.id)}) }
render :json => data
and in my model:
def as_json(options = {})
{ :name => self.name,
:favorite => options[:favorite].is_a?(Proc) ? options[:favorite].call(self) : options[:favorite] }
end
The problem is, rails encodes the values of 'photos' & 'albums' (in my data hash) as JSON twice, and this breaks everything... The only way I could get this to work is if I call 'as_json' instead of 'to_json':
data = { :albums => PhotoAlbum.all.as_json,
:photos => Photo.all.as_json(:favorite => lambda {|photo| favorite_ids.include?(photo.id)}) }
However, when I do this, my :favorite => lambda option no longer makes it into the model's as_json method.......... So, I either need a way to tell 'render :json' not to encode the values of the hash so I can use 'to_json' on the values myself, or I need a way to get the parameters passed into 'as_json' to actually show up there.......
I hope someone here can help... Thanks!
Ok I gave up... I solved this problem by adding my own array methods to handle performing the operations on collections.
class Array
def to_json_objects(*args)
self.map do |item|
item.respond_to?(:to_json_object) ? item.to_json_object(*args) : item
end
end
end
class Asset < ActiveRecord::Base
def to_json_object(options = {})
{:id => self.id,
:name => self.name,
:is_favorite => options[:favorite].is_a?(Proc) ? options[:favorite].call(self) : !!options[:favorite] }
end
end
class AssetsController < ApplicationController
def index
#favorite_ids = current_user.favorites.map(&:asset_id)
render :json => {:videos => Videos.all.to_json_objects(:favorite => lambda {|v| #favorite_ids.include?(v.id)}),
:photos => Photo.all.to_json_objects(:favorite => lambda {|p| #favorite_ids.include?(p.id)}) }
end
end
I think running this line of code
render :json => {:key => "value"}
is equal to
render :text => {:key => "value"}.to_json
In other words, don't use both to_json and :json.
I currently have three methods which I want to collapse into one:
def send_email(contact,email)
end
def make_call(contact, call)
return link_to "Call", new_contact_call_path(:contact => contact, :call => call, :status => 'called')
end
def make_letter(contact, letter)
return link_to "Letter", new_contact_letter_path(:contact => contact, :letter => letter, :status => 'mailed')
end
I want to collapse the three into one so that I can just pass the Model as one of the parameters and it will still correctly create the path_to. I am trying to do this with the following, but stuck:
def do_event(contact, call_or_email_or_letter)
model_name = call_or_email_or_letter.class.name.tableize.singularize
link_to "#{model_name.camelize}", new_contact_#{model_name}_path(contact, call_or_email_or_letter)"
end
Thanks to the answers here, I have tried the following, which gets me closer:
link_to( "#{model_name.camelize}", send("new_contact_#{model_name}_path",
:contact => contact,
:status => "done",
:model_name => model_name) )
But I can't seem to figure out how to past the #{model_name} when it is an :attribute and then send the value of model_name, not as a string, but referring the object.
I got this to work: -- giving points to Kadada because he got me in the right direction :)
def do_event(contact, call_or_email_or_letter)
model_name = call_or_email_or_letter.class.name.tableize.singularize
link_to( "#{model_name.camelize}", send("new_contact_#{model_name}_path",
:contact => contact,
:status => 'done',
:"#{model_name}" => call_or_email_or_letter ) )
end
Try this:
def do_event(contact, call_or_email_or_letter)
model_name = call_or_email_or_letter.class.name.tableize.singularize
link_to( "#{model_name.camelize}", send("new_contact_#{model_name}_path",
contact, call_or_email_or_letter) )
end