PG::UndefinedColumn: ERROR: column services.zip_code does not exist - ruby-on-rails

I have 2 models (Service and Town) with a :has_many :through relationship. I want to be able to find every services of a town and every towns of a service.
Also in front I should never be able to see my Town ID so I can link service and town only with the zip_code of a town.
Here is all my migrations
create_table :services, type: :uuid do |t|
t.string :name, null: false
t.string :action, null: false
t.string :kind, null: false
end
create_table :towns do |t|
t.string :name, null: false
t.stirng :zip_code, null: false
t.string :country, null: false
end
create_table :services_towns do |t|
t.belongs_to :service
t.belongs_to :town
t.string :zip_code, null: false
t.index :zip_code
end
here are my models
class Town < ApplicatonRecord
has_many :services_towns, primary_key: :zip_code, foreign_key: :zip_code
has_many :services, through: :services_communes
end
class Service < ApplicationRecord
has_many :services_towns
has_many :towns, through: :services_communes
end
class ServicesTown < ApplicationRecord
belongs_to :service
belongs_to :town, primary_key: :zip_code, foreign_key: :zip_code
end
#service.towns and #town.services are working well in my rails console but if I try a more complex search like
Service.where(towns: [towns_array]) I got the following error
PG::UndefinedColumn: ERROR: column services.zip_code does not exist
With this request I would like to have every Services from every Towns I have passed in the array.
I guess the problem are because of my primary_key or foreign_key but I don't know what to do better

You need to fix your query, try this
Service.joins(:towns).where(towns: { zip_code: towns_array })
or
Service.joins(:towns).where("towns.zip_code IN (?)", towns_array)
Hope that helps!

Related

Foreign Key is not being updated correctly after running migrations in Rails 5

I have Users and Protests tables. Users can create protests.
I want to add user foreign key to Protests table with a different name "creator". Whenever I run my migrations, I expect to see creator_id in my Protests table, but I see user_id instead in my schema.rb. What could be the reason for that? Thank you.
User Model
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates :first_name, :last_name, :email, presence: true
has_many :protests, foreign_key: :creator_id
has_many :attendances
has_many :attended_protests, through: :attendances, source: :protest
has_many :passengers
has_many :transportations, through: :passengers
end
Protest Model
class Protest < ApplicationRecord
validates :name, :description, :location,
:starts_at, :creator, presence: true
has_attached_file :image, styles: {thumb: "100x100#", medium:"400x600#" }, default_url: "/images/default_:style_avatar.png"
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
belongs_to :creator, class_name: :User
has_many :attendances
has_many :users, through: :attendances
has_many :transportations
end
Protests Migration
class CreateProtests < ActiveRecord::Migration[5.1]
def change
create_table :protests do |t|
t.string :name
t.text :description
t.string :location
t.datetime :starts_at
t.references :user
end
end
end
What I get in my schema.rb
...
create_table "protests", force: :cascade do |t|
t.string "name"
t.text "description"
t.string "location"
t.datetime "starts_at"
t.bigint "user_id"
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.index ["user_id"], name: "index_protests_on_user_id"
end
...
You see user_id because of this line in your migration:
t.references :user
To get creator_id you can use integer instead of references:
t.integer :creator_id
Try changing you migration to:
t.references :creator, index: true, foreign_key: { to_table: :users }
credit to this answer:
https://stackoverflow.com/a/42056089/4553162

adding t.reference or t.belongs_to for models in has many through

I have a has many through relationship. Should I have foreign key in Physician and patient model?
class CreateAppointments < ActiveRecord::Migration
def change
create_table :physicians do |t|
t.string :name
t.references :patient, index: true
t.timestamps null: false
end
create_table :patients do |t|
t.string :name
t.references :physician, index: true
t.timestamps null: false
end
create_table :appointments do |t|
t.belongs_to :physician, index: true
t.belongs_to :patient, index: true
t.datetime :appointment_date
t.timestamps null: false
end
end
end
You don't need need to add index in both physicians and patients table, since your appointments table holding both of these indexes. You can access Patients of a Physician, vice versa through this association itself, all you need to do is mention it in your physician and patient model,
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, through: :appointments
end
and your migration file should be like this.
class CreateAppointments < ActiveRecord::Migration
def change
create_table :physicians do |t|
t.string :name
t.timestamps null: false
end
create_table :patients do |t|
t.string :name
t.timestamps null: false
end
create_table :appointments do |t|
t.belongs_to :physician, index: true
t.belongs_to :patient, index: true
t.datetime :appointment_date
t.timestamps null: false
end
end
end
When you are adding references that will generate the foreign key in its corresponding table.

Two different relations between same two models

