I have been trying to export a database to CSV in Rails. After many trials and errors, I finally got it to work, and right now my CSV consists of the full 2 tables.
However, I can't seem to be able to extract only certain columns from each table - hourlog name, hourlog description, hourlog hours, hourlog created_at and project name (marked in red in the photo attached).
All solutions I found online were for extracting the whole table.
This is my model (for hourlog):
class Hourlog < ApplicationRecord
belongs_to :user
belongs_to :project
accepts_nested_attributes_for :project
validates :name, presence: true
validates :description, presence: true
validates :hours, presence: true
validates :date, presence: true
validates :project, presence: true
def self.to_csv
CSV.generate do |csv|
csv << column_names
all.each do |hourlog|
csv << (hourlog.attributes.values_at(*column_names) + hourlog.project.attributes.values )
end
end
end
end
This is my controller (for hourlog):
def index
@user = User.all
@filter = Filter.first
@project = Project.all
[... a bunch of code that defines @hourlogs...]
respond_to do |format|
format.html
format.csv { render text: @hourlogs.to_csv }
end
end
This is the view:
<%= link_to "CSV", hourlogs_path(format: "csv") %>
This is the schema for hourlogs:
create_table "hourlogs", force: :cascade do |t|
t.string "name"
t.string "project"
t.text "description"
t.integer "hours"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.datetime "date"
t.integer "project_id"
t.datetime "date_from"
t.datetime "date_to"
t.string "project_filter"
t.index ["project_id"], name: "index_hourlogs_on_project_id", using: :btree
t.index ["user_id"], name: "index_hourlogs_on_user_id", using: :btree
end
And this is the schema of project:
create_table "projects", force: :cascade do |t|
t.string "name"
t.text "description"
t.string "plan"
t.integer "planhours"
t.integer "thours"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "plandate"
t.datetime "starthourtrack"
t.integer "duration"
t.text "notes"
t.boolean "status", default: true
end
Any help will be appreciated, I have been struggling for 10 hours now, and can't seem to get it. I tried creating a separate index.csv.erb file, outlining the header names, selecting hourlog.name, instead of hourlog.attributes.values_at(*column_names), but I can't seem to get the syntax/logic right. Thanks!
[EDIT: SOLUTION] It looks like I simply needed some brackets - I added specific column names to limit the # of columns displayed, and then I wrote out each column I needed (hourlog.name, hourlog.description etc.) - I didn't realize I needed to put those in [], after "csv <<" which did the trick.
def self.to_csv
CSV.generate do |csv|
column_names = %w(Project Name Description Hours Date)
csv << column_names
all.each do |hourlog|
csv << [hourlog.project.name, hourlog.name, hourlog.description, hourlog.hours, hourlog.created_at]
end
end
end
It looks like I simply needed some brackets - I added specific column names to limit the # of columns displayed, and then I wrote out each column I needed (hourlog.name, hourlog.description etc.) - I didn't realize I needed to put those in [], after "csv <<" which did the trick.
def self.to_csv
CSV.generate do |csv|
column_names = %w(Project Name Description Hours Date)
csv << column_names
all.each do |hourlog|
csv << [hourlog.project.name, hourlog.name, hourlog.description, hourlog.hours, hourlog.created_at]
end
end
end