I'm new to Rails (using 5.1) and I'm having trouble setting up my ActiveRecord associations.
Organizers can sign up and then create a club. An organizer belongs to one club (I guess could potentially have multiple but for now it's fine to expect just one). Clubs can have many organizers.
Clubs will always be created after the Organizer has been created so the foreign key on clubs is nil initially.
Here's the error I'm getting when trying to create an organizer without having any clubs already created:
ActiveRecord::InvalidForeignKey: ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: insert or update on table "organizers" violates foreign key constraint "fk_rails_bc04936880"
DETAIL: Key (club_id)=(0) is not present in table "club".
Organizer:
class Organizer < ApplicationRecord
belongs_to :club, optional: true
#also put config.active_record.belongs_to_required_by_default = false in application.rb
end
Club:
class Club < ApplicationRecord
has_many: organizers
end
Schema:
create_table "clubs", force: :cascade do |t|
t.string "full_name"
t.string "urn"
t.string "short_name"
t.string "address1"
t.string "address2"
t.string "city"
t.string "state"
t.string "zip"
t.string "website"
t.string "phone"
end
create_table "organizers", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
t.boolean "superuser", default: false
t.string "activation_digest"
t.boolean "activated", default: false
t.datetime "activated_at"
t.string "reset_digest"
t.datetime "reset_sent_at"
t.bigint "club_id"
t.index ["club_id"], name: "index_organizers_on_club_id"
t.index ["email"], name: "index_organizers_on_email", unique: true
end
add_foreign_key "organizers", "clubs"
Thanks in advance for the help!
For some reason your code tries to set 0 value to club_id.
I would suggest forcing nil in this attribute and observe if error still occurs:
Organizer.create!(
#...
club_id = nil
)
Related
I have a model Place which has reviews, which has a column stars.
I tried following query:
Place.select('place_id, name, avg(reviews.stars)').join(:reviews).group('place_id, name').order('avg(reviews.stars) desc')
I got following error:
PG::UndefinedColumn: ERROR: column "place_id" does not exist LINE 1: SELECT place_id, name, avg(reviews.stars) FROM "places" ^ : SELECT place_id, name, avg(reviews.stars) FROM "places"
How can he complain about place_id? This column is created by Rails. How can I solve this issue?
My models are:
class Review < ApplicationRecord
belongs_to :place
end
and
class Place < ApplicationRecord
has_many :reviews
end
The schema is as follows:
create_table "reviews", force: :cascade do |t|
t.integer "stars"
t.string "content"
t.bigint "place_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["place_id"], name: "index_reviews_on_place_id"
end
and
create_table "places", force: :cascade do |t|
t.bigint "user_id"
t.string "name"
t.string "description"
t.float "lng"
t.float "lat"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.float "latitude"
t.float "longitude"
t.string "address"
t.index ["user_id"], name: "index_places_on_user_id"
end
join is a method that is being delegated to underlying records, resulting in Array#join being called directly after your select.
You want to call joins instead of join to construct a proper query. If you take a closer look at your error, you will see that everything after select has been ignored.
I have two models: User and Listing.
I am trying to set up a one-to-many relationship between them via existing db columns.
class User < ApplicationRecord
has_many :listings
class Listing < ApplicationRecord
belongs_to :user, foreign_key: "user_id"
This is my migration:
class AddFkToListing < ActiveRecord::Migration[5.1]
def change
add_foreign_key :listings, :users, column: :user_id, primary_key: :user_id
end
end
But it created the foreign key in table users on column id.
Any idea how to do this properly?
Here is the DB schema:
create_table "listings", force: :cascade do |t|
t.integer "listing_id"
t.string "state"
t.integer "user_id"
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["listing_id"], name: "index_listings_on_listing_id", unique: true
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
t.boolean "admin", default: false
t.string "activation_digest"
t.boolean "activated", default: false
t.datetime "activated_at"
t.string "reset_digest"
t.datetime "reset_sent_at"
t.string "request_token"
t.string "request_secret"
t.string "oauth_verifier"
t.string "oauth_token"
t.string "login_name"
t.integer "user_id"
t.index ["email"], name: "index_users_on_email", unique: true
end
Thank you so much!
Since you have a conventional foreign key field name (user_id in listings table), I believe this should work just fine for you:
class AddFkToListing < ActiveRecord::Migration[5.1]
def change
add_foreign_key :listings, :users
end
end
The syntax of add_foreign_key is:
first argument (:listings) - table which should contain foreign key
second argument (:users) - table which should be used for constraint
column: :user_id - specifies to which field of the listings table constraint should be applied
primary_key: - specifies the field of the users table to build a constraint
(see https://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_foreign_key)
The primary_key: :user_id part in your example actually refers (tries to) to non-existing user_id field in users table.
I am trying to build a toy application and ran across an issue I cannot seem to solve. How do I enforce that a pair of values are unique in a table?
suppose the following schema:
create_table "courses", force: :cascade do |t|
t.string "title"
t.text "description"
t.string "number"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "status", default: 0
end
create_table "professors", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "status", default: 0
end
create_table "sections", force: :cascade do |t|
t.integer "number"
t.integer "max_enrollment"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "professor_id"
t.integer "course_id"
t.string "room"
t.index ["course_id"], name: "index_sections_on_course_id"
t.index ["professor_id"], name: "index_sections_on_professor_id"
end
and I wanted to create a uniqueness constraint in the sections table that the professor_id paired with course_id must be unique. the only thing I have found in my digging is that you can use the validates keyword in the model to enforce the uniqueness of a single field... I also saw that there is a validates_with keyword but I cannot find any way of writing a validator to do what I'm looking for. any help would be greatly appreciated.
Add a unique constraint in your database (Pun in a migration):
add_index :sections, [:professor_id, :course_id], unique: true
Now also put a validation constraint in your Section model:
validates_uniqueness_of :professor_id, scope: :course_id
Now your professor_id will be uniquely validated in the scope of course_id. Also there will be a unique constraint in your database table.
This is a rails project using ActiveRecord with Postgres.
Hi I'm working with two CSVs. One is a record of all registered voters in the state. When I created this table I didn't use a generated unique id as an indexed column, but instead used the already assigned state state_voter_id. Schema for Voter table:
create_table "voters", id: false, force: :cascade do |t|
t.string "state_voter_id", null: false
t.string "county_voter_id"
t.string "first_name"
t.string "middle_name"
t.string "last_name"
t.string "suffix"
t.string "birthdate"
t.string "gender"
t.string "add_st_num"
t.string "add_st_name"
t.string "add_st_type"
t.string "add_unit_type"
t.string "add_pre_direction"
t.string "add_post_direction"
t.string "add_unit_num"
t.string "city"
t.string "state"
t.string "zip"
t.string "county"
t.string "precinct"
t.string "leg_dist"
t.string "cong_dist"
t.string "reg_date"
t.string "last_vote"
t.string "status"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["city"], name: "index_voters_on_city"
t.index ["first_name"], name: "index_voters_on_first_name"
t.index ["last_name"], name: "index_voters_on_last_name"
t.index ["state_voter_id"], name: "index_voters_on_state_voter_id", unique: true
t.index ["zip"], name: "index_voters_on_zip"
end
I know want to add in a new table/model of vote records containing the state_voter_id as the reference to the Voter table
This is the migration I tried:
def change
create_table :votes do |t|
t.references :voter, column: :state_voter_id
t.string :county
t.string :date
t.timestamps
end
When I ran the migration It migrated, but when I tried to start seeding voter records I got the following error: ActiveRecord::UnknownPrimaryKey: Unknown primary key for table voters in model Voter. I also noted that the table was set up to take a bigint.
How do I set it up so that I am properly referencing the Voter on state_voter_id, which is an alphanumeric string?
Something along the lines of:
class AddPrimaryKeyToVoters < ActiveRecord::Migration
def change
change_column :voters, :state_voter_id, :primary_key
end
end
In your voters model add
self.primary_key = "state_voter_id"
The problem isn't with your migration, it's with your Model. You need this
class Voter < ApplicationRecord
self.primary_key = 'state_voter_id'
...
end
Note that's assuming Rails 5 with the new ApplicationRecord class. If you're using rails 4 then just inherit from ActiveRecord::Base as usual.
I have this problem, but don't know why.
I create models with generator:
bin/rails generate model Book name:string author:string description:text cover:string
bin/rails generate model Episode name:string description:text art:string
ant other...
book.rb
class Book < ApplicationRecord
has_many :episodes
end
episode.rb
class Episode < ApplicationRecord
belongs_to :book
has_many :scenes
end
When in console i try to: book.episodes << episode i had an error: ActiveModel::MissingAttributeError: can't write unknown attribute "book_id"
My schema.rb
ActiveRecord::Schema.define(version: 20170320111956) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "answers", force: :cascade do |t|
t.text "text"
t.string "next_scene"
t.string "next_episode"
t.string "voiceover"
t.integer "end"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "books", force: :cascade do |t|
t.string "name"
t.string "author"
t.text "description"
t.string "cover"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "episodes", force: :cascade do |t|
t.string "name"
t.text "description"
t.string "art"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "scenes", force: :cascade do |t|
t.string "name"
t.text "text"
t.integer "choise"
t.string "next_scene"
t.string "next_episode"
t.string "art"
t.string "music"
t.string "sound_fx"
t.string "voiceover"
t.integer "end"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
In schema i haven't id_book, but why? I also do db:migrate and have error again.
By default, Rails uses the convention of naming the primary as the autogenerated column id. If you wish to specify a different primary key, such as book_id, you could do the following:
class Book < ApplicationRecord
self.primary_key = "book_id"
end