Home > Back-end >  Rails Need help to capture form field in model from product view
Rails Need help to capture form field in model from product view

Time:08-14

I need to capture a field added by a user in a form_for, inside the product show page.

My product.rb model as follows:

belongs_to :user
has_many :complaints

My complaint.rb model as follows:

belongs_to :product
belongs_to :user

My user.rb model as follows:

has_many :products

My product controller is a basic controller with all the new, create, edit, update actions and all the routes are good.

User looks at the product show page like this, and it's all good

http://localhost:3000/products/1

My goal is to create a complaint from the product show page, when user views the specific product. So I have created a complaints_controller.rb to capture all the details of the product, and create a complaint. I have an issue with capturing the complaint_number which is a field inside the complaints table.

Here is my form inside the product show page

<%= form_for([@product, @product.complaints.new]) do |f| %>
  <%= f.number_field :complaint_number, placeholder: "Enter complaint number you were given" %>
  <%= f.submit 'Complaint' %>
<% end %>

Here is my complaints_controller.rb

Goal is to capture the complaint_number fields and run the make_complaint method to create a complaint and populate rest of the fields in the newly created row of the complains table.

class ComplaintsController < ApplicationController
  before_action :authenticate_user!
  
  def create

    # Will Get product_id from the action in the form in product show page.
    product = Product.find(params[:product_id])
    # This complaint_number does not seem to work
    complaint_number = product.complaints.find_by(complaint_number: params[:complaint_number])

    # Now I want to run a make_complaint method and pass the product and the complaint number. This fails, I can't capture the complaint_number in the form from user input.
    make_complaint(product, complaint_number) 
    redirect_to request.referrer

  end

  private

    def make_complaint(product, complaint_number)
      
      complaint = product.complaints.new
      complaint.title = product.title
      complaint.owner_name = product.user.name
      complaint.owner_id = product.user.id
      
      # Note: complaint_number and current_complaint are a fields in the Orders table
      # Note: 
      complaint.current_complaint = complaint_number

      if complaint.save
        flash[:notice] = "Your complaint has been sent!"
      else
        flash[:alert] = complaint.errors.full_messages
      end

    end

end

For routes I have added resources :complaint, only: [:create] inside the resources of products to get products/:id/complaints

My routes.rb is like this

Rails.application.routes.draw do
  
  get 'products/new'
  get 'products/create'
  get 'products/edit'
  get 'products/update'
  get 'products/show'
  root 'pages#home'

  get '/users/:id', to: 'users#show'

  post '/users/edit', to: 'users#update'

  resources :products do
    member do 
      delete :remove_image
      post :upload_image
    end
    resources :complaint, only: [:create]
  end

  devise_for :users, path: '', path_names: { sign_in: 'login', sign_up: 'register', sign_out: 'logout', edit: 'profile' }
           

CodePudding user response:

Your form has complaint_quantity:

<%= form_for([@product, @product.complaints.new]) do |f| %>
  <%= f.number_field :complaint_quantity, placeholder: "Enter complaint number you were given" %>
  <%= f.submit 'Complaint' %>
<% end %>

Your controller has complaint_number:

complaint_number = product.complaints.find_by(complaint_number: params[:complaint_number])

If you check your params from the server log, I bet you'll see the value you are looking for is coming across as complaint_quantity and not complaint_number.

UPDATE

With the form misspelling corrected, the error persists, so let's check into more areas:

complaint_number = product.complaints.find_by(complaint_number: params[:complaint_number])

So, break that down:

1. What does params actually include?

Is :complaint_number being submitted from the form? If not, the form still has an error somewhere.

2. Does product.complaints actually include a complaint that could be matched by complaint_number?

I don't know your data structure well enough to tell, but it looks to me like you might actually want to do:

Complaint.find_by(complaint_number: params[:complaint_number])

instead of:

products.complaints.find_by(complaint_number: params[:complaint_number])

UPDATE #2

You know the problem is with your params.

I'm confident you aren't accessing your params correctly since you are using a nested form:

form_for([@product, @product.complaints.new])

Should mean your params are structured like { product: { complaint: { complaint_number: 1234 }}}

So params[: complaint_number] is nil because it should really be something like params[:product][:complaint][:complaint_number]

Please look at your server log in your terminal right after you submit the form to see the structure of your params. Or insert a debugger in the controller action and see what params returns.

ALSO, Instead of accessing params directly, you should whitelist params as a private method in your controller.

Something along these lines:

private

def product_complaint_params
  params.require(:product).permit(:id, complaint_params: [ :complaint_number ])

end

See this: https://api.rubyonrails.org/classes/ActionController/StrongParameters.html

  • Related