Home > Enterprise >  Ruby on rails - How to associate with generated folders that are nested/sub folders of other folders
Ruby on rails - How to associate with generated folders that are nested/sub folders of other folders

Time:07-21

I have a folder named admin that has a generated scaffolding in it named products that also has the primary_key, id, changed to ect. I then created a model called cart_products that has a belongs_to :product. When I try to use it like: @cart.cart_products.create(product: @product, quantity:), it throws a name error, saying

Rails couldn't find a valid model for Product association. Please provide the :class_name option on the association declaration. If :class_name is already provided, make sure it's an ActiveRecord::Base subclass.

So I then changed the belongs_to to belongs_to :product, :class_name => "Admin::Product" which is the name of the product model. Now I am getting an

ActiveRecord::StatementInvalid - SQLite3::SQLException: no such table: main.products

Where did main.products come from when in my database it is saved as create_table "admin_products", primary_key: "ect", force: :cascade do |t|?

This is what My code looks like:

# controllers/home/cart_controller.rb
class Home::CartController < HomeController
  def add
    @product = Admin::Product.find_by(ect: params[:ect])
    # Code breaks on next line
    @cart.cart_products.create(product: @product, quantity:)
  end
end

# models/cart_product.rb
class CartProduct < ApplicationRecord
  belongs_to :product, class_name: "Admin::Product"
  belongs_to :cart
end

# models/admin/product.rb
class Admin::Product < ApplicationRecord
    has_many :cart_products
    has_many :carts, through: :cart_products
  end
end

# models/admin.rb
module Admin
  def self.table_name_prefix
    "admin_"
  end
end

The Database that I am trying to access is:

# associated with models/admin/product.rb
create_table "admin_products", primary_key: "ect", force: :cascade do |t|
    t.string "title"
    t.decimal "price"
    t.text "description"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
end
# associated with models/cart_product.rb
class CreateCartProducts < ActiveRecord::Migration[7.0]
  def change
    create_table :cart_products do |t|
      t.belongs_to :product, null: false, foreign_key: true
      t.belongs_to :cart, null: false, foreign_key: true
      t.integer :quantity

      t.timestamps
    end
  end
end

CodePudding user response:

Always run after scaffolding with any model

rails db:migrate

CodePudding user response:

Is your model file admin/product.rb

class Admin::Product < ApplicationRecord

If yes, then you need to have class_name with associations as below

belongs_to :product, class_name: "Admin::Product"

CodePudding user response:

You have to tell rails the table name:

# app/models/admin/product.rb
module Admin
  class Product < ApplicationRecord
    self.table_name = "admin_products"
  end
end

Or add prefix to every table for models in Admin module.

# app/models/admin.rb
module Admin
  def self.table_name_prefix
    "admin_"
  end 
end

Update

Rollback your CreateCartProducts migrations and update it to fix foreign key constraint:

# NOTE: by default when foreign key constraint is created
#       the name of the foreign table is inferred from
#       the argument `:product`. There is no `products` table,
#       which is why SQLite complains about it in the error;
#       custom primary key has to be also specified.
# t.belongs_to :product, null: false, foreign_key: true
t.belongs_to :product, null: false,
  foreign_key: { to_table: :admin_products, primary_key: "ect" }

Run migrations again. This should fix it.

Also, it's probably best to set up PostgreSQL for development. It would have raised an error when trying to run that migration, but SQLite seems to be ok with migration but complains later.


https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema/ClassMethods.html#method-i-table_name

https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_reference

  • Related