Home > OS >  DRY way of assigning new object's values from an existing object's values
DRY way of assigning new object's values from an existing object's values

Time:11-18

I created a class method that is called when a new object is created and copied from an old existing object. However, I only want to copy some of the values. Is there some sort of Ruby shorthand I can use to clean this up? It's not entirely necessary, just curious to know if something like this exists?

Here is the method I want to DRY up:

def set_message_settings_from_existing existing
  self.can_message = existing.can_message
  self.current_format = existing.current_format
  self.send_initial_message = existing.send_initial_message
  self.send_alert = existing.send_alert
  self.location = existing.location
end

Obviously this works perfectly fine, but to me looks a little ugly. Is there any way to clean this up? If I wanted to copy over every value that would be easy enough, but because I only want to copy these 5 (out of 20 something) values, I decided to do it this way.

CodePudding user response:

def set_message_settings_from_existing(existing)
  [:can_message, :current_format, :send_initial_message, :send_alert, :location].each do |attribute|
    self.send("#{attribute}=", existing.send(attribute))
  end
end

Or

def set_message_settings_from_existing(existing)
  self.attributes = existing.attributes.slice('can_message', 'current_format', 'send_initial_message', 'send_alert', 'location')
end

CodePudding user response:

a hash might be cleaner:

def set_message_settings_from_existing existing
  fields = {
    can_message: existing.can_message,
    current_format: existing.current_format,
    send_initial_message: existing.send_initial_message,
    send_alert: existing.send_alert,
    location: existing.location
  }
  self.attributes = fields
end

you can take this further by only selecting the attributes you want:

def set_message_settings_from_existing existing
  fields = existing.attributes.slice(
    :can_message, 
    :current_format, 
    :send_initial_message, 
    :send_alert,
    :location
  )
  self.attributes = fields
end

at this point you could also have these fields defined somewhere, eg:

SUB_SET_OF_FIELDS = [:can_message, :current_format, :send_initial_message, :send_alert, :location]

and use that for your filter instance.attributes.slice(SUB_SET_OF_FIELDS)

  • Related