Search code examples
ruby-on-railsrubydeviseassociationsruby-on-rails-6

How to add products to the Devise user model


I am beginner in Ruby on Rails and am trying to create a Shopper application in rails. There are 3 models : Batch, Product, User(Devise). Each batch has many products and each user has many products. I have created an association(has_many) between User and Product. How to add the specific product(Each product has a link to the products path) to the current user logged in if I click the link Buy.

My User model:

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  has_many :products, :dependent => :destroy
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end

My Product model:

class Product < ApplicationRecord
  belongs_to :batch
  belongs_to :user
  validates :name, presence: true

end

Routes file:

Rails.application.routes.draw do

  devise_for :users
  root to: 'batches#index'
  resources "batches", only: %i[index show]
  resources "products"
end

Schema file:

ActiveRecord::Schema.define(version: 2020_06_16_134907) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "batches", force: :cascade do |t|
    t.string "name"
    t.integer "code"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

  create_table "products", force: :cascade do |t|
    t.string "name"
    t.bigint "batch_id", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.bigint "user_id"
    t.index ["batch_id"], name: "index_products_on_batch_id"
    t.index ["user_id"], name: "index_products_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

  add_foreign_key "products", "batches"
end

Products controller:

class ProductsController < ApplicationController
  def show
    @product = Product.find(params[:id])
  end

  def index
    @products = Product.order(:name)
  end

  def new
    @product = Product.new
  end

  def create
    @product = current_user.products.build(params[:product])
    if @product.save
      puts 'yes'
    else
      puts 'no'
    end
  end

  private
  def prod_params
    params.require(:product).permit(:name, :user_id)
  end
end

Suggest me to specify the redirect_to links if the product is added to the user. I am printing a message. Clearly it didn't print it. I also referred this: How to associate a Devise User with another existing model?

Thanks in advance.


Solution

  • I am a bit confused about the actual problem you are having, but if your question is about links to your newly created Product... Your routes file defines products as:

    resources 'products'
    

    This will create a set of routes that have the base form:

    <root>/product/:id
    

    So, the URI namespace for your products is not currently scoped by user, and all you need is a product ID. So, if you have want to include a link to a user's set of products, you could do something like:

    <% current_user.products.each do |product|%>
      <%= link_to product.name, product_path(product.id) %>
    <% end %>
    

    If you really want the paths to products to be scoped by each user, you can do that too. The routes file allows you to nest resources inside another like this:

    resource :users do
      resources :products
    end
    

    That will generate routes of the form:

    <root>/users/:user_id/products/:id
    

    I suggest checking out the Rails Guide page on routes ( https://guides.rubyonrails.org/routing.html) to get an idea of the various things you can do to set up routes the way you want them.