unflores
unflores

Reputation: 1810

Should I ever put validation in a controller in Rails?

I have an instance where I will do certain validations on a resource but not another, where the two resources map to the same model.

In concrete, I have an export model which is linked to a competition and I build an export of all the users in that competition. So naturally there will be a validation to ensure that there is a competition attached. However, a client wants to also be able to build all of the user exports at a given time and have it work like the competition exports.

I plan on using two separate resources for that(routes, controllers) but a validation only makes sense on a per resource level.

Anyone have any thoughts wrt best practices?

Upvotes: 1

Views: 1358

Answers (2)

JayJay
JayJay

Reputation: 814

To be honest, no. Your best solution would be to split responsibility of export variant into specific classes that carry out the behavior you want on a model. Psuedo code for example, just guessing at implementation here- and may need fettling:

class CompetitionExports
  self.abstract_class: true # order just include the relevent ActiveRecord modules
  MODEL = Export

  def initialize(id)
    @competition_export_id = id
  end

  def all
    return [] unless validate
    MODEL.where(id: competition_exports_id).joins(:users) #can pluck/ select what you want here
  end

  private
  attr_reader :competition_export_id
  def validate
    return true if MODEL.where(id: competiton_export_id).has_competition?
    self.errors.add(:competition, 'does not exist')
    false
  end
end

class UserExports
  self.abstract_class: true # order just include the relevent ActiveRecord modules
  MODEL = Export
  def initialize(id)
    @user_export_id = id
  end

  def all_at(date)
    return [] unless validate(date)
    MODEL.where(id: user_exports_id).joins(:users) #can pluck/ select what you want here
  end

  private
  attr_reader :user_export_id
  def validate(date)
    return true if MODEL.where(id: user_export_id, date: date).present? 
    self.errors.add(:user, "no users at #{date}")
    false
  end
end

So here, I have two resources that check the Export model for their own specific behavior, without actually interfering with the model itself. This keeps the business logic at the model level itself, without mixing it in with everything.

In the controller, you could then just instantiate the class you need at the time. So for all Competition users:

export = CompetitionExports.new(params[:id])
export.all 

or users at specific date

export = UserExports.new(params[:id])
export.all_at(params[:date])

Both will run through their specific validations before processing the results.

Upvotes: 1

Hardik Upadhyay
Hardik Upadhyay

Reputation: 2659

You can set custom validation or conditional validation in rails.

Refer below link

http://www.justinweiss.com/articles/a-lightweight-way-to-handle-different-validation-situations/

Hope it's help you.

Upvotes: 0

Related Questions