can_lookup.rb 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. module ApplicationModel::CanLookup
  3. extend ActiveSupport::Concern
  4. class_methods do
  5. =begin
  6. lookup model from cache (if exists) or retrieve it from db, id, name, login or email possible
  7. result = Model.lookup(id: 123)
  8. result = Model.lookup(name: 'some name')
  9. result = Model.lookup(login: 'some login')
  10. result = Model.lookup(email: 'some login')
  11. returns
  12. result = model # with all attributes
  13. =end
  14. def lookup(**attr)
  15. raise ArgumentError, "Multiple lookup attributes given (#{attr.keys.join(', ')}), only support (#{lookup_keys.join(', ')})" if attr.many?
  16. attr.transform_keys!(&:to_sym).slice!(*lookup_keys)
  17. raise ArgumentError, "Valid lookup attribute required (#{lookup_keys.join(', ')})" if attr.empty?
  18. cache_get(attr.values.first) || find_and_save_to_cache_by(attr)
  19. end
  20. =begin
  21. return possible lookup keys for model
  22. result = Model.lookup_keys
  23. returns
  24. [:id, :name] # or, for users: [:id, :login, :email]
  25. =end
  26. def lookup_keys
  27. @lookup_keys ||= %i[id name login email number] & attribute_names.map(&:to_sym)
  28. end
  29. private
  30. def find_and_save_to_cache_by(attr)
  31. record = find_by(attr)
  32. return nil if string_key?(attr.keys.first) && (record&.send(attr.keys.first) != attr.values.first.to_s) # enforce case-sensitivity on MySQL
  33. return record if ActiveRecord::Base.connection.transaction_open? # rollbacks can invalidate cache entries
  34. cache_set(attr.values.first, record)
  35. record
  36. end
  37. def string_key?(key)
  38. type_for_attribute(key.to_s).type == :string
  39. end
  40. end
  41. end