Rails 4 Devise/Omniauth Email exists in database error - ruby-on-rails

I am "banging" my head against a wall trying to figure this out. I decided to allow users to log in through twitter, Google,my site or Facebook. The problem is that twitter does not provide emails, so I am trying to add users by username. The problem with that is devise keeps checking for email and when I don't require it, I get PG::Error: ERROR: duplicate key value violates unique constraint "index_users_on_email" DETAIL: Key (email)=() already exists. : INSERT INTO "users" ("created_at", "name", "provider", "uid", "updated_at", "username") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id".
I don't know what I should do. I created a username column in my database, and I made sure to add this to my devise.rb intializer, config.authentication_keys = [ :username ]

I think that's because default Devise installation creates unique key on email coulmn. In your case it's empty, hence second user doesn't have unique one (because empty string is taken by the first user).
Migration in my case
class AllowNullEmail < ActiveRecord::Migration
def up
remove_index :users, :email
change_column :users, :email, :string, :null => true
end
def down
change_column :users, :email, :string, :null => false
add_index :users, :email, unique: true
end
end

Related

Error when creating association with polymorphic nested attribute

I have three models. Customer, Address, and CreditMemo.
Originally, I had a non polymorphic model Address and I changed it to polymorphic when I created CreditMemo so they could both share the same model. Since then, when I try to create a record with a different parent type than Customer, I get a validation error saying the Customer parent doesn't exist.
Before I created CreditMemo I simply had a 1-to-many association between Customer and Address. Here is the migration I made to change Address to polymorphic.
class MakeAddressPolymorphic < ActiveRecord::Migration[5.1]
def up
rename_column :addresses, :customer_id, :addressable_id
add_column :addresses, :addressable_type, :string
add_index :addresses, [:addressable_id, :addressable_type]
Address.reset_column_information
Address.update_all(:addressable_type => "Customer")
end
def down
rename_column :addresses, :addressable_id, :customer_id
remove_column :addresses, :addressable_type
end
end
My schema after the migration:
create_table "addresses", force: :cascade do |t|
t.text "line_1"
t.text "line_2"
t.string "city"
t.string "state"
t.string "zip_code"
t.string "address_type"
t.bigint "addressable_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "same_as_billing"
t.string "addressable_type"
t.index ["addressable_id", "addressable_type"], name: "index_addresses_on_addressable_id_and_addressable_type"
t.index ["addressable_id"], name: "index_addresses_on_addressable_id"
end
I can create a customer with the nested attributes just fine. However, when I try to create a CreditMemo with the nested address atrributes, I get this error:
PG::ForeignKeyViolation: ERROR: insert or update on table "addresses" violates foreign key constraint "fk_rails_d5f9efddd3" DETAIL: Key (addressable_id)=(36) is not present in table "customers". : INSERT INTO "addresses" ("line_1", "line_2", "city", "state", "zip_code", "address_type", "addressable_id", "created_at", "updated_at", "addressable_type") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING "id"
Here is my Customer model:
has_many :addresses, :as => :addressable, inverse_of: :addressable
accepts_nested_attributes_for :addresses
My CreditMemo model:
has_many :addresses, :as => :addressable, inverse_of: :addressable
accepts_nested_attributes_for :addresses
My Address model:
belongs_to :addressable, :polymorphic => true
I'm pretty sure the issue is in this line which is at the bottom of my schema:
add_foreign_key "addresses", "customers", column: "addressable_id"
I'm not sure how to fix this or what it should be .
You can't use foreign keys with polymorphic associations, so you'd have to remove the foreign key from your schema, you can use remove_foreign_key for this.
Just write a new migration with this:
remove_foreign_key :addresses, :customers

rails migration unique true but allow null values

I originally had this migration:
def change
add_column :users, :provider, :string, null: false, default: "email"
add_column :users, :uid, :string, null: false, default: ""
add_index :users, [:uid, :provider], unique: true
end
But in my application, users can sign in with both omniauth and username and password without oauth authentication. As a result, in many situations, uid and provider will be null. So I created the following migration:
def change
change_column_default :users, :provider, nil
change_column_default :users, :uid, nil
end
But when I try to set the provider or uid to nil in Rails, I get a PG::NotNullViolation: ERROR:
u = User.first
u.provider = nil
u.save!
(0.4ms) BEGIN
SQL (1.5ms) UPDATE "users" SET "updated_at" = $1, "provider" = $2 WHERE "users"."id" = $3 [["updated_at", 2017-08-16 00:01:34 UTC], ["provider", nil], ["id", 1]]
(0.5ms) ROLLBACK
ActiveRecord::StatementInvalid: PG::NotNullViolation: ERROR: null value in column "provider" violates not-null constraint
DETAIL: Failing row contains
It appears unique: true in the migration prevents setting null values. How can I get around this?
You have set the columns to null: false in your first migration which is causing the PG::NotNullViolation exception. That needs to be set to true to allow null values in both the columns. Writing a new migration to set null: true should resolve the issue as follows.
def change
change_column_null :users, :provider, true
change_column_null :users, :uid, true
end
Also below index may not work(RecordNotUnique exception raises as it is set unique: true) as you will have multiple rows having both uid and provider with null values. So this index need to be dropped.
add_index :users, [:uid, :provider], unique: true
In addition to this:
def change
change_column :users, :provider, :string, null: true
change_column :users, :uid, :string, null: true
remove_index :users, [:uid, :provider]
end
which would subsequently allow null values but eliminate the two field constraint at the database-level, I did this at the model-level:
validates :provider, uniqueness: { scope: :uid }, allow_nil: true

rails foreign key violation error key not present in table

