tkit
tkit

Reputation: 8622

View model attribute helper on attribute itself

I have :meaning and :reading attributes on my view model. I want to run sanitize before_validation to clean user input before saving it to DB. Now, instead of typing something like this:

before_validation :sanitize_input

def sanitize_input
  self.meaning = ActionController::Base.helpers.sanitize(self.meaning)
  self.reading = ActionController::Base.helpers.sanitize(self.reading)
end

I wanted to make it a bit nicer. So I came up with an ActiveRecordExtension:

module ActiveRecordExtension
  extend ActiveSupport::Concern

  def sanitize_attribute(attribute)
    ActionController::Base.helpers.sanitize(attribute)
  end
end

ActiveRecord::Base.send(:include, ActiveRecordExtension)

Now I can call sanitize the input like this:

def sanitize_input
  self.meaning = sanitize_attribute(self.meaning)
  self.reading = sanitize_attribute(self.reading)
end

I would like to shorten this a bit by doing something like this (kind of like helper method on the attribute itself) in my view model:

def sanitize_input
  self.meaning.sanitize_attribute!
  self.reading.sanitize_attribute!
end

or

def sanitize_input
  sanitize_attribute!(self.meaning)
  sanitize_attribute!(self.reading)
end

But whatever I tried, I could not make this work (various combinations of using replace and bang (!) in my sanitize_attribute method.

Could it be shortened even further by using something like this:

def sanitize_attributes!(*args)
  args.each do |arg|
    arg.replace ActionController::Base.helpers.sanitize(arg)
  end
end

and calling it with something like:

sanitize_attributes!(self.meaning, self.reading)

The last one would be handy for cases when there are multiple attributes that need to be sanitized. Can it somehow be done in one of the ways I want it to be done?

Upvotes: 1

Views: 101

Answers (1)

firien
firien

Reputation: 1568

where are these inputs coming from that you have to manually sanitize them?

try this:

def sanitize_attributes!(*attrs)
  attrs.each do |attr|
    dirty = self.send attr
    #this should mark the attribute as changed, so it's included with partial updates
    self.send "#{attr}=".to_sym, ActionController::Base.helpers.sanitize(dirty)
    #or
    #self.write_attribute(attr, ActionController::Base.helpers.sanitize(dirty))
  end
end

sanitize_attributes!(:meaning, :reading)

Upvotes: 1

Related Questions