Skip to content

Instantly share code, notes, and snippets.

@onemanstartup
Created January 11, 2015 06:42
Show Gist options
  • Save onemanstartup/2df9aa2d7d037256cd23 to your computer and use it in GitHub Desktop.
Save onemanstartup/2df9aa2d7d037256cd23 to your computer and use it in GitHub Desktop.

Revisions

  1. onemanstartup created this gist Jan 11, 2015.
    44 changes: 44 additions & 0 deletions json_accessor.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,44 @@
    # You don't actually need this.
    # I wrote this, but rails support this
    # Use store_accessor :data, :admin

    module JsonAccessor
    extend ActiveSupport::Concern

    module ClassMethods
    def json_accessor(json_attribute, *fields)
    send(:store, json_attribute, accessors: fields)

    field_methods = Module.new
    fields.each do |any_key|
    key = any_key.to_s.freeze

    field_methods.send(:define_method, "#{key}_changed?") do
    send("#{key}_change").present?
    end

    field_methods.send(:define_method, "#{key}_will_change!") do
    send("#{json_attribute}_will_change!")
    end

    field_methods.send(:define_method, "#{key}_was") do
    (send(:attribute_was, json_attribute) || {})[key]
    end

    field_methods.send(:define_method, "#{key}_change") do
    json_changes = send("#{json_attribute}_change")
    return if json_changes.nil?
    attribute_changes = json_changes.map { |change| change.try(:[], key.to_s) }
    attribute_changes.compact.present? ? attribute_changes : nil
    end

    field_methods.send(:define_method, "restore_#{key}!") do
    old_json = send("#{json_attribute}_change").try(:first) || {}
    send("#{key}=", old_json[key.to_s])
    end

    include field_methods
    end
    end
    end
    end