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?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Dec 26, 2013 at 12:35
\$\endgroup\$
1
  • 2
    \$\begingroup\$ inn as an option of validates? \$\endgroup\$ 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, ...
answered Jan 1, 2014 at 3:47
\$\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.

answered May 9, 2019 at 2:58
\$\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
answered Feb 13, 2015 at 0:13
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.