postgres production database isn't synced with heroku app - ruby-on-rails

I first noticed trouble after I dropped an Active Record table using this migration:
class DropDelayedJobTables < ActiveRecord::Migration
def change
drop_table :delayed_jobs
end
end
bundle exec rake db:migrate seemed to successfully drop the table; it disappeared from schema following rake db:schema:dump; and the records no longer seemed to exist via the heroku console. But, the table still exists in my postgres production database!
$ psql myapp_production
myapp_production=# \dt
Schema | Name | Type | Owner
--------+-------------------+-------+-----------
public | delayed_jobs | table | leoebrown
public | foods | table | leoebrown
public | lists | table | leoebrown
public | quantities | table | leoebrown
public | schema_migrations | table | leoebrown
public | users | table | leoebrown
I also noticed that when I delete records via heroku console (Food.find(1234).destroy), the records still exist in the myapp_production postgres database. For example, when I check the number of foods in the postgres database, it is:
myapp_production=# SELECT COUNT(*) from FOODS;
count
-------
6716
(1 row)
But when I run Food.count in the heroku console, the result is
In general, my postgres database seems disconnected from my live heroku app.
$heroku run console
irb(main):001:0> Food.count
=> 6161
When I check the number of foods in the live website, it is 6161.
Clearly, I am doing something fundamentally wrong. The production database seems totally disconnected from the app. I didn't even notice, because it wasn't affecting performance. It's almost as though it doesn't matter what is in the production database. Though surely it does matter.
Below is my database.yml file in case it provides a clue. For full disclosure, I'm not sure if/where some of these ENV variables are stored or, if they do exist, where to find them, and what they should be set to.
Thank you for any guidance you may provide.
database.yml:
development:
host: localhost
adapter: postgresql
encoding: UTF8
pool: 5
username: <%= ENV['USERNAME'] %>
password: <%= ENV['PASSWORD'] %>
database: myapp_development
test:
host: localhost
adapter: postgresql
encoding: UTF8
pool: 5
username: <%= ENV['USERNAME'] %>
password: <%= ENV['PASSWORD'] %>
database: myapp_test
production:
host: <%= ENV['IP'] %>
adapter: postgresql
encoding: UTF8
pool: 5
username: <%= ENV['USERNAME'] %>
password: <%= ENV['PASSWORD'] %>
database: myapp_production

Well from your post, I think you are saying that your local database named my_app_production is not synced with your heroku database. which will never happen.
You should note that to login to psql session of heroku you need to use following command
heroku pg:psql --app <your app_name here>
psql myapp_production lets you open psql session with your local database. It is not your heroku production database.
More on this https://devcenter.heroku.com/articles/heroku-postgresql

Related

Rails searches the wrong database for model data when using multiple databases

I am building an application in Rails which requires me to access multiple SQL databases. The resources I found online suggested I use ActiveRecord::Base.establish_connection, however, this seems to interfere with my site's models. After connecting to a different database, when I next do <model>.<command>, it gives me Mysql2::Error: Table '<Database I had to access through establish_connection>.<Model's table>' doesn't exist eg: Mysql2::Error: Table 'test.words' doesn't exist , which means rails tries to look for the table associated with its models in the database I had to access through establish_connection instead of the site development database.
Steps to reproduce error:
Here are some steps I found which seem to reproduce the problem;
First, I create a new rails app:
rails new sqldbtest -d mysql
cd sqldbtest
Then I set the config file:
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: <omitted>
host: localhost
Then create a controller, model, and some data in the mysql database:
rails generate controller test test
rails generate model Word name:string txt:text
rails db:create
rails db:migrate
rails c
cat=Word.new
cat.name="Cat"
cat.txt="Cat."
cat.save
exit
mysql -u root -p # I already have a database called "test".
use test;
create table extst (id int primary key, name varchar(8), txt text);
insert into extst (id,name,txt) values (0,"Bob","Bob.");
quit
I then made the controller and the view:
class TestController < ApplicationController
def test
itemOne=Word.find_by(name:"Cat")
#textOne=itemOne.txt
con=ActiveRecord::Base.establish_connection(adapter: 'mysql2', encoding: 'utf8mb4', username: 'root', password: <omitted>, host: 'localhost', database: 'test').connection
#textTwo=con.execute('select txt from extst where name="Bob"').to_a[0][0]
end
end
I wrote this in the view:
<%= #textOne %><br>
<%= #textTwo %>
added 'root "test#test"' to config/routes.rb
rails s
Result:
When I load the page, it shows "Cat." and "Bob." on separate lines as expected, but when I refresh, It shows the error as described above.
I have tried adding con.close to the controller, but this does not work.
Since this error comes from making a connection to another database, adding ActiveRecord::Base.establish_connection(adapter: 'mysql2', encoding: 'utf8mb4', username: 'root', password: <omitted>, host: 'localhost', database: 'sqldbtest_development').connection to the controller after #textTwo=con.execute('select txt from extst where name="Bob"').to_a[0][0] stops the error from happening, however I don't know if this is the best practice or if it has any side effrcts. For example, the database will need to be changed when moving to test or production.
This solution is most likely just a temporary workaround.

Test database not using .env values