I have two models division definition and model definition
division definition :
has_many :model_definitions, inverse_of: :division_definition, foreign_key: :division_definition_id, primary_key: :division_definition_id
ModelDefinition:
belongs_to :division_definition, inverse_of: :model_definitions, foreign_key: :division_id, primary_key: :division_id
In Db structure
def change
create_table :model_definitions do |t|
t.string :model_id , null: false, unique: true
t.string :car_model_name , null: false
t.belongs_to :division_definition , null: false
t.timestamps null: false
end
add_index :model_definitions, :division_definition_id
add_foreign_key :model_definitions, :division_definitions, on_delete: :restrict
end
divisiondefinition table
def change
create_table :division_definitions do |t|
t.integer :division_definition_id, null: false
t.string :division_name,null: false
t.timestamps null: false
end
add_index :division_definitions, :division_definition_id, unique: true
end
When i try to create model definition through division definition in console i'm getting following error
PG::ForeignKeyViolation: ERROR: insert or update on table "model_definitions" violates foreign key constraint "fk_rails_addc8b742e"
DETAIL: Key (division_definition_id)=(124) is not present in table "division_definitions".
: INSERT INTO "model_definitions" ("model_id", "car_model_name", "division_definition_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"
(0.3ms) ROLLBACK
ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: insert or update on table "model_definitions" violates foreign key constraint "fk_rails_addc8b742e"
DETAIL: Key (division_definition_id)=(124) is not present in table "division_definitions".
: INSERT INTO "model_definitions" ("model_id", "car_model_name", "division_definition_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"
from /home/love/.rvm/gems/ruby-2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql_adapter.rb:602:in `exec_prepared'
This is what i tried,
DivisionDefinition.create(division_definition_id: '124', division_name: 'BMW')
a = DivisionDefinition.last.model_definitions.build(model_id: 'bmw1', car_model_name: 'bmw1')
a = DivisionDefinition.last.model_definitions.build(model_id: 'bmw1', car_model_name: 'bmw1')
a.save
If i remove add_foreign_key from db i am able to create model definition through divisiondefinition
what is the error i'm making in migration file?
Your ModelDefinitions class refers to :division_id which appears nowhere else in your code.

migration to add index when column is already exists in db rails?

how to add index when column is already exists in my db?
when i create migration like this :
class AddIndexToUsers < ActiveRecord::Migration
def change
remove_column :users, :id_number if index_exists?(:id_number)
add_column :users, :id_number, :string
add_index :users, :id_number, unique: true
end
end
i get error like this when create object with same id_number :
SQLite3::ConstraintException: column id_number is not unique: INSERT INTO "users" ("bank_account", "birth_date", "confirmed", "confirmed_at", "created_at", "credit_card_id", "email", "encrypted_password", "facebook_id", "google_id", "id_issuing_country", "id_number", "last_name", "name", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
class AddIndexToUsers < ActiveRecord::Migration
def change
remove_index :users, :id_number if index_exists?(:id_number)
add_index :users, :id_number, unique: true
end
end
This wiil fail if your already duplicate id_number entries in the :users table. You will have to remove the duplicates first if any
Think about your question very carefully...Why do you want to add something that already exists? If you want to generate a model in a relational database and not have an ID to it, you need to pass in :id => false
create_table(:categories_suppliers, id: false) do |t|
t.column :category_id, :integer
t.column :supplier_id, :integer
end
If you're mistaken, and your trying to ensure there is an ID to your model, you can test by going to your terminal and typing rails c
#users = User.all
#users.first.id
To validate this, you will need to actually have some data in your table. Of course, you'll know, because typing #users into your terminal will return an empty array.

Datetime field using Rails on Postgres

I'm using Rails to make a scheduling app with Postgres. I have a model Shift with two timedate columns, start_at and end_at. The migration to create it follows:
class CreateShifts < ActiveRecord::Migration
def change
create_table :shifts do |t|
t.references :user
t.references :schedule
t.datetime :start_at
t.datetime :end_at
t.string :position
t.string :notes
t.timestamps
end
add_index :shifts, :user_id
add_index :shifts, :schedule_id
end
end
When I try to create a record I get the following error 500 output:
GError: ERROR: column "end_at" is of type timestamp without time zone but expression is of type time without time zone at character 132
HINT: You will need to rewrite or cast the expression.
: INSERT INTO "shifts" ("created_at", "end_at", "notes", "position", "schedule_id", "start_at", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id"
I am creating a valid DateTime object before the DB save, because I've used the logger to display it and it is correct. The params look like this:
{"utf8"=>"✓",
"authenticity_token"=>"qornHMTAdikZJP/sByPIg//fFuYHHAQH3M/0R9XnP+o=",
"shift"=>{"user_id"=>"1",
"start_at(1i)"=>"2011",
"start_at(2i)"=>"11",
"start_at(3i)"=>"14",
"start_at(4i)"=>"00",
"start_at(5i)"=>"01",
"end_at(1i)"=>"2011",
"end_at(2i)"=>"11",
"end_at(3i)"=>"14",
"end_at(4i)"=>"00",
"end_at(5i)"=>"02",
"position"=>"",
"notes"=>""},
"schedule_id"=>"1"}
However, I can create a record via console by setting both fields to Time.now.
The error message is quite clear:
Your $2 in the INSERT statement is of type time instead of type timestamp (datetime)
INSERT INTO "shifts"
("created_at", "end_at", "notes", "position", "schedule_id", "start_at", "updated_at", "user_id")
VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id"
Emphasis mine.
You must be mixing up parameters, $2 is obviously not the one you display at the end of your posting. Or you inadvertently cast it to time before assigning. The part where you assign $2 is not visible in the question, that is where the problem occurs, most likely.
Maybe some kind of typo like in your question where you mention timedate instead of datetime?

Resources