json_serialized_field.rb 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. require 'json_with_indifferent_access'
  2. module JsonSerializedField
  3. extend ActiveSupport::Concern
  4. module ClassMethods
  5. def json_serialize(*fields)
  6. fields.each do |field|
  7. class_eval <<-CODE
  8. serialize :#{field}, JsonWithIndifferentAccess
  9. validate :#{field}_has_no_errors
  10. def #{field}=(input)
  11. @#{field}_assignment_error = false
  12. case input
  13. when String
  14. if input.strip.length == 0
  15. self[:#{field}] = ActiveSupport::HashWithIndifferentAccess.new
  16. else
  17. json = JSON.parse(input) rescue nil
  18. if json
  19. self[:#{field}] = ActiveSupport::HashWithIndifferentAccess.new(json)
  20. else
  21. @#{field}_assignment_error = "was assigned invalid JSON"
  22. end
  23. end
  24. when Hash
  25. self[:#{field}] = ActiveSupport::HashWithIndifferentAccess.new(input)
  26. else
  27. @#{field}_assignment_error = "cannot be set to an instance of \#{input.class}"
  28. end
  29. end
  30. def #{field}_has_no_errors
  31. errors.add(:#{field}, @#{field}_assignment_error) if @#{field}_assignment_error
  32. end
  33. CODE
  34. end
  35. end
  36. end
  37. end