Home > Back-end >  Rails call custom validation before .new or .create
Rails call custom validation before .new or .create

Time:11-25

I make objects in controller's loop.

I need to check pet_name array before loop starts. (because i got undefined method 'each' for nil:NilClass when params[:pet_name].each do |pid|) runs)

But my validation always called after User.new or User.create. I want to change to validate as when i push submit button and check validation, and redirects back when pet_name array is nil. Ho can i change my code?

Controller

  def create
    user_name = params[:user_name]
    
    params[:pet_name].each do |pid|
      @user = User.new
      @user.name = user_name
      @user.pet_name = pid
      render :new unless @user.save
    end
    redirect_to users_path
  end

User.rb

class User < ApplicationRecord
  has_many :pet

  validates :name, presence: true
  validates :pet_name, presence: true
  validate :check_pet
  def check_pet
    if pet_name.nil?
      errors.add(:pet_name, 'at least one pet id')
    end
  end
end

Prams structure

  { name: 'blabla', pet_name: ['blabla', 'blablabla', 'bla'] }

CodePudding user response:

Sorry but that isn't even close to how you approach the problem in Rails.

If you want a user to have many pets and accept input for the pets when creating users you need to create a working assocation to a Pet model and have the User accept nested attributes:

class User < ApplicationRecord
  has_many :pets # has_many assocations should always be plural!
  validates :name, presence: true
  validates :pets, presence: true
  accepts_nested_attributes_for :pets
end
# rails g model pet name user:reference
class Pet < ApplicationRecord
  belongs_to :user
  validates :name, presence: true
end
class UsersController < ApplicationController
  def new
    @user = User.new(user_params)
    3.times { @user.pets.new } # seeds the form with blank inputs
  end

  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user, 
        success: 'User created',
        status: :created
    else
      render :new, 
        status: :unprocessable_entity
    end
  end

  private

  def user_params
    params.require(:user)
          .permit(:name, pets_attributes: [:name])
  end
end
<%= form_with(model: @user) do |form| %>
  <div >
    <%= form.label :name %>
    <%= form.text_input :name %>
  </div>

  <fieldset>
     <legend>Pets</legend>
     <%= form.fields_for(:pets) do |pet_fields| %>
     <div >
       <div >
         <%= pet_fields.label :name %>
         <%= pet_fields.text_input :name %>
       </div>
     </div>
     <% end %>
  </fieldset>

  <div >
     <%= f.submit %>
  </div>
<% end %>

This is a pretty advanced topic and you should have your Rails CRUD basics well figured out before you attempt it. You should also consider if you instead want to use a separate controller to create the pets one by one as a nested resource after creating the user.

  • Related