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\$ 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\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.