Ben Smith
Ben Smith

Reputation: 819

Ruby on Rails: How to validate if on specific page?

In my Ruby on Rails application I am trying to add in validations that will ensure the user has entered a value in a text box. In my system I have a table called Account which stores users' email account information, when they go onto the views/accounts/_form.html.erb page to add a new email account I want to validate the presence of a port number. I can do this through the following code:

validates :port, presence: true

This successfully ensures that users enter their port number, but when a user signs up through the views/users/_new.html.erb page they have to enter only an email address (e.g [email protected]) and the users_controller will then create a record in the Account table for this email address. My problem is that on the views/accounts/_form.html.erb page the port number is required but on the views/users/_new.html.erb it is not.

Is there a way of validating that the user enters the port number if they are on the views/accounts/_form.html.erb page or invoking the create method in the accounts_controller?

I am aware that I could do this through the HTML required validation like so: <%= f.text_field :port, :required => true %> but I need to add in further validation as well as presence, so this is not suitable.

Upvotes: 0

Views: 1278

Answers (3)

alba hoo
alba hoo

Reputation: 164

I would not recommend you have model aware of views. In @SteveTurczyn 's solution, an abstract field is introduced into model to identified the which page it come from, which is an good solution.

As from Ruby on Rail MVC, both View and Model talk to the controller, another solution will be have controller handle validation of params before passing the value to create account.

Upvotes: 0

bbozo
bbozo

Reputation: 7301

Extract that part of the logic into a form object, check out the legendary 2012 blog entry from CodeClimate. Things have changed since then, the author uses Virtus to build form objects, more popular & up-to-date gems these days are:

if it's a one-off thing, just do what Steve said in the other answer but that is a sure way to hell, safe-hate and divorce (at least from personal experience) in any slightly teeny weeny bigger project (i.e. you mean to spend some hours more working on it, it's not like you just finished everything and want to go home).

Actually, just use form classes everywhere and avoid model validations & other callbacks at all. You don't want things sending account activation mails or validating your password complexity when you're writing tests and just need a "post" that belongs to "user".

My own favorite personal fuckup due to model callbacks is sending 240.000 "your account has been upgraded/downgraded" emails because of an innocent spelling change update in an account_type attribute migration just because account_type_changed? was true.

So.. Form classes for ever, model callbacks never.

Upvotes: 1

SteveTurczyn
SteveTurczyn

Reputation: 36860

You can create an attr_accessor field that determines if the validation should occur...

class Account < ActiveRecord:Base
  attr_accessor :port_needs_validation
  validates :port, presence: true, if: -> {port_needs_validation} 

Then just set the accessor in your create method...

def create
  @account = Account.new
  @account.assign_attributes(account_params)
  @account.port_needs_validation = true
  if @account.save
    ...

Upvotes: 7

Related Questions