I am running tests using rails test:models and got this error (though the tests still run)
ActiveRecord::NoDatabaseError: We could not find your database: postgres. Which can be found in the database configuration file located at config/database.yml.
A database called postgres does not exist because I gave the DB's a different name.
My database.yml is :
# config/database.yml
default: &default
adapter: postgresql
encoding: unicode
username: <%= ENV['POSTGRES_USER'] %>
password: <%= ENV['POSTGRES_PASSWORD'] %>
pool: 5
timeout: 5000
host: <%= ENV['POSTGRES_HOST'] %>
development:
<<: *default
database: <%= ENV['POSTGRES_DB'] %>
test:
<<: *default
database: <%= ENV['POSTGRES_TEST_DB'] %>
production:
<<: *default
database: <%= ENV['POSTGRES_DB'] %>
and my respective .env is :
# ./env
POSTGRES_USER='bob'
# If you declared a password when creating the database:
POSTGRES_HOST='localhost'
POSTGRES_DB='database1'
POSTGRES_TEST_DB='database1_test'
In PSQL, you can also see the test database isn't using the .env value for its owner but the production database is :
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
--------------+---------------+----------+---------+-------+---------------------------------
database1 | bob | UTF8 | C | C |
database1_test | bobsurname | UTF8 | C | C |
I think you don't have the database database1_test
You can login to Postgres via:
sudo -u postgres psql to login into Postgres
\l will show the all database
If database1_test doesn't exist, run this cmd to create and migrate database for testing
RAILS_ENV=test rails db:prepare
The issue might be that your ENV variables aren't available in your test suite.
To check this try accessing them in a console:
> RAILS_ENV=test rails console
> ENV # should print out all your ENV variables
> ENV['POSTGRES_TEST_DB'] # should print out the name of your test db
If I'm right and these ENV vars aren't available when your environment is test, you'll need to look at a strategy to include the ENV vars you need.
ThoughtBot has a few ideas that are pretty solid
You can add ENV vars manually as this SO from way back points out

PG rails db:create InsufficientPrivilege: ERROR: permission denied to create db

I executed:
$ GRANT ALL PRIVILEGES ON db1 to user1
$ ALTER USER user1 CREATEDB
$ ALTER USER user1 CREATEDB
$ ALTER USER user1 WITH 'pass'
But still get an error on
$ rails db:create
config/database.yml:
default: &default
adapter: postgresql
encoding: unicode
# For details on connection pooling, see Rails configuration guide
# https://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
development:
<<: *default
database: pg_app_development
Linux Manjaro.
Rails 6.0.2.2
Ruby 2.7.1
Pg 12.2
Also I do not want to put superuser info in database.yml
$ ALTER USER USER1 WITH CREATEDB

How do I pull data from a dual database in Rails (Postgresql and SQL Server)

I was working with just one database initially but I needed to add the clients other database which is a SQL Server database. I was able to connect but I am running into a few problems.
Original full database.yml
development:
adapter: postgresql
database: martin_development
username: *******
password: *******
pool: 5
timeout: 5000
development_sec:
adapter: sqlserver
host: *******
port: 1433
database: Database1
username: *******
password: *******
I get the following error:
TinyTds::Error (Database 'DATABASE1' does not exist. Make sure that the name is entered correctly.)
If I take out the database name so it looks like this:
development_sec:
adapter: sqlserver
host: *******
port: 1433
database:
username: *******
password: *******
Everything appears to run normal and I do not get any error messages in regards to a database not being found. However, that database does exist on the clients side.
I am confused on how to extract data from my customers SQL Server database. I am trying to follow along with some resources I found so my project files so far are looking like this:
Model (Mssql.rb)
class MssqlBase < ActiveRecord::Base
establish_connection :development_sec
self.abstract_class = true
end
Model(site.rb)
class Site < MssqlBase
end
Controller(sites_controller.rb)
class SitesController < ApplicationController
def index
#sites = Site.all
#hash = Gmaps4rails.build_markers(#sites) do |site, marker|
marker.lat site.latitude
marker.lng site.longitude
end
end
end
database.yml
development:
adapter: postgresql
database: martin_development
username: *******
password: *******
pool: 5
timeout: 5000
development_sec:
adapter: sqlserver
host: *******
port: 1433
database:
username: *******
password: *******
My goal is to start pulling data from the database but as of right now with this look in regards to my file I am getting the following error:
ActiveRecord::StatementInvalid (TinyTds::Error: Invalid object name 'sites'.: SELECT [sites].* FROM [sites]):
So just to recap I need it to read from the 'DATABASE1' but it is saying it does not exist. When I leave it out for some reason it is connecting with the server but I do not know which database. Now I am trying to pull the data but am getting invalid statements. Any help would be appreciated.
You can do this with Rails.
Create this method.
def with_connection(database, &block)
ActiveRecord::Base.establish_connection(database)
yield
ActiveRecord::Base.establish_connection
end
It changes what database your app is connected to, runs the query and then restores it to default. Not sure if thread safe. Using establish_connection on its own, will not revert to original (as your app can only be connected to one database at a time)
Then use:
with_connection :development_sec do
MssqlBase.first # will call development_sec database
end

Rails database migration failing because of Postgres inet type

I have a Rails(4.1.0) app that works fine on Heroku. However, on my local machine, rake db:migrate fails due to a table for devise that uses inet datatype and I am using sqlite3 for testing.
I have included the postgres gem as well as postgres_ext but still coming up with the error:
undefined method `inet' for #<ActiveRecord::ConnectionAdapters::Table:0x00000005fae9e8>/home/app/db/migrate/20141107192501_add_devise_to_users.rb:19:in `block in up'
If testing locally using Postgres is acceptable just setup the correct adapters. A sample database.yml:
common: &common
adapter: postgresql
encoding: utf8
template: template0 # Required for UTF8 encoding
username: <%= ENV["POSTGRES_USER"] %>
password: <%= ENV["POSTGRES_PASSWORD"] %>
host: <%= ENV["POSTGRES_HOST"] %>
development:
<<: *common
database: 'my_app_dev'
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *common
database: 'my_app_test'

Resources