简体   繁体   中英

Capitalizing more than one attribute in a Rails before_save method

I'd like to capitalize the first_name and last_name of my model instances using the before_save method. Of course I could do this:

before_save do 
  self.first_name = first_name.capitalize
  self.last_name = last_name.capitalize
end

But I'd much rather alter the two attributes in one fell swoop. Is there a way to select certain columns in my model and apply the desired method to them?

You could do something like this

before_save :capitalize_attributes

private
   def capitalize_attributes
     capitalizable = ["first_name","last_name"]
     self.attributes.each do |attr,val|
       #based on comment either of these will work
       #if you want to store nil in the DB then
       self.send("#{attr}=",val.strip.capitalize) if capitalizable.include?(attr) && !val.nil?
       #if you want to store a blank string in the DB then 
        self.send("#{attr}=",val.to_s.strip.capitalize) if capitalizable.include?(attr)
     end
   end

Then you can just add the attributes you want capitalized to the capitalizable array. I use a similar code to upcase all Strings in certain models just to keep data clean an consistent.

This is just an another version of @engieeringmnky's answer:

before_save :capitalize_attributes

private
   def capitalize_attributes
     self.attributes.select{ |a| ["first_name","last_name"].include? a }.each do |attr, val|
       self.send("#{attr}=", val.try(:strip).try(:capitalize))
     end
   end

Building on @engineersmnky's answer further for Rails 4+ with Concerns (more here ):

app/models/concerns/model_hooks.rb

module ModelHooks
  extend ActiveSupport::Concern

  included do
    before_save :capitalize_attributes
  end

  def capitalize_attributes
     self.attributes.each do |attr,val|
       # if the attribute only has spaces, then this will store nil in the DB
       self.send("#{attr}=",val.strip.capitalize) if self.capitalizable_attrs.include?(attr) && !val.nil?
     end    
  end
end

then in your models:

class Trail < ApplicationRecord
  include ModelHooks

  def capitalizable_attrs
    ["name"] # return an array of attributes you want to capitalize
  end

end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM