how to save CSV file for COPY to postgresql table - ruby-on-rails

I am trying to copy a CSV file to populate one of the tables and have been struggling. I would appreciate any hints or help understanding how this should work.
Edit: I am working in Cloud9 IDE.
I have tried putting the file in various locations, including this Shared folder which should be accessible:
thenutritionalgorithm_development=# COPY foods FROM '/Users/Shared/rake.csv';
ERROR: could not open file "/Users/Shared/rake.csv" for reading: No such file or directory
When I try \COPY, the error message is different:
thenutritionalgorithm_development=# \COPY foods FROM '/Users/Shared/rake.csv';
/Users/Shared/rake.csv: No such file or directory
The tables in this database are all owned by ‘ubuntu,’ which is my current user.
List of relations
Schema | Name | Type | Owner
--------+-------------------+-------+--------
public | foods | table | ubuntu
public | lists | table | ubuntu
public | quantities | table | ubuntu
public | schema_migrations | table | ubuntu
My database.yml file indicates that ‘ubuntu’ should be the user with access to these databases.
development:
adapter: postgresql
encoding: UTF8
pool: 5
username: ubuntu
password: password
database: thenutritionalgorithm_development
test:
adapter: postgresql
encoding: UTF8
pool: 5
username: ubuntu
password: password
database: thenutritionalgorithm_test
production:
adapter: postgresql
encoding: UTF8
pool: 5
username: ubuntu
password: password
database: thenutritionalgorithm_production
I should note that I am fairly confused/fuzzy on the concept of users in this context. Do the user and password in the .yml have to be anything in particular?
I've granted all privileges to the user ubuntu:
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------+-------------------+----------+-----------------------+--------------------------
public | foods | table | ubuntu=arwdDxt/ubuntu |
public | foods_id_seq | sequence | |
public | lists | table | |
public | lists_id_seq | sequence | |
public | quantities | table | |
public | quantities_id_seq | sequence | |
public | schema_migrations | table | |
I thought that maybe the solution would be to somehow save the file in the database cluster, but I'm not sure how to do that in practice (if that even makes sense as something that could be done). I created the databases using a simple bundle exec rake db:create after writing the .yml file.
In general, I am confused about how and where to save the .CSV file so that it can COPY interact with my postgresql database.
Thank you for any suggestions or tips.

