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\$
  • 2
    \$\begingroup\$ inn as an option of validates? \$\endgroup\$ – tokland Dec 27 '13 at 13:44
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, ...
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ It seems better, but maybe is it something better than that? \$\endgroup\$ – asiniy Jan 9 '14 at 5:34
  • \$\begingroup\$ It seems there isn't any better than that. Regards! \$\endgroup\$ – asiniy Jan 21 '14 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.

|improve this answer|||||
\$\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
|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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