Creating record that belongs to 2 seperate tables - ruby-on-rails

So I am trying to create a record that is associated with 2 tables but I cannot seem to get it to work.
Parameters: {"name"=>"asdfasd", "upc"=>"243252353", "availableOn"=>"07/12/2020", "properties"=>[{"name"=>"material", "value"=>"jean"}], "send_datum"=>{"name"=>"asdfasd", "upc"=>"243252353", "availableOn"=>"07/12/2020", "properties"=>[{"name"=>"material", "value"=>"jean"}]}}
class SendDataController < ApplicationController
protect_from_forgery with: :null_session
def save
product = Product.create(name:params[:name], upc:params[:upc].to_i, available_on:params[:availableon])
x=0
while x < params[:properties].length
property = product.properties.create(name:params[:properties][x][:name])
property.product_properties.create(value:params[:properties][x][:value])
x += 1;
end
end
end
This line is the one I cannot seam to get to work:
property.product_properties.create(value:params[:properties][x][:value])
This is my first react on rails project and understanding table assoc. has been a real challenge but I am getting there.
Models:
class Property < ApplicationRecord
belongs_to :product
has_many :product_properties
end
class Product < ApplicationRecord
has_many :properties
has_many :product_properties
end
class ProductProperty < ApplicationRecord
belongs_to :property
belongs_to :product
end
Migration:
class CreateProducts < ActiveRecord::Migration[5.2]
def change
create_table :products do |t|
t.string :name
t.string :upc
t.datetime :available_on
t.timestamps
end
end
end
class CreateProperties < ActiveRecord::Migration[5.2]
def change
create_table :properties do |t|
t.string :name
t.timestamps
end
end
end
class CreateProductProperties < ActiveRecord::Migration[5.2]
def change
create_table :product_properties do |t|
t.string :value
t.timestamps
end
end
end
class AddProductRefToProperties < ActiveRecord::Migration[5.2]
def change
add_reference :properties, :product, foreign_key: true
end
end
class AddProductRefToProductProperties < ActiveRecord::Migration[5.2]
def change
add_reference :product_properties, :product, foreign_key: true
end
end
class AddPropertiesRefToProductProperties < ActiveRecord::Migration[5.2]
def change
add_reference :product_properties, :property, foreign_key: true
end
end
Schema:
ActiveRecord::Schema.define(version: 2018_09_24_163027) do
create_table "product_properties", force: :cascade do |t|
t.string "value"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "product_id"
t.integer "property_id"
t.index ["product_id"], name: "index_product_properties_on_product_id"
t.index ["property_id"], name: "index_product_properties_on_property_id"
end
create_table "products", force: :cascade do |t|
t.string "name"
t.string "upc"
t.datetime "available_on"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "properties", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "product_id"
t.index ["product_id"], name: "index_properties_on_product_id"
end
end
UPDATE::
It is related to the fact that the product_property is getting the property_id from property but is not getting the product_id from the product. How do I fix that?
Any help is greatly appreciated. Thanks!!

The issue was I had my associations set up incorrectly. As #DavidAldridge pointed out I needed to link Property to Product through product property.
class Product < ApplicationRecord
has_many :product_properties
has_many :properties, through: :product_properties
end
class ProductProperty < ApplicationRecord
belongs_to :property, required: false
belongs_to :product, required: false
end
class Property < ApplicationRecord
has_many :product_properties
has_many :products, through: :product_properties
accepts_nested_attributes_for :product_properties
end

Related

RoR and Postgresql DB: belongs_to association works, but not has_many

I have two Models,
class Store < ApplicationRecord
self.primary_key = 'storeid'
has_many : employees
end
class Employee < ApplicationRecord
belongs_to :store, optional: true, foreign_key: :storeid
end
With the Following schema.rb,
create_table "employees", force: :cascade do |t|
t.text "storeid", null: false
t.index ["store_id"], name: "index_employees_on_store_id"
end
create_table "stores", force: :cascade do |t|
t.text "storeid", null: false
t.index ["storeid"], name: "index_stores_on_storeid", unique: true
end
add_foreign_key "employees", "stores", column: "store_id"
add_foreign_key "employees", "stores", column: "storeid", primary_key: "storeid"
end
My issue is that when I go to rails console, and try to query Store.first.employees, I just get a reference to the model and then it crashes. When I do Employee.first.stores It returns the appropriate associated store to the employee.
p.s. I'm aware of the, Rails naming convention issues
EDIT 0:
This is my latest migration
class Keys < ActiveRecord::Migration[6.0]
def up
add_index :stores, [:storeid], :unique => true
add_reference :employees, :stores, foreign_key: true
add_foreign_key :employees, :stores, column: :storeid, primary_key: :"storeid"
end
def down
execute "ALTER TABLE stores DROP CONSTRAINT table_pkey;"
end
end
Tables Migration:
class Stores < ActiveRecord::Migration[6.0]
def change
create_table :stores do |t|
t.column :storeid, :text, null: false, unique: true
t.column :contactname, :text, null: true
end
end
end
class Employees < ActiveRecord::Migration[6.0]
def change
create_table :employees do |t|
t.column :storeid, :text, null: false, unique: true
t.column :name, :text, null: true
end
end
end
Looks like your Store model is missing the foreign key:
class Store < ApplicationRecord
self.primary_key = 'storeid'
has_many :employees, foreign_key: :storeid
end

