When I post something in my Rails app (locally), it works perfectly. However, when I deploy it on Herokuapp, it breaks. Here is what I have:
#Gemfile
# Use sqlite3 as the database for Active Record
gem 'sqlite3', group: :development
gem 'pg', '0.18.1', group: :production
gem 'rails_12factor', group: :production
#database.yml
production:
<<: *default
adapter: postgresql
database: db/production.sqlite3
I then proceeded to deploy my app to Heroku like this:
git add .
git commit -m "comment"
git push heroku master
heroku run rake db:migrate
heroku run rake db:seed
I've checked my version using the following:
heroku run rake db:version
>> Current version: 20171103035018
rake db:version
>> Current version: 20171103035018
Finally, here is my controller where I perform a create action:
#suggestions_controller.rb
def create
#suggestion = Suggestion.new(suggestion_params)
if #suggestion.save
flash[:notice] = "Suggestion successfully posted!"
redirect_to root_path
else
flash[:error] = "Suggestion failed to post!"
redirect_to root_path
end
end
private
def suggestion_params
params.require(:suggestion).permit(:suggester, :ip, :suggestion_type, :title, :body)
end
I tried this on my localhost and it creates just fine, but when I deploy it on Heroku, it displays this error:
I'm pretty certain I did everything correctly and I have no idea what's breaking here.
Thanks for any help.
Edit: I just got a lead to the problem. It says that my created_at is null.
ActiveRecord::NotNullViolation (PG::NotNullViolation: ERROR: null value in column "created_at" violates not-null constraint
I'm researching on the web now to see how I can fix this problem.
Well, you should take a look at your logs. Heroku documented their logging here: https://devcenter.heroku.com/articles/logging
From your description, it may be something about your database setup, e.g. wrong database.yml.
If the logs don't help you, please fix the indentation of your database.yml posted above.
I figured out the problem. It was indeed this particular error message:
ActiveRecord::NotNullViolation (PG::NotNullViolation: ERROR: null value in column "created_at" violates not-null constraint
I had to add this line of code to my suggestions_controller.rb
def create
Suggestion.record_timestamps = true; #added this line of code
... #other logic
end
When I upvote and downvote a post, I don't want it to update the timestamps such as this:
def upvote
Suggestion.record_timestamps = false;
... #other logic
end
I redeployed my app and it works fine now.
I want to use the point type which there's in PostgreSQL. I've done:
rails g model Test point:point
The resulting migration is:
class CreateTests < ActiveRecord::Migration
def change
create_table :tests do |t|
t.point :point
t.timestamps
end
end
end
When I run:
rake db:migrate
The result is:
== CreateTests: migrating ====================================================
-- create_table(:tests)
rake aborted!
An error has occurred, this and all later migrations canceled:
undefined method `point' for #<ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::TableDefinition:0x000000038991a0>/home/i/Dropbox/programming/ruby/rails_pg_for_tests/db/migrate/20140306151700_create_tests.rb:4:in `block in change'
/home/i/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract/schema_statements.rb:184:in `create_table'
/home/i/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-4.0.2/lib/active_record/migration.rb:625:in `block in method_missing'
/home/i/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-4.0.2/lib/active_record/migration.rb:597:in `block in say_with_time'
...
May be I need to install PostGIS, but I don't understand what for, if I have point type in PostgreSQL. And I only need to store latitude and longitude without any other options.
How can I use this point type or what is better to use in this case?
Thank you.
You can specify the data type as a string
t.column 'point', 'point'
Rails have support for point for several years. The test cases have been there since rails 4.2 beta.
If you are using rails 4.2 or later. you should not get that error. I have not tested it on 4.2 beta yet. I only test it on rails 5.2 and it works without any additional gem.
https://github.com/rails/rails/blob/24adc20ace69ec0fcf317e0a8d91d112478ba015/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb
Usage:
Migration
class CreateAddresses < ActiveRecord::Migration[5.2]
def change
create_table :addresses do |t|
t.point :coordinate
end
end
end
Create a new record
Address.create coordinate: ActiveRecord::Point.new(1, 1)
You receive undefined method 'point' for #<ActiveRecord:... error on migration code
t.point :point
because point method does not exist in ActiveRecord.
ActiveRecord natively supports following data types,
:primary_key, :string, :text, :integer, :float, :decimal, :datetime, :timestamp,
:time, :date, :binary, :boolean
See the official documentation of ActiveRecord for the same.
As suggested by #bridiver, you could choose to specify a type other than the supported datatypes of ActiveRecord(as listed above) with t.column :point, 'point' BUT as quoted in ActiveRecord documentation
this will not be database agnostic and should usually be avoided.
UPDATE
I would recommend utilizing the benefits of activerecord-postgis-adapter gem, as suggested by #euricovidal. It is a geospatial extension for pgsql and it acts as a wrapper around the PostGIS query functions and allows you to write geo-aware migrations.
It will allow you to create a point type and using this your current syntax should work.
Refer PostGIS ActiveRecord Adapter: Creating Spatial Tables for example. You would also need to update the adapter to postgis in the database.yml file for this to work.
if you are using activerecord-postgis-adapter you need change adapter on database.yml to postgis.
https://github.com/dazuma/activerecord-postgis-adapter#installation-and-configuration
You most likely need to edit your config\database.yml to reference postgis as your database adapter
default: &default
adapter: postgis
encoding: unicode
pool: 5
timeout: 5000
host: localhost
development:
<<: *default
database: learning_rails
username: brentpayne
password:
You might also want to edit your migration to specify the :point as geographic so you can calculate distances.
t.point :point, :geographic => true
But the error you are having is identical to mine when I left my adapter set to postgresql. Changing it to postgis fixed my issues.
Reference: https://github.com/rgeo/activerecord-postgis-adapter#installation-and-configuration
If you install georuby the point datatype becomes available.
Gemfile
gem 'pg'
gem 'georuby'
In a migration
def change
create_table :space_table do |t|
t.point :location
t.timestamps
end
end
You can save a point with model_object.location = [-33.233, 123.123]
I saw this question up before, but only for rspec. I haven't created test yet because it's too advanced for me but one day soon i will! :P
I get this error when I try to sign-up/login into my app. I used devise to create user and also omniauth2 to sign-in with google.
this is the error
ActiveRecord::StatementInvalid at /users/auth/google_oauth2/callback
PG::UndefinedTable: ERROR: relation "users" does not exist
LINE 5: WHERE a.attrelid = '"users"'::regclass
^
: SELECT a.attname, format_type(a.atttypid, a.atttypmod),
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
FROM pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attrelid = '"users"'::regclass
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum
I tried rake db:migrate, but it already is created: in schema table users exist. Has anyone got this error before?
database.yml
config=/opt/local/lib/postgresql84/bin/pg_config
development:
adapter: postgresql
encoding: unicode
database: tt_intraweb_development
pool: 5
username: my_username
password:
test:
adapter: postgresql
encoding: unicode
database: tt_intraweb_test
pool: 5
username: my_username
password:
production:
adapter: postgresql
encoding: unicode
database: tt_intraweb_production
pool: 5
username: my_username
password:
At first, you shall detach all connections out of database. By default you use the development environment. Then try to reset database with the following:
rake db:reset
The rake db:reset task will drop the database and set it up again. This is functionally equivalent to rake db:drop db:setup.
This is not the same as running all the migrations. It will only use the
contents of the current schema.rb file. If a migration can't be rolled back,
rake db:reset may not help you. To find out more about dumping the schema see
Schema Dumping and You section. Rails Docs
If the trick doesn't help, drop the database, then re-create it again, migrate data, and if you have seeds, sow the database:
rake db:drop db:create db:migrate db:seed
or in short way (since 3.2):
rake db:migrate:reset db:seed
Since db:migrate:reset implies drop, create and migrate the db. Because the default environment for rake is development, in case if you see the exception in spec tests, you should re-create db for the test environment as follows:
RAILS_ENV=test rake db:drop db:create db:migrate
or with just loading the migrated scheme:
RAILS_ENV=test rake db:drop db:create db:schema:load
In most cases the test database is being sowed during the test procedures, so db:seed task action isn't required to be passed. Otherwise, you shall to prepare the database (this is deprecated in Rails 4):
rake db:test:prepare
and then (if it is actually required):
RAILS_ENV=test rake db:seed
On newer versions of Rails the error ActiveRecord::NoEnvironmentInSchemaError may be risen, so just prepend the tasks with a database environment set task: db:environment:set:
RAILS_ENV=test rake db:environment:set db:drop db:create db:migrate
I encountered this error, and upon my research, found out that one of the reasons for PG undefinedtable error relation users does not exist error is:
This error is a migration error. You may have created new model with some database attributes. After creating model you have to migrate attributes to your rails app schema.
If you are using local machine, for development, you can use command
rake db:migrate
If you're using heroku
heroku run rake db:migrate
Your test database is not ready for rspec.
Prepare your test database for rspec to fix this error
RAILS_ENV=test rake test:prepare
It will drop, create and add migrations to your test database
In case rake task is aborted with message like 'PG::Error: ERROR: database "[your_db_test]" is being accessed by other users' execute this one
RAILS_ENV=test rake db:migrate
I was getting this error as well when running rspec:
Failure/Error: it { expect(subject.priority_list).to eq [nil] * 9 }
ActiveRecord::StatementInvalid:
PG::UndefinedTable: ERROR: relation "priorities" does not exist
LINE 5: WHERE a.attrelid = '"priorities"'::regclass
...
It was resolved for me after I ran
rake db:test:prepare
rake db:test:load
I had a similar error. The root of my error was that I had a reference to a Rails model in my factories.rb file. So it caused a load error issue. The fix was to wrap the reference in a block or {} so that it delays running it.
Here was the BROKEN code:
FactoryGirl.define do
factory :user do
guid User.new.send(:new_token)
end
end
And it was erroring because User was not defined when factories.rb was being loaded. I wrapped the User.new call in a block and it solved the issue:
Fixed code:
FactoryGirl.define do
factory :user do
guid { User.new.send(:new_token) }
end
end
Note: probably not best practice to need to call your model like this, but it was a solution to DRY up my code.
This is often caused by a bug in ActiveAdmin. Here's how to get around the bug:
If you're using ActiveAdmin, whichever table PG says doesn't exist, comment out the contents of that ActiveAdmin rb file.
For example, for this case PGError: ERROR: relation "users" does not exist, comment out the entire contents of app/admin/users.rb, then uncomment after you've done your migrations.
That issue for me was being caused by Factory Girl rails. I would recommend for those using it to rename the specs/factories folder to specs/temp and attempting
RAILS_ENV=your_environment bundle exec rake db:migrate --trace
If it passes, then you just found what was causing it. A quick dig through the Factory Girl Rails gem github repo helped me identify the issue.
The factories were failing because I was trying to instantiate a Model that didn't exist upon running! Code sample below:
FactoryGirl.define do
factory :billing_product, class: 'Billing::Product' do
name Faker::Cat.name
product_type 'fuel'
active true
payment_options [Billing::PaymentOption.new(term: 1, payment_term: 1)]
end
end
Encapsulating the Array in a block (adding {}) did the fix for me. Note that payment_options can take more than one payment option in the example...
payment_options {[Billing::PaymentOption.new(term: 1, payment_term: 1)]}
Refer to the Dynamic Attributes part of the Factory Girl Rails docs for more info.
Don't forget to rename your factories folder back!
I was facing the same problem and then I discovered the following solution.
Make sure You have entered all of the following credentials in the database.yml file and they are correct:
development:
adapter: postgresql
encoding: unicode
database: my_database
host: localhost
port: 5432
pool: 5
username: postgres
password: xyz
test:
adapter: postgresql
encoding: unicode
database: my_test_database
host: localhost
port: 5432
pool: 5
username: postgres
password: xyz
I had this problem after I deleted the users table. solutions was changing
change_table(:users)
to
create_table(:users)
::Migration[5.0] was missing in migrations.
instead of throwing syntax error it throws
PG::UndefinedTable: ERROR: relation roles does not exists
after wasting hours I finally figured out that migration is missing ::Migration[5.0].
Erroneous Migration:
class CreateRoles < ActiveRecord # <---- Pay attention
def change
create_table :roles do |t|
t.string :name
t.integer :code, limit: 2
t.boolean :is_active, default: true
t.timestamps
end
end
end
Fixed and Correct Migration
class CreateRoles < ActiveRecord::Migration[5.0]
def change
create_table :roles do |t|
t.string :name
t.integer :code, limit: 2
t.boolean :is_active, default: true
t.timestamps
end
end
end
This could be a bug with rails and might help someone, instead of struggling and wondering.
The most probable cause is that your rake is using different environment from database.yml than your webserver.
I was getting a similar error while trying to run tests using rspec.
I followed Малъ Скрылевъ's steps but still ended up short. The final step I needed to do was load my schema into my test database using:
RAILS_ENV=test rake db:schema:load
After that the problem went away and I could move on to the next bug. Hopefully that gives you some insight.
Remove the Admin folder and run rake again.
(I know this is old, but for future googlers)
Are you using devise? I know specifically omniauthable is a problem, but maybe others as well. It doesn't have to be devise though. Generically the solution is to comment out the offending model, class, whatever, and un-comment any sections the errors ask for.
For me, what was happening is that devise is reading the User model to see what you have as arguments for devise (the class method
i.e. devise :database_authenticatable, :registerable #etc)
But, it will read the whole file and if this isn't a new project it might get tripped up by other class methods relying on other things (in my case it was the friendly_id gem, and then an alias_method
The answer was to comment out the User model except for the devise lines(s) * and rake db:schema:load should run fine.
otherwise I got this error:
ArgumentError: Mapping omniauth_callbacks on a resource that is not omniauthable
Please add devise :omniauthable to the User model
If you get this error while migrating, make sure your model name is plural
e,g.
add_column :images, :url, :string
I had this problem and it turned out to be caused by Grape API. I noticed in the stack trace that the routes file was being read during the migration.
In routes.rb the Grape api is mounted
mount API::Base => '/'
And in the API were references to the missing model. So, thanks to this answer I put it in a block that detects whether its being run by the server or during the migration.
unless ( File.basename($0) == "rake" && ARGV.include?("db:migrate") )
mount API::Base => '/'
end
And it worked.
I was having the following error and doing a lookup into all my application code for type_zones I was unable to find it. I also looked at the db and it was updated.
Turns out it was a file under fixtures /test/fixtures/type_zones.yml that was causing the trouble.
ERROR["test_should_get_new", UsersControllerTest, 0.47265757399145514]
test_should_get_new#UsersControllerTest (0.47s)
ActiveRecord::StatementInvalid: ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "type_zones" does not exist
LINE 1: DELETE FROM "type_zones"
^
: DELETE FROM "type_zones"
For anyone who is still having this problem, in my case, it was my factory in FactoryGirl that was triggering this error.
I was trying to add reference via '.new' or '.create'.
In my case, I had to comment out 2 ActiveAdmin files. Here were my steps:
Initial error/stacktrace (note we're using Solr on this project):
⇒ rkdbm
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)
=> Solr is already running
rake aborted!
PG::UndefinedTable: ERROR: relation "discussions" does not exist
LINE 5: WHERE a.attrelid = '"discussions"'::regclass
^
: SELECT a.attname, format_type(a.atttypid, a.atttypmod),
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
FROM pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attrelid = '"discussions"'::regclass
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum
/Users/matthewcampbell/Sites/code/stack-builders/AchieveX/app/admin/users.rb:25:in block in <top (required)>'
/Users/matthewcampbell/Sites/code/stack-builders/AchieveX/app/admin/users.rb:1:in'
/Users/matthewcampbell/Sites/code/stack-builders/AchieveX/config/routes.rb:3:in block in <top (required)>'
/Users/matthewcampbell/Sites/code/stack-builders/AchieveX/config/routes.rb:1:in'
/Users/matthewcampbell/Sites/code/stack-builders/AchieveX/config/environment.rb:5:in `'
Tasks: TOP => db:migrate => environment
(See full trace by running task with --trace)
I commented out the app/admin/discussions.rb file per Arcolye's answer above and tried to migrate my database again.
Same error.
I looked at the stacktrace a bit more closely, and noticed that in fact app/admin/users.rb:25 was throwing the exception - and sure enough, that file has a dependency on my discussions table (via executing Discussion.all).
Finally, commenting out the contents of users.rb allowed me to finally migrate my database successfully.
FYI: there's a discussion here in ActiveAdmin about whether that gem should load the database when required.
So having the same problem just now. Remember to have only one model in each migration. That solved it for me.
I came across the answer here.
I was catching the Error:
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "users" does not exist
LINE 8: WHERE a.attrelid = '"users"'::regclass
It turned out to be a super easy fix. I had copied files over from an older version of the project and forgot to nest them inside of a "migrate" folder. When I did that it solved the problem for me.
it usually can happen when you use wrong type of association between models, check for dependency destroy and has_many associations, for example:
wrong way that can cause this trouble:
article.rb
has_many :subcategories, through: :categories, dependent: :destroy
subcategory.rb
has_and_belongs_to_many :articles
right way:
article.rb
has_many :subcategories, through: :categories, dependent: :destroy
subcategory.rb
declare association with categories here not articles (belongs_to / has_many_and_belongs_to)
Forgetting the migration file in your commit can cause this issue. When pushed on heroku for e.g. rails db:migrate will obviously not work. Be sure that the migration file defining the undefined table have been committed.
My case was also related to FactoryGirl/FactoryBot and I just had to change the definition. Replacing the constant by a string.
My env:
Rails 5.2.6
factory_bot 4.8.2
From this:
FactoryBot.define do
factory :user, class: Admin::User do
...
end
end
To this:
FactoryBot.define do
factory :user, class: 'Admin::User' do
...
end
end
Which is something recommended by Getting Started - Specifying the class explicitly.
I was trying to run test.rake script and encountered the same issue. Spent a lot of time trying to understand what's going on. Eventually, it get fixed after I renamed the file.
I am using RoR (3.2.2) and SQLite 3 (1.3.5). When I initially generate a model I am able to successfully create a database. However, whenever I try to use the migration generator it appears to not have any issues in the command line (no errors), but when I check the database nothing has updated or changed.
For example, I create this database:
$ rails generate model User name:string email:string
db/migrate/[timestamp]_create_users.rb
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
And I run a migration:
$ bundle exec rake db:migrate
So far so good, I check my database using SQLite Database Browser and everything looks as it should.
Then if I want to add an index:
$ rails generate migration add_index_to_users_email
db/migrate/[timestamp]_add_index_to_users_email.rb
class AddIndexToUsersEmail < ActiveRecord::Migration
def change
add_index :users, :email, unique: true
end
end
I run a migration:
$ bundle exec rake db:migrate
And command line gives me the following:
bundle exec rake db:migrate
== AddIndexToUsersEmail: migrating ===========================================
== AddIndexToUsersEmail: migrated (0.0000s) ==================================
However, when I check my database using SQLite Database Browser it isn't updated. I get the same results if I try to add new columns to the table, etc. The only way I have been able to do migrations is manually updating the database using the SQLite Database Browser. Any help as to why it is not working through Rails and the command line would be greatly appreciated.
Here is my gemfile:
source 'https://rubygems.org'
gem 'rails', '3.2.2'
gem 'bootstrap-sass', '2.0.0'
group :development, :test do
gem 'sqlite3', '1.3.5'
gem 'rspec-rails', '2.8.1'
gem 'annotate', '~> 2.4.1.beta'
end
group :assets do
gem 'sass-rails', '3.2.4'
gem 'coffee-rails', '3.2.2'
gem 'uglifier', '1.2.3'
end
gem 'jquery-rails', '2.0.0'
group :test do
gem 'capybara', '1.1.2'
end
group :production do
gem 'pg', '0.12.2'
end
Database.yml
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
test:
adapter: sqlite3
database: db/test.sqlite3
pool: 5
timeout: 5000
production:
adapter: sqlite3
database: db/production.sqlite3
pool: 5
timeout: 5000
Example of successfully adding a column:
rails generate migration add_password_digest_to_users password_digest:string
invoke active_record
create db/migrate/20120318235656_add_password_digest_to_users.rb
$ subl db/migrate/[timestamp]_add_password_digest_to_users.rb
$ bundle exec rake db:migrate
== AddPasswordDigestToUsers: migrating =======================================
-- add_column(:users, :password_digest, :string) -> 0.0008s
== AddPasswordDigestToUsers: migrated (0.0009s) ==============================
Example of unsuccessfully adding a column:
$ rails generate migration add_remember_token_to_users
invoke active_record
create db/migrate/20120319010623_add_remember_token_to_users.rb
$ subl db/migrate/[timestamp]_add_remember_token_to_users.rb
$ bundle exec rake db:migrate
== AddRememberTokenToUsers: migrating ========================================
== AddRememberTokenToUsers: migrated (0.0000s) ===============================
Notice when it fails to update the database the migration time is zero. I'm not sure what I am doing wrong. Thanks in advance for any suggestions.
I solved the problem undoing the last migration with
rails destroy migration add_index_to_users_email
Then I closed my terminals to ensure that all db connections were closed, then I run
rake db:reset
Finally, running the same commands again
rails generate migration add_index_to_users_email
Updating the file with the same content and running
rake db:migrate
All the same commands and files that were not working before now worked at all (for me).
I hope this works for you as well.
I think what happens is you get the syntax slightly wrong (it's insanely tricky) then you get an empty migration which doesn't do anything.
I would double check that the actual migration file has add column. I often end up manually putting the actual change (or up/down) in.
As t Harrison says, adding an index is more subtle - as you sure it doesn't get added if you refresh the sqlite borwser. The examples you gave that worked... are to add columns...
The output you posted from the add index example shows that the migration is indeed running ... but you report it's not actually doing anything. Try bundle exec rake:db rollback (with optional STEP=n to go more than one step back). This really should "just work", and a case of an index might be a little subtle -- try adding a column or something (which you said you have done, but, just to be sure). Does it really not work? How can you tell?
Running rake db:migrate followed by rake test:units yields the following:
rake test:functionals
(in /projects/my_project)
rake aborted!
SQLite3::SQLException: index unique_schema_migrations already exists: CREATE UNIQUE INDEX "unique_schema_migrations" ON "ts_schema_migrations" ("version")
The relevant part of db/schema.rb is as follows:
create_table "ts_schema_migrations", :id => false, :force => true do |t|
t.string "version", :null => false
end
add_index "ts_schema_migrations", ["version"], :name => "unique_schema_migrations", :unique => true
I'm not manually changing this index anywhere, and I'm using Rails' default SQLite3 adapter with a brand new database. (That is, running rm db/*sqlite3 before rake db:migrate doesn't help.)
Is the test:units task perhaps trying to re-load the schema? If so, why? Shouldn't it recognize the schema is already up to date?
In SQLite, index name uniqueness is enforced at the database level. In MySQL, uniqueness is enforced only at the table level. That's why your migrations work in the latter and not the former: you have two indexes with the same name on different tables.
Rename the index, or find and rename the other unique_schema_migrations index, and your migrations should work.
In your database.yml file are your environments setup up to connect to different databases for Development and Test?
IE:
development:
adapter: sqlite3
database: db/dev.sqlite3
timeout: 5000
test:
adapter: sqlite3
database: db/test.sqlite3
timeout: 5000
Try to search if your schema.rb file does not contain other declarations that create an index with the same name: unique_schema_migrations