I have two models: users and emails.
I have separated this tables because we want the user to be able to have many emails in the same user account, and also easily check uniqueness of email values among accounts.
primary_email_id is a FK of a unique email, but also a user has many emails. How do I say that in the rails model?
I was trying
class User < ActiveRecord::Base
# relations
has_many :emails
has_one :primary_email
end
…
class Email < ActiveRecord::Base
# relations
belongs_to :user
end
Is that correct? How does rails know when I say primary_email I'm making reference to the emails table?
By the way, both migrations are:
create_table :users do |t|
t.string :username
t.string :first_name
t.string :last_name
t.binary :password
# t.integer :primary_email
t.timestamps null: false
end
create_table :emails do |t|
# t.integer :user
t.string :email
t.boolean :verified
t.timestamps null: false
end
add_reference :users, :primary_email, references: :emails, index: true, foreign_key: true
add_reference :emails, :user, index: true, foreign_key: true

Rails4 how to create the model relationship on join table

this is user table:
create_table :users do |t|
t.string :name
t.string :password
t.string :department
t.timestamps
end
this is meet table:
create_table :meets do |t|
t.string :name, null: false
t.string :state, null: false
t.string :description, null: false
t.string :location, null: false
t.float :spend, null: false
t.timestamps
end
The following is a relationship between user and meet:
user can create many meets
a meet can have many participants(users)
I am new to study rails, i tried to create migration and model, But i do not know the correct way:
User can create many meets, I think i can add reference in meets migrate to create a one to one relationship
t.references :users
a meet can have many users, I think i must create a join table:
rails g migration CreateJoinTableUsersMeets user meet
The above command will auto generate a migration file:
create_join_table :Users, :Ploys do |t|
t.index [:user_id, :ploy_id]
t.index [:ploy_id, :user_id]
end
But i want know how to create model relationship on join tabel?
This is how I would do it.
create_table :users do |t|
t.string :name
t.string :password
t.string :department
t.timestamps
end
create_table :meets do |t|
t.string :name, null: false
t.string :state, null: false
t.string :description, null: false
t.string :location, null: false
t.float :spend, null: false
t.references :creator, class_name: "User"
t.timestamps
end
create_table :participations do |t|
t.references :user
t.references :meet
end
add_index :participations, [:user_id, :meet_id]
add_index :participations, [:meet_id, :user_id]
class User < ActiveRecord::Base
has_many :meets, through: :participations
has_many :created_meets, class_name: "Meet", foreign_key: "creator_id"
end
class Meet < ActiveRecord::Base
has_many :users, through: :participations
belongs_to :creator, class_name: "User"
end
You do not create a one to one relationship in the table but you just have to create a join table called participations. That model will have a reference to a user and a meet. Then, you can specify has_and_belongs_to_many by adding the above code to both models. The point is that it uses the join table to create associations. Comment if you have any other question :)

Rails has_one and belongs_to migration?

I'm trying to establish a relationship between two models in Rails but I am having trouble figuring out what I need to do in my migration. Any help is much appreciated.
I want each business to have a type/category such as "Automotive", or "Restaurant and Bar".
Business.rb:
class Business < ActiveRecord::Base
has_one :category, :foreign_key => "cid"
attr_accessible :description, :email, :facebook, :foursquare, :google, :manager,
:mobile, :name, :phone, :url, :yelp
end
Type.rb:
class Type < ActiveRecord::Base
attr_accessible :cid, :category
belongs_to :business
end
CreateTypes migration file:
class CreateTypes < ActiveRecord::Migration
def change
create_table :types do |t|
t.integer :cid
t.string :category
t.references :business
t.timestamps
end
add_index :types, :cid
end
end
CreateBusinesses migration file:
class CreateBusinesses < ActiveRecord::Migration
def change
create_table :businesses do |t|
t.string :name
t.string :url
t.string :phone
t.string :manager
t.string :email
t.boolean :mobile
t.boolean :foursquare
t.boolean :facebook
t.boolean :yelp
t.boolean :google
t.text :description
t.integer :cid
t.timestamps
end
end
end
It would be easiest for you to keep with rails naming conventions. If I got it correctly, a business belongs to a Type/Category. let the business reference the type. add a belongs_to on the business side and a has_many on the type/category side. Roughly like this:
class Business < ActiveRecord::Base
attr_accessible :description, :email, :facebook, :foursquare, :google, :manager, :mobile, :name, :phone, :type_id, :url, :yelp
belongs_to :type
end
class Type < ActiveRecord::Base
has_many :businesses
end
class CreateTypes < ActiveRecord::Migration
def change
create_table :types do |t|
t.string :category
t.timestamps
end
end
end
class CreateBusinesses < ActiveRecord::Migration
def change
create_table :businesses do |t|
t.string :name
t.string :url
t.string :phone
t.string :manager
t.string :email
t.boolean :mobile
t.boolean :foursquare
t.boolean :facebook
t.boolean :yelp
t.boolean :google
t.text :description
t.integer :type_id
t.timestamps
end
end
end
Your businesses table must have integer field cid, because it you set it as a foreign key. You types table must not have cid field. The types.id field will be used to create a relationship. Note that belongs_to method doesn't have foreign_key option, you should remove it from its call.
I can advise you not to change foreign key name without a reason. If you don't specify foreign key, it defaults to type_id.

Resources