I am new to Rails and I have figured out how to export results from my Database but I am having issues creating new records from a CSV File. With the code listed below I want to be able to import a CSV file and fill in the last two columns with session data from the user. For now I just inserted a static number to try to get this working. I currently receive "can't convert ActionDispatch::Http::UploadedFile into String" as the error message
CSV DOCUMENT
name,task,expected_results,require_id
Test Name 1,Open a File,Open,t
Test Name 2,Read a File,Read,t
Test Name 3,Close a File,Close,f
CONTROLLER
def csv_import
file = params[:file]
FasterCSV.foreach(file,{:headers => true, :row_sep => :auto}) do |row|
Script.create!(:name => row[0],
:task => row[1],
:expected_results => row[2],
:require_id => row[3],
:department_id => 1,
:category_id => 1)
end
end
VIEW
<%=form_tag '/script_admin/csv_import', :multipart => true do%>
<%= file_field_tag "file" %><br/>
<%= submit_tag("Import") %>
<% end %>
DB MIGRATION
class CreateScripts < ActiveRecord::Migration
def self.up
create_table :scripts do |t|
t.integer :department_id, :null => false
t.integer :category_id, :null => false
t.string :name, :null => false
t.string :task, :null => false
t.string :expected_results, :null => false
t.boolean :require_id, :null => false, :default => "t"
t.timestamps
end
end
def self.down
drop_table :scripts
end
end
Any help with this can be appreciated
~Kyle
Issue is resolved thanks to James Gray
def csv_import
file = params[:file]
FCSV.new(file.tempfile, :headers => true).each do |row|
Script.create!(:name => row[0],
:task => row[1],
:expected_results => row[2],
:require_id => row[3],
:department_id => 1,
:category_id => 1)
end
end
Related
In Rail, I have this schema (for a join table between car and user habtm)
create_table "cars_users", :id => false, :force => true do |t|
t.integer "user_id"
t.integer "car_id"
end
add_index "cars_users", ["car_id", "user_id"], :name => "index_cars_users_on_car_id_and_user_id"
add_index "cars_users", ["user_id", "car_id"], :name => "index_cars_users_on_user_id_and_car_id"
but due to some bug, I have duplicate rows in this table.
shouldn't the index handle that?
Try:
add_index :cars_users, [ :user_id, :car_id ], :unique => true, :name => 'by_user_and_car'
it will raise an exception but you can add your own validation
class User < ActiveRecord::Base
has_and_belongs_to_many :cars, :before_add => :validates_car
def validates_car(car)
errors.add(:car, "already created" ) if self.cars.include? car
end
end
I have a field that creates a comment (named pcomment). I am trying to get it to automatically add the user_id to the pcomment in the pcomment table like it adds the purchase_id automatically. I am not sure why the purchase_id is being recorded in the database but the user_id remains blank for each pcomment. Here is the form for the pcomment.
<%= form_for([purchase, purchase.pcomments.build], :html => { :id => "blah_form" }) do |f| %>
<div class="field">
<h4>What deal are you offering?</h4>
<%= f.text_field :body %>
</div>
<% end %>
It may be that I have to add some hidden_field, but I don't think so. I am using http://ruby.railstutorial.org/book/ruby-on-rails-tutorial#cha-user_microposts as resource and in that the microposts dont have any hidden_field. Instead, the user_id is indexed and it automatically is created upon the creation of a micropost (based on who is signed in at the time). This part is working for me too, adding to my rational that indexing user_id on the pcomments table is enough to automatically generate it. Here is my schema.rb file so that you can see the current state of my database.
ActiveRecord::Schema.define(:version => 20121011085147) do
create_table "pcomments", :force => true do |t|
t.string "body"
t.integer "purchase_id"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "pcomments", ["purchase_id"], :name => "index_pcomments_on_purchase_id"
add_index "pcomments", ["user_id"], :name => "index_pcomments_on_user_id"
create_table "purchases", :force => true do |t|
t.string "content"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "purchases", ["user_id", "created_at"], :name => "index_purchases_on_user_id_and_created_at"
create_table "sales", :force => true do |t|
t.string "content"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "sales", ["user_id", "created_at"], :name => "index_sales_on_user_id_and_created_at"
create_table "scomments", :force => true do |t|
t.string "body"
t.integer "sale_id"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "scomments", ["sale_id"], :name => "index_scomments_on_sale_id"
add_index "scomments", ["user_id"], :name => "index_scomments_on_user_id"
create_table "users", :force => true do |t|
t.string "name"
t.string "email"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "password_digest"
t.string "remember_token"
t.boolean "admin", :default => false
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
add_index "users", ["remember_token"], :name => "index_users_on_remember_token"
end
and the reason I know its not working is that I check in the database and the pcomment is successfully created with all columns filled in including purchase_id but the user_id is still blank. also, the user has_many pcomments and has_many purchases. The purchase has_many pcomments and belongs_to user. The pcomment belongs_to user and belong_to purchase.
also, here is the pcomments_controller.rb
class PcommentsController < ApplicationController
before_filter :signed_in_user
def create
#purchase = Purchase.find(params[:purchase_id])
#pcomment = #purchase.pcomments.build(params[:pcomment], :user_id => #purchase.user_id)
#pcomment.purchase = #purchase
if #pcomment.save
flash[:success] = "Offer submited!"
redirect_to :back
else
render 'shared/_pcomment_form'
end
end
def new
#pcomment=purchase.pcomments.new
end
end
def new
#pcomment=purchase.pcomments.new(:user_id => purchase.user_id)
end
end
purchase.pcomments.build builds empty Pcomment object just with purchase_id filled from purchase. To assign also user_id pass the hash with attribute:
purchase.pcomments.build(:user_id => purchase.user_id)
I loaded some seed data in using the code below, and it worked fine. Then, I needed to add two more columns, and I did so using the following steps, but it's not attaching the two new columns seed data to the table, what am I doing wrong?
Steps:
Add two columns using migration
Make them attr_accessible in the model
Replace old CSV file with new CSV file
Change the seed.rb file to plug in the new data
Run rake db:seed
Seed.rb
require 'csv'
Model.delete_all
CSV.foreach("#{Rails.root}/lib/data/model.csv") do |row|
Model.create!(:model_number => row[0], :areq => row[1], :length => row[2], :width => row[3], :depth => row[4], :material => row[5], :frame => row[6], :edge => row[7], :tubes => row[8], :tube_length => row[9])
end
Schema.rb
create_table "models", :force => true do |t|
t.string "model_number"
t.float "areq"
t.float "length"
t.float "width"
t.float "depth"
t.string "material"
t.string "frame"
t.float "edge"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.float "tubes"
t.float "tube_length"
end
Cant say this may work 100%
Try Model.reset_column_information above the seed file once
this should refresh the columns information in table.
require 'csv'
Model.reset_column_information
Model.delete_all
#......
just a guess check if the proper model.csv is getting loaded and have column 8 and 9 means have in all 10 columns.
I have three models: Post (has_many votes as votable), Comment (has_many votes as votable) and Votes (belongs_to votable).
This is votes_controller.rb:
class VotesController < ApplicationController
def vote_up
#votable = WHAT_TO_PLACE_HERE?.find(params[:id])
if #votable.votes.exists?(:user_id => current_user.id)
#notice = 'You already voted'
else
#vote = #post.votes.create(:user_id => current_user.id, :polarity => 1)
#votable.reload
end
respond_to do |format|
format.js
end
end
Relevant schema:
create_table "comments", :force => true do |t|
t.text "content"
t.integer "post_id"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "total_votes", :default => 0
end
add_index "comments", ["post_id", "user_id"], :name => "index_comments_on_micropost_id_and_user_id"
create_table "posts", :force => true do |t|
t.string "content"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "title"
t.integer "comments_count", :default => 0, :null => false
t.integer "total_votes", :default => 0
end
create_table "votes", :force => true do |t|
t.integer "votable_id"
t.string "votable_type"
t.integer "user_id"
t.integer "polarity"
t.integer "total"
t.datetime "created_at"
t.datetime "updated_at"
end
I need way to find the type of the votable element (Post or Comment) so I can assign it to #votable. Any suggestions to accomplish this?
EDIT:
views/posts/show.html.erb:
<%= link_to "Vote Up", vote_up_path(#post), :remote => true, :class => "vote-up" %><br />
routes.rb:
get 'votes/:id/vote_up' => 'votes#vote_up', as: 'vote_up'
Assuming the type is passed via params, you can do this:
params[:votable_type].constantize.find(params[:id])
Please check the documentation for constantize.
You can send the type by appending it as an argument to vote_up_path:
<%= link_to "Vote Up", vote_up_path(#post, :votable_type => 'Post'), :remote => true, :class => "vote-up" %>
Like this it will be added as a get parameter, which shouldn't be a problem. If you don't like this, you have to change your route and add :votable_type somewhere.
dear developers I have some problems with Rails models
Here is my sql tables
create_table "areas", :primary_key => "ndc", :force => true do |t|
t.string "townname", :limit => 256, :null => false
end
create_table "books", :primary_key => "ndc", :force => true do |t|
t.integer "booked", :null => false
t.integer "free", :null => false
end
class Book < ActiveRecord::Base
self.primary_key = "ndc"
has_one :area, :foreign_key => 'ndc'
end
class Area < ActiveRecord::Base
self.primary_key = "ndc"
belongs_to :book , :foreign_key => 'ndc'
end
in controller I have such code
#books = Book.paginate :page => params[:page] || 1, :per_page => 10
#books.each do |booking|
p booking.area
p booking
end
In production mode doesn't work, booking.area is nil object. what it can be ?
Area becames nil if config.cache_classes = true
so booking.area generates such queries
if cashe_classes = true
SELECT areas.* FROM areas WHERE (areas.ndc = NULL) LIMIT 1
but without cashing classes
SELECT areas.* FROM areas WHERE (areas.ndc = 30) LIMIT 1
FIXED by removing belongs_to :book , :foreign_key => 'ndc' from area class.
Your areas table needs a book_id integer field to match against the books table's primary key.