After much trial and error, I have devised an approach that consistently works. It may not be the most efficient or elegant and I appreciate suggested improvements. This is for Cloud9, though I think most if not all can be applied generally. I'm assuming you're starting from scratch or able to delete/rebuild your existing PostgreSQL databases.
Start the PostgreSQL server.
$ sudo service postgresql start
If you have existing PostgreSQL databases that do not contain important data, delete them one at a time.
$ sudo sudo -u postgres psql
# DROP DATABASE "database_one";
# DROP DATABASE "database_two";
Assuming you have three databases (development, test, and production), write your database.yml file like this. The reason it works this way is related to how PostgreSQL comes preinstalled on every Cloud9 workspace.
development:
adapter: postgresql
encoding: UTF8
pool: 5
username: <%= ENV['USERNAME'] %>
password: <%= ENV['PASSWORD'] %>
host: <%= ENV['IP'] %>
database: yourapp_development
test:
host: <%= ENV['IP'] %>
adapter: postgresql
encoding: UTF8
pool: 5
username: <%= ENV['USERNAME'] %>
password: <%= ENV['PASSWORD'] %>
database: yourapp_test
production:
host: <%= ENV['IP'] %>
adapter: postgresql
encoding: UTF8
pool: 5
username: <%= ENV['USERNAME'] %>
password: <%= ENV['PASSWORD'] %>
database: yourapp_production`
Create your development and test databases.
$ bundle exec rake db:create
$ bundle exec rake db:migrate
Creation of the production database requires separate commands.
$ RAILS_ENV=production rake db:create
$ RAILS_ENV=production rake db:migrate
Enter the PostgreSQL server. For each table, change the owner of the table to ubuntu.* Grant all privileges on each table to ubuntu.
$ sudo sudo -u postgres psql
# \c yourapp_development
# ALTER TABLE table_dining OWNER TO ubuntu;
# ALTER TABLE table_kitchen OWNER TO ubuntu;
# ALTER TABLE lists OWNER TO ubuntu;
# ALTER TABLE schema_migrations OWNER TO ubuntu;
# GRANT ALL PRIVILEGES ON table_dining TO ubuntu;
# GRANT ALL PRIVILEGES ON table_kitchen TO ubuntu;
# \c postgres
Repeat this for each database. To view/verify the owner of a database table, use the following commands.
# \c yourapp_development
# \dt
Only for the tables you will be populating using the CSV file: Delete the created_at and updated_at columns that get automatically created.
ALTER TABLE table_dining DROP COLUMN created_at RESTRICT, DROP COLUMN updated_at RESTRICT;
Build a CSV file where Row 1 contains the names of the attributes. Name the first column id and manually add id numbers. Be sure that the CSV columns are (left-to-right) in the same order as how the attributes are added to the database table in your migrations. If you want to change the order of the columns, edit or recreate your migration files and clear and recreate your database (repeat steps 2 and 4).
Save your CSV file to the /db folder by dragging and dropping or File/Upload local files from the Cloud9 menu. I think any folder would work, but I refer to the /db folder in these instructions. Since I often repeat this process of uploading/replacing data, I find it useful to always name the file "rake.csv" and replace the file it each time so that I don't end up "storing" or relying on data in /db. This is meant to be just a temporary location.**
Move the newly created rake.csv file to your /tmp folder with the following command.
$ scp db/rake.csv //tmp/rake.csv
Enter the PostgreSQL server and the database where the CSV data will be added. Delete all contents of your database if you mean to recreate it completely.
$ sudo sudo -u postgres psql
# \c yourapp_development
# DELETE FROM table_dining;
If you want to check whether there is any data in the table, use the following command.
# \d+ table_dining;
Or perhaps it would be enough to see how many rows of data are in the table.
# SELECT COUNT(*) FROM table_dining;
Finally! Add the CSV data to your table.
# copy table_dining from '/tmp/rake.csv' with CSV HEADER;
Once you've done this with all of your databases, you can view the data in PostgreSQL or on the Cloud9 terminal.
Once you've populated the production database and wish to push it to heroku (assuming you are starting "from scratch" and do not need to preserve heroku data), use the following commands.
$ heroku pg:reset DATABASE
$ heroku pg:push yourapp_production DATABASE_URL
$ git add -A
$ git c
$ git commit -m "message"
$ git push
$ heroku pg:push yourapp_production DATABASE_URL
$ git push heroku
$ heroku restart
I hope this is helpful! Please let me know any edits/methods you recommend.
*I suspect this step could be avoided if the database.yml file were written differently, but I am too far along/afraid to make this change at this time. I will edit if someone can corroborate this or if I end up trying it.
**I'm almost certain this step could be replaced by a more efficient approach; suggestions welcome.

Related

Rails - connecting to postgres with url, role does not exist

I'm attempting to deploy a Rails 5 app using Capistrano, and I'm hung up on the db:migrate step.
Specifically, when my scripts attempt to run db:migrate I get the error:
ActiveRecord::NoDatabaseError: FATAL: role "admin" does not exist
My database.yml file looks like this for the production block:
production:
adapter: postgresql
encoding: unicode
# For details on connection pooling, see rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
url: <%= ENV['DATABASE_URL'] %>
and my database_url takes the form of:
postgresql:://mydb_user:mydbuser_pass#localhost/db_name
With mydb_user, mydbuser_pass, and db_name substituted in with my own correct values.
Inside of postgres I can see these permissions on my database:
db_name | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres + postgres=CTc/postgres + mydb_user=CTc/postgres
Which I think means that mydb_user has the permissions necessary for using my database.
Now, the user I'm logged in as during the capistrano deploy does have the username of 'admin', which leads me to believe that I fundamentally don't understand something about postgres roles. Why would my currently logged in user have anything to do with the postgres connection when I've given my username and password via the database url for a specific postgres user I've already created? Is this saying that my ubuntu username needs to match mydb_user in order to login? How do I fix this error specific to rails and database urls with postgres?
prev commenter was wrong: correct format of database url is
postgresql://[user[:password]#][netloc][:port][/dbname][?param1=value1&...]
for example:
postgresql://db_user:db_password#localhost:5432/db_name?timeout=5000&connect_timeout=5&pool=10
Classic case of dumb mistakes. The urls do not have two colons in them like I describe above, instead they are
postgres://
By default rails was attempting to connect as 'admin' because that's the unix user I was logged in as. Solution, double check your postgres url format.

Rails: permission denied for relation schema_migrations

I'm trying to setup a local production environment for a Ruby on Rails web application. I can run the application with rails server command, which gives the development environment.
The production environment I'm trying to set up is purely local and I've followed this tutorial for setting it up with apache 2: https://www.digitalocean.com/community/tutorials/how-to-setup-a-rails-4-app-with-apache-and-passenger-on-centos-6
However when I go to the page of my application I get the following error:
PG::InsufficientPrivilege: ERROR: permission denied for relation schema_migrations : SELECT "schema_migrations".* FROM "schema_migrations"
in my database.yml I have these settings for development and production:
adapter: postgresql
database: whiteboard
username:
password:
pool: 5
timeout: 5000
I'm not allowed to change these settings, no matter what.
Is there any way to fix this? (if yes, step by step please)
It seems you have to create a DB user with all needed privileges on your DB.
For example I think you could do the trick by log in your DB console then do something like:
CREATE USER your_new_username WITH PASSWORD 'your_new_password';
CREATE DATABASE whiteboard;
GRANT ALL PRIVILEGES ON DATABASE whiteboard to your_new_username;
ALTER DATABASE whiteboard OWNER TO your_new_username;
Then update you database.yml like this:
adapter: postgresql
database: whiteboard
username: your_new_username
password: your_new_password
pool: 5
timeout: 5000
Hope it helps!
I was using dbmate which also creates a table called schema_migrations on startup, and thus fails when a full dump is applied that also has the same table. Here are a few approaches
PostgreSQL doesn't support creating dump with IF NOT EXISTS, unlike mysql:
See Can pg_dump be instructed to create tables with "IF NOT EXISTS"?
However, PostgreSQL 9.1 and newer supports CREATE TABLE IF NOT EXISTS -syntax, so you could string replace the dump for example by using sed:
sed -i 's/CREATE TABLE/CREATE TABLE IF NOT EXISTS/g' dump.sql
But in practice, I ended to delete the lines from the dump with schema_migrations on it, and +1-2 lines following:
sed -i '/CREATE TABLE public.schema_migrations (/,+2 d' dump.sql
sed -i '/ALTER TABLE ONLY public.schema_migrations/,+1 d' dump.sql

Include more than one postgres schema in rake db:schema:dump?

When running rake db:schema:dump on an app that uses a postgres schema (i.e. schema_name.users), it looks like it's only dumping tables for the first schema in the db user's search path. Is there a way to include tables from more than one schema?
To state the problem differently:
createdb myapp
psql myapp -U postgres -c "create table stuff"
#=> creates table "stuff" in the public schema
psql myapp -U postgres -c "create schema specific_thing"
psql myapp -U postgres -c 'create table "specific_thing".users(id int)'
createuser -U postgres -S -D -R special_user
psql myapp -U postgres -c "grant all on schema specific_thing to special_user"
psql myapp -U postgres -c "ALTER USER special_user SET search_path TO specific_thing,public"
In database.yml:
...
development:
adapter: postgresql
database: stuff
username: special_user
password:
host: localhost
...
Running: rake db:schema:dump
Only dumps the users talbe from the specific_thing schema and ignores everything in the public schema.
So here's what I found. I don't have the code in front of me so I can't point to anything specifically, but there is some code in PostgresAdapter that identifies what the adapter considers as its available 'tables'. The adapter assumes it's always going to deal with the 'public' schema (public is actually hardcoded in the query that gets a list of tables), so my solution to the problem involved subclassing PostgresAdapter to have a different concept of what it's 'tables' are. This got me most of the way there. There were some other obstacles to overcome but everything was much more clear after fitting this piece into the puzzle. Definitely involved spending some time in the Rails source though.

Database not being selected in rails project when attempting to rake db:migrate

Working with a rails app, having some manner of weird database / rake issues.
When I execute:
rake db:migrate
I am getting the following error:
Mysql2::Error: No database selected: SHOW TABLES
(See full trace by running task with --trace)
The trace isn't revealing much useful information. Can be seen here: http://pastebin.com/WdsguudC
The config file looks right, and the user is getting logged in, or I would have gotten some kind of access error. The database exists, the user has correct permission, and I can access and manipulate it manually. I have done a bunch of googling, and haven't found anything helpful. Not sure if there is any other code that needs provided, because this seems like fairly low level problem.
after all that it was a spacing issue in the yaml.
Note that ruby has exchanged its YAML parser in a recent 1.9.2 version.
This might also cause this problem.
In order to switch back to the old YAML parser syck, use this in boot.rb:
require 'yaml'
YAML::ENGINE.yamler= 'syck'
Well, it is a common issue for us beginners. This issue comes from the moment when you create your new project in rails. Let’s say to have an example
$ rails new toy –d mysql
After you do the bundle and start your server, most likely you will have an error. To correct it you need to go to your database.yml and modify the following:
Add a password in the password field as shown below, this is the password you use to secure mysql.
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password: mypassword
socket: /tmp/mysql.sock
Also, comment out the database adding a hash tag (#)before the name as shown below
development:
: *default
database: #toy_development
Then restart your command line and go to the root of your application and type:
$ rails s
You have to see the Ruby on Rails welcome page..
After, you need to create a database.
Create a DATABASE.
The issue message is saying that not DATABASE is selected. It is because I didn’t create one. When you work with MySQL you have to create one, so:
Go to the root of my application and type:
$ mysql –u root –p
$ Passwor: mypassword (Enter your password, this is the one you entered to secure MySQL)
Note: This example works wit a project called toy and the user I wanted to grant privileges is mark and the password I’ll give is 45mark. Below you will see where I apply these elements. Remember to apply your own elements on each part of the statement.
Create and user for this project
Once you are in, you will see the pointer (mysql> ), so type after it:
mysql> GRANT ALL PRIVILEGES ON toy_development.* TO 'mark'#'localhost' IDENTIFIED BY '45mark';
Then type:
mysql> exit;
Check that it is working by typing:
$ mysql –u mark –p toy_development
Enter password: 45mark (You enter the one you gave)
Open database.yml file and configure what is needed and fix as required. In my case I will chance the username to mark and the password to 45mark
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: mark
password: 45mark
socket: /tmp/mysql.sock
- Also, REMOVE the hash tag (#) added before
development:
: *default
database: toy_development
Save it.
Go to the root of the application and type
$ rake db:schema:dump
Done!!
I hope this helps. Happy coding!!
Thanks
I had the same issue with ruby 1.9.2-p180 , upgraded to p290 and it works
Just restart the server; in the command line:
Press Ctrl + C
execute:
rails s
I had a similar error when i typed rake db:schema:dump and it turns out that I just have to comment out all the databases on my yaml file except my development one.
Give a try to this.
rake db:test:prepare
Install this to see if you have actually created a table or not. Open the "development.sqlite3" in db folder
http://sqlitebrowser.org/
Its a simple error checkout the entire database.yml file and see that where is default decription is given database name is given or not if not then look below it there will another development name is also given where configuration of database is use check that give your database name in it
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password: 12345
host: localhost
development:
<<: *default
database: db_name
One potential cause is that there is a DATABASE_URL environment variable defined.
$ echo $DATABASE_URL
=> mysql2://root#localhost:3306
If you get a similar output to the above url (i.e., the database name is not present), then you might want to add the database name to the string or unset the env var.
$ export DATABASE_URL=mysql2://root#localhost:3306/my_rails_app_development
$ unset DATABASE_URL
If you unset the var, you probably want to specify the database details in database.yml instead.

PGError: ERROR: source database "template1" is being accessed by other users

I'm having problems getting testing to work with Postgresql and Rails 3.
Both development and production databases I can get to work fine, however the test database throws the following errors when I run rake or db:test:prepare, etc.
PGError: ERROR: source database "template1" is being accessed by other users
Update
Googling around, it seems that one should use template0 instead of template1 when using createdb to create a new database in Postgres. In typical “So I’ll remove the cause. But not the symptom” fashion, I found vendor/rails/railities/lib/task/databases.rake and changed line 109 to read:
createdb #{enc_option} \
-U "#{abcs["test"]["username"]}" \
-T template0 #{abcs["test"]["database"]}
But I don't really wanna do that, as I'm using Rails as a GEM, any one know of another work around or fix?
database.yml:
development:
adapter: postgresql
encoding: unicode
database: test1234_development
pool: 5
username: holden
password: postgres
test:
adapter: postgresql
encoding: unicode
database: test1234_test
pool: 5
username: holden
password: postgres
Full error:
NOTICE: database "test1234_test" does not exist, skipping
PGError: ERROR: source database "template1" is being accessed by other users
DETAIL: There are 1 other session(s) using the database.
: CREATE DATABASE "test1234_test" ENCODING = 'unicode'
Short story: CREATE DATABASE works by copying an existing database. PostgreSQL won't let you copy a database if another session is connected to it. If template1 is being accessed by other users, CREATE DATABASE will fail.
The question you need to answer: Why are other sessions connected to template1?
The difference between template0 and template1
At the point you initialize a database cluster, template0 and template1 are the same. Any location-specific stuff you want to make available to every database you create by using CREATE DATABASE should go into template1. So, for example, if you add the procedural langauge PL/python to template1, every database you create later will include PL/python.
The database template0 is intended to be a "virgin" template. It should contain only standard database objects--the ones created by initializing the cluster. As a "virgin" template, it should never be changed. Never.
If you need to specify encoding and locale settings (collation), then you can do that by copying template0. You can't do that by copying template1.
This problem occur when you had logged(psql template1 or psql template0) in template1 and template0 database and exit using below command.
Ctrl + z
Better way exist from db use below postgres command then problem will not create:
\q + enter
There are 2 solutions, If have problem.
Solution - 1
Restart posgres service like.
sudo service postgresql restart
Solution - 2
sudo ps aux | grep template1
Make sure don't delete this processes
postgres 8363 0.0 0.0 111760 7832 pts/11 T 09:49 0:00 /usr/lib/postgresql/9.5/bin/psql template1
ankit 18119 0.0 0.0 14224 976 pts/14 S+ 12:33 0:00 grep --color=auto template1
rest of process should be kill using below command.
sudo kill -9
Now try to create db again.
Hope this help you.
Ankit H Gandhi.
Just restart the service of database.
I restarted my system and the error was still showing. However, I followed the steps below to sort it out.
Stop all processes using the postgres port 5432 by doing this in command prompt (Admin): Type netstat -ano in command prompt. Find the pid with Local Address of 0.0.0.0:5432. Then use taskkill /pid {pid} /f to kill the task.
Start the postgres service in windows services.
I also got this error while trying to reset the database while I had the default Ruby on Rails server WEBrick running:
$ bin/rake db:reset
PG::Error: ERROR: database "dev" is being accessed by other users
DETAIL: There is 1 other session using the database.
: DROP DATABASE IF EXISTS "dev"
The other user here was the running Rails app. After shutting down the server with CTRL + c, I was able to re-run the database reset command without any problems.
It makes sense too. You can't drop the database if someone else is currently connected to it, as Mike Sherrill also points out.
Solution for me was to delete old server and create a new one from Postgresql administration web interface. Could now create new database without this error.
I was also stuck setting up postgres on ruby on rails project, ensure that you have installed pg locally and created a user with its password then on your database.yml should have:- host: localhost, password: (set password) then run:
$ rails db:create
$ rails db:migrate

Resources