JuanM.
JuanM.

Reputation: 432

How to validate presence of at least one field in form in Ruby on Rails

I have a Searching model that contains several columns. Those columns are filled with a common form_for @search do |s| in app/views/searchings/index.html.erb. So the thing is that I got three fields on that view, each one activated by its own checkbox. I want to validate the presence of at least one field. I tested without validations and when an input field is disabled its value is nil. Here is the code:

app/models/searching.rb

  class Searching < ActiveRecord::Base
      belongs_to :user

      validate :capacidad_num
      validate :has_a_field

      def has_a_field
        arr = [self.tipo?, self.capacidad?, self.ubicacion_cont?, self.free_to?, self.free_from?]
        if !arr.include?(true)
          self.errors.add(:base, 'Debes ingresar al menos one parameter de búsqueda')
        end
      end

      def capacidad_num
        if self.capacidad?
          if !(self.capacidad.to_i != 0)
            self.error.add(:capacidad, 'tiene que ser un número')
          end
        end
      end

  end

app/controllers/searchings_controller.rb

class SearchingsController < ApplicationController
    before_action :get_search, only: [:show]

    def index

      @couches = Couch.all
      @tipos = Tipoc.all
      @search = Searching.new

    end

    def show
      #...show stuff not important
    end


    def create
      @search = Searching.new(params.permit(:tipo, :ubicacion_cont, :capacidad))

      respond_to do |format|
        if @search.save
          format.html { redirect_to @search, notice: "Mostrando resultados de búsqueda" }
          format.json { render :show, status: :created, location: @search }
        else
          format.html { render :index }
          format.json { render json: @search.errors, status: :unprocessable_entity }
        end
     end
   end

   private
   def get_search
     @search = Searching.find(params[:id])
   end

end

If it helps, here is the schema of this model:

create_table "searchings", force: :cascade do |t|
 t.integer  "tipo"
 t.string   "ubicacion_cont"
 t.integer  "capacidad"
 t.date     "free_from"
 t.date     "free_to"
 t.datetime "created_at",       null: false
 t.datetime "updated_at",       null: false
end

I tried to verify the presence of at least one field with an array containing boolean values of each field but it seems not to be working. Every time I input values on the form it gives me error.

Upvotes: 0

Views: 1653

Answers (3)

JuanM.
JuanM.

Reputation: 432

I got another approach to the solution, and worked fine. In my controller inside def create I check if params[:searching] is nil. If so, show a message of alert.

def create

  if params[:searching].nil?

    redirect_to new_searching_path, alert: 'Debes ingresar al menos un parámetro'

  else

    #do the new and save stuff

  end

end

I ended up with this solution after using byebug and checking what I was receiving in params inside my def create. I know it's not some good practise of rails programming, but for what I want, it works like a charm.

Upvotes: 0

user3506853
user3506853

Reputation: 814

Try this:-

def has_a_field
    arr = [self.tipo, self.capacidad, self.ubicacion_cont, self.free_to, self.free_from]
    arr_with_present_val = arr.select(&:presence)
    if arr_with_present_val.blank?
        self.errors.add(:base, 'Debes ingresar al menos one parameter de búsqueda')
        return false    
    end
end

Upvotes: 1

spickermann
spickermann

Reputation: 107142

I am not sure if the magic boolean check (just adding a ? to the attribute name) works like this. I would try something like this:

def has_a_field
  fields = [:tipo, :ubicacion_cont, :capacidad, :free_to, :free_from]

  unless fields.any? { |field| self.send(field).present? }
    errors.add(:base, 'Debes ingresar al menos one parameter de búsqueda')
  end
end

Upvotes: 1

Related Questions