snpd
snpd

Reputation: 29

validating attribute presence with condition

I am trying to introduce a functionality in my application in which the users can suggest an event to the organizers.To suggest an event the user will have to fill a form. I want to validate the presence of few fields(the attribute of the events) with a condition to be true, i.e. the fields should not be left blank if the user(the submitter of the form) is not an admin.However if the submitter of the form is an admin, the fields can be left blank.

validates :attribute_name, presence: { :if => :user.is_admin? }

undefined method `is_admin?' for :user:Symbol Did you mean? is_haml?

I have also tried :user.is_admin()==True , It also throws error: undefined method `is_admin' for :user:Symbol Did you mean? is_a?

I have this attribute in the users table:

t.boolean  "is_admin",               default: false

I have the following associations defined in my events model:

has_many :event_users, dependent: :destroy
  has_many :users, through: :event_users


  has_one :submitter_event_user, -> { where(event_role: 'submitter') }, class_name: 'EventUser'
  has_one  :submitter, through: :submitter_event_user, source: :user

In the controllers I have this code:

@event.submitter = current_user

Upvotes: 0

Views: 234

Answers (1)

engineersmnky
engineersmnky

Reputation: 29308

The issue is you are trying to call is_admin? on the Symbol :user as the error suggests.

If I understand correctly this attribute should be present unless user.is_admin? returns true

This can be done in multiple ways:

validates :attribute_name, presence: true, unless: -> {|u| u.is_admin?} 
#Or 
validates :attribute_name, presence: true, unless: :is_admin?
# or using presence directly as you tried to originally 
validates :attribute_name, presence: {unless: -> {|u| u.is_admin?} } 
# or 
validates :attribute_name, presence: {unless: :is_admin? } 

I generally prefer the first option as, IMO, it is the least ambiguous and the most readable but all of them should result in the same function so choose the one you prefer as long as you remain consistent.

In the block form the instance is yielded to the block and the block's return value is used to determine whether or not the validation should run.

When using the symbol the symbol is sent to the instance via the send message transmission e.g. self.send(:is_admin? and again the return value is used to determine if the validation should be applied

ActiveModel::Validations::ClassMethods#validates

Update based on revised question:

Since the Event is related to the User via submitter and this is already being set to the instance of a User you can validate in a very similar fashion via

validates :attribute_name, presence: true, 
    unless: ->(event) { event.submitter&.is_admin?} 

Or make a separate method such as

def admin_submitter? 
  self.submitter&.is_admin? 
end
validates :attribute_name, presence: {unless: :admin_submitter?} 

Upvotes: 4

Related Questions