mardi 4 août 2015

Rails - DRY similar methods? [migrated]

In order to reduce redundancy in my app, I have added the method self.find_or_keep(object) to many of my models in order to find existing records with the same values, so I can reference the already existing ones instead of creating new records. Basically, what the method does is checking most attributes for equality between two objects; id, created_at and updated_at are always excluded for obvious reasons.

class IPv4 < ActiveRecord::Base
  # returns its param or an already existing record
  def self.find_or_keep(ipv4)
    # create new object in memory, if param is a Hash
    ipv4 = IPv4.new(ipv4) if ipv4.is_a?(Hash)
    return (entry = IPv4.find_by(address: ipv4.address, subnetmask: ipv4.subnetmask)) ? entry : ipv4
  end
end

class Service < ActiveRecord::Base
  # returns its param or an already existing record
  def self.find_or_keep(service)
    # create new object in memory, if param is a Hash
    service = Service.new(service) if service.is_a?(Hash)
    return (entry = Service.find_by(protocol: service.protocol, port_from: service.port_from, port_to: service.port_to)) ? entry : service
  end
end

As you can see, not very DRY. The problem here is, that the method each time has to check for different parameters, so I have to rewrite the find_by every time I want to use the method in another class. What I have in mind for DRYing it up is something like this:

class IPv4 < ActiveRecord::Base
  implement_find_or_keep_with(:address, :subnetmask)
end

class Service < ActiveRecord::Base
  implement_find_or_keep_with(:protocol, :port_from, :port_to)
end

class ActiveRecord::Base
  # whatever is need
end

Is something like this possible and if so, how would I implement it?

Aucun commentaire:

Enregistrer un commentaire