1
\$\begingroup\$

Rails AR. validate one field, with 4 validators & 2 condition block

validates :inn,
          presence: { if: -> { user.is_a?(Client) } },
          inn: { if: -> { user.is_a?(Client) } },
          uniqueness: { if: -> { user.is_a?(Client) } },
          absence: { if: -> { user.is_a?(Department) } }

Could I have some tips on refactoring this?

\$\endgroup\$
1
  • 2
    \$\begingroup\$ inn as an option of validates? \$\endgroup\$
    – tokland
    Commented Dec 27, 2013 at 13:44

3 Answers 3

1
\$\begingroup\$

You can try something like this (obviously names can be shorter):

if_user_is_a = ->(klass) { { if: -> { user.is_a?(klass) } } }
validates :inn, presence: if_user_is_a[Client], ..., absence: if_user_is_a[Department]

or

if_user_is_a = ->(klass) { { if: -> { user.is_a?(klass) } } }
if_user_is_a_client = if_user_is_a[Client]
...
validates :inn, presence: if_user_is_a_client, ...
\$\endgroup\$
2
  • \$\begingroup\$ It seems better, but maybe is it something better than that? \$\endgroup\$ Commented Jan 9, 2014 at 5:34
  • \$\begingroup\$ It seems there isn't any better than that. Regards! \$\endgroup\$ Commented Jan 21, 2014 at 23:49
1
\$\begingroup\$

Why don't you split both conditions into 2 diffrent validations? I think it's cleaner and easier to read (ie more maintenable).

validates :inn, presence: true, uniqueness: true, if: :user_is_client #no idea about that `inn` option on your example
validates :inn, absence: true, if: :user_is_department

def user_is_client
  user.is_a?(Client)
end

def user_is_department
  user-is_a?(Department)
end

Personally, I prefer to be more verbose some times. Also, I think this way conditions are checked only once each, the other way each condition is checked for each validation since rails has to evaluate all blocks.

\$\endgroup\$
0
\$\begingroup\$

You can try to use a method instead of repeat yourself 4 times

Something like:

validates :inn,
          presence: { inn_meth { Client } },
          inn: { inn_meth { Client } },
          uniqueness: { inn_meth { Client} },
          absence: { inn_meth{ Department } }

def inn_meth
    if: -> { user.is_a?(yield) }
end
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.