Mohamed El Mahallawy
Mohamed El Mahallawy

Reputation: 13842

Rails class methods validations

I have a few class methods that help with querying the database but I'd like to add some sort of validations for the params sent to these methods. For example,

def self.get_ayahs_by_range(surah_id, from, to)
      self.where('quran.ayah.surah_id = ?', surah_id)
          .where('quran.ayah.ayah_num >= ?', from)
          .where('quran.ayah.ayah_num <= ?', to)
          .order('quran.ayah.surah_id, quran.ayah.ayah_num')
    end

which is called from the controller by passing params[:surah_id], params[:to] and params[:from] to this function.

At times, for some reason, we have :surah_id being undefined which causes a mess. How can I fix by validations prior to?

Any suggestions for params validation other than strong_params which didn't work for an index action I felt?

controller:

def index
    unless valid_params?
      return render json: {message: 'Params are wrong.'}
    end

    params_hash = (params[:range] || ("#{params[:from]}-#{params[:to]}")) + "/#{params[:quran]}/#{params[:audio]}/#{params[:content]}"

    if params.key?(:range)
      range = params[:range].split('-')
    elsif params.key?(:from) && params.key?(:to)
      range = [params[:from], params[:to]]
    else
      range = ['1', '10']
    end

    if (range.last.to_i - range.first.to_i) > 50
      return render json: {error: "Range invalid, use a string (maximum 50 ayat per request), e.g. '1-3'"}
    end

    @results = Rails.cache.fetch("surahs/#{params[:surah_id]}/ayahs/#{params_hash}", expires_in: 12.hours) do
      ayahs = Quran::Ayah.get_ayahs_by_range(params[:surah_id], range[0], range[1])
      Quran::Ayah.merge_resource_with_ayahs(params, ayahs)
    end

    render json: @results
  end

Upvotes: 1

Views: 31

Answers (1)

SteveTurczyn
SteveTurczyn

Reputation: 36860

Make a new simple class in your models (it doesn't have to be a table in your database)

require 'ostruct'
class SearchOptions < OpenStruct
  include ActiveModel::Validations
  validates :surah_id, presence: true
  validates :from, presence: true
  ...
end

Then in the controller

@search_option = SearchOption.new(seach_params)
@search_option.valid?
   # here you put the "invalid" processing
   # maybe re-render the search parameters view
end

Upvotes: 1

Related Questions