Unable to count records for associated model NoMethodError

I tried to multiple ways to get the count of all job applications for the job model, that an employer has. When it comes to one job in particular (job.job_applications.count), it works. You can actually count the applications for that job in question. When you try to sum all job applications for all jobs. I may have overlooked something while setting up the relationships. I receive the error below:
line of code that breaks: <%= current_employer.jobs.job_applications.count %>
undefined method job_applications' for #<Job::ActiveRecord_Associations_CollectionProxy:0x0000000011066998>
The code that I wrote beforehand, is below:
schema
job
create_table "jobs", force: :cascade do |t|
t.string "job_title"
t.text "required_exp"
t.text "job_description"
t.text "job_requirements"
t.bigint "employer_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "slug"
t.bigint "visit_id"
t.index ["employer_id"], name: "index_jobs_on_employer_id"
t.index ["slug"], name: "index_jobs_on_slug", unique: true
end
job applications
create_table "job_applications", force: :cascade do |t|
t.bigint "user_id"
t.string "user_resume_link"
t.string "user_contact_time"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "user_first_name"
t.string "user_last_name"
t.bigint "job_id"
t.index ["job_id"], name: "index_job_applications_on_job_id"
t.index ["user_id"], name: "index_job_applications_on_user_id"
end
job.rb
class Job < ApplicationRecord
belongs_to :employer
has_many :job_applications, dependent: :destroy
has_one :job_category
end
job_application.rb
class JobApplication < ApplicationRecord
belongs_to :user
belongs_to :job
end
employer.rb
class Employer < ApplicationRecord
has_many :jobs, :dependent => :destroy
end
user.rb
class User < ApplicationRecord
has_many :job_applications, dependent: :destroy
has_many :jobs, :through => :job_applications
end
class Employer < ApplicationRecord
has_many :jobs, :dependent => :destroy
has_many :job_applications, through: :jobs
end
And then just call current_employer.job_applications.count

About associations

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

ActiveRecord -- user has_many events and belongs to those events as member

I want to set up a relationship where users can start events and then also join them as members. I figured this uses a many to many relationship, but it also has a simple belongs_to relationship from Event to User.
class User < ActiveRecord::Base
has_secure_password
has_many :events # => Owning
has_many :events, through: :members # => Joining
end
class Event < ActiveRecord::Base
belongs_to :user # => event owner
has_many :users, through: :members # => joining users
end
class Member < ActiveRecord::Base
belongs_to :user
belongs_to :event
end
But I'm having trouble getting queries like Event.first.members to work... I can't figure out what's preventing me from using these methods. Am I thinking of these relationships the wrong way? My Schema.rb:
ActiveRecord::Schema.define(version: 20161205220807) do
create_table "events", force: :cascade do |t|
t.string "title"
t.string "location"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "events", ["user_id"], name: "index_events_on_user_id"
create_table "members", force: :cascade do |t|
t.integer "user_id"
t.integer "event_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "members", ["event_id"], name: "index_members_on_event_id"
add_index "members", ["user_id"], name: "index_members_on_user_id"
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.integer "age"
t.string "password_digest"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
Updated to fix my mistake
class User < ActiveRecord::Base
has_secure_password
has_many :members
has_many :events, through: :members
end
class Event < ActiveRecord::Base
#belongs_to :user # => event owner
has_many :members
has_many :users, through: :members
class Member < ActiveRecord::Base
belongs_to :user
belongs_to :event
end
If this is giving you a stack level too deep error im guessing the issue is elsewhere. Your logs might have more info.

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.

Resources