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, this method checks 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, it's 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? If so, how would I implement it?