0

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'] }
6
  • because you have one default and one custom validation in your model. Please remove this 'validates :pet_name, presence: true' , if you only want custom validation. Commented Nov 21, 2022 at 6:37
  • @lhh thanks. but it still not work because of the loop's nill error Commented Nov 21, 2022 at 7:57
  • @lhh can i validate before loop creating? Commented Nov 21, 2022 at 7:58
  • what you are trying to achieve here? is there any specific value are you checking in Array before saving ? Commented Nov 21, 2022 at 9:43
  • @lhh i'm trying to validate if params[:pet_name] (array) is nil before create, but i just changed to check params before create. thanks for your help Commented Nov 21, 2022 at 9:57

1 Answer 1

2

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 class="field">
    <%= form.label :name %>
    <%= form.text_input :name %>
  </div>

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

  <div class="actions">
     <%= 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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.