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.
Related
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!
I have 3 Models. Proprietor, Property and Renter.
I'm confuse about Renter association because in my real estate system a tenant can have several leased properties.
Maybe has_many through ? If yes. How implement this?
class Proprietor < ApplicationRecord
has_many :properties, dependent: :destroy
end
class Property < ApplicationRecord
belongs_to :proprietor
end
class Renter < ApplicationRecord
end
class CreateProprietors < ActiveRecord::Migration[5.0]
def change
create_table :proprietors do |t|
t.string :full_name
t.string :email
t.date :birthday
t.string :social_security
t.string :doc_id
t.text :address
t.string :zip_code
t.timestamps
end
end
end
class CreateProperties < ActiveRecord::Migration[5.0]
def change
create_table :properties do |t|
t.references :proprietor, foreign_key: true
t.text :address
t.string :zip_code
t.integer :rooms
t.integer :bedrooms
t.integer :bathrooms
t.integer :garage
t.string :price
t.boolean :published, defalt: false
t.timestamps
end
end
end
class CreateRenters < ActiveRecord::Migration[5.0]
def change
create_table :renters do |t|
t.string :full_name
t.string :email
t.date :birthday
t.string :social_security
t.string :doc_id
t.timestamps
end
end
end
I don't think you need a has_many through on this (unless properties can have many renters as well as renters having many properties?)
If the need is as you state in your question this should be achievable like so:
class Proprietor < ApplicationRecord
has_many :properties, dependent: :destroy
end
class Property < ApplicationRecord
belongs_to :proprietor
belongs_to :renter
end
class Renter < ApplicationRecord
has_many :properties
end
class CreateProprietors < ActiveRecord::Migration[5.0]
def change
create_table :proprietors do |t|
t.string :full_name
t.string :email
t.date :birthday
t.string :social_security
t.string :doc_id
t.text :address
t.string :zip_code
t.timestamps
end
end
end
class CreateProperties < ActiveRecord::Migration[5.0]
def change
create_table :properties do |t|
t.references :proprietor, foreign_key: true
t.references :renter, foreign_key: true
t.text :address
t.string :zip_code
t.integer :rooms
t.integer :bedrooms
t.integer :bathrooms
t.integer :garage
t.string :price
t.boolean :published, default: false
t.timestamps
end
end
end
class CreateRenters < ActiveRecord::Migration[5.0]
def change
create_table :renters do |t|
t.string :full_name
t.string :email
t.date :birthday
t.string :social_security
t.string :doc_id
t.timestamps
end
end
end
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
I'm getting a weird error. I had sqlite3 working and now switching over to postgres, i'm getting this error.
I have migrations, and I had to add a new column.
create_ideas migration
class CreateIdeas < ActiveRecord::Migration
def change
create_table :ideas do |t|
t.string :name
t.text :description
t.string :picture
t.timestamps
end
add_foreign_key :ideas, :lists
end
end
add_list_id_column_to_ideas migration
class AddListIdColumnToIdeas < ActiveRecord::Migration
def change
add_column :ideas, :list_id, :integer
end
end
What is wrong with my foreign key? I get the error when I do rake db:migrate
I have another migration with foreign key, and no errors yet? Maybe its catching the first error first before seeing the other one, but I have this one too:
create_comments migration
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :user_name
t.text :body
t.integer :idea_id
t.timestamps
end
add_foreign_key :comments, :ideas
end
end
last migration I have create_lists
class CreateLists < ActiveRecord::Migration
def change
create_table :lists do |t|
t.string :name
t.text :description
t.string :picture
t.timestamps
end
end
end
Any clue why I'm getting errors?
Thanks
edit
my relationships
comments model
belongs_to :idea
idea model
belongs_to :list
has_many :comments
list model
has_many :ideas
I'm making an extension for refinerycms in rails and this is the structure I follow :
Project has many project_images
Project_images belongs_to Project & Image ( The refinery Image class )
Now when I want to create a new object of ProjectImage in my Project class I always get this error :
Unknown primary key for table refinery_projects_images in model Refinery::Projects::ProjectImage.
I don't need a primary key for this table because it is a join table. Here is the code of my models and migration file:
Migration.rb
class CreateProjectsProjects < ActiveRecord::Migration
def up
create_table :refinery_projects do |t|
t.string :title
t.text :description
t.string :investor
t.string :location
t.string :area
t.string :purpose
t.string :architect
t.string :users
t.integer :position
t.integer :position
t.timestamps
end
add_index :refinery_projects, :id
create_table :refinery_projects_images, :id => false do |t|
t.references :image
t.references :project
t.integer :position
t.string :category
t.string :caption
end
add_index :refinery_projects_images, [:image_id, :project_id], :uniq => true
end
def down
if defined?(::Refinery::UserPlugin)
::Refinery::UserPlugin.destroy_all({:name => "refinerycms-projects"})
end
if defined?(::Refinery::Page)
::Refinery::Page.delete_all({:link_url => "/projects/projects"})
end
drop_table :refinery_projects
drop_table :refinery_projects_images
end
end
Project.rb
module Refinery
module Projects
class Project < Refinery::Core::BaseModel
self.table_name = 'refinery_projects'
attr_accessible :title, :description, :investor, :location, :area, :purpose, :architect, :users, :position, :position, :images_attributes
acts_as_indexed :fields => [:title, :description, :investor, :location, :area, :purpose, :architect, :users]
validates :title, :presence => true, :uniqueness => true
has_many :project_images
has_many :images, :through => :project_images, :order => 'position ASC'
accepts_nested_attributes_for :images, :allow_destroy => false
def images_attributes=(data)
ProjectImage.delete_all(:project_id => self.id)
(0..(data.length-1)).each do |i|
unless (image_data = data[i.to_s]).nil? or image_data['id'].blank?
project_image = self.project_images.new(:image_id => image_data['id'].to_i, :position => i)
# Add caption if supported
if false
project_image.caption = image_data['caption']
end
self.project_images << project_image
end
end
end
end
end
end
ProjectImage.rb
module Refinery
module Projects
class ProjectImage < Refinery::Core::BaseModel
self.table_name = 'refinery_projects_images'
attr_accessible :image_id, :position
belongs_to :image, :class_name => 'Refinery::Image'
belongs_to :project, :class_name => 'Refinery::Projects::Project'
end
end
end
Somebody knows why he keeps looking for the primary key?
Refinery::Core::BaseModel is somehow derived from ActiveRecord::Base. When you use that class then your table layout needs an id. If you don't want an id, Have a look at has_and_belongs_to_many in the rails guides: http://guides.rubyonrails.org/association_basics.html