Skip to content

Instantly share code, notes, and snippets.

@haslo
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haslo/c1cb3e549c2a3a8ee576 to your computer and use it in GitHub Desktop.
Save haslo/c1cb3e549c2a3a8ee576 to your computer and use it in GitHub Desktop.
Getters and Setters for JSON Data Fields for ActiveRecord Models
module Concerns
module ModelWithJSONData
extend ActiveSupport::Concern
module ClassMethods
def json_data_field_descriptions
[]
end
end
def method_missing(method, *args, &block)
self.class.json_data_field_descriptions.each do |field_description|
if field_description[:name].to_s == method.to_s
self.class.__send__(:define_method, field_description[:name].to_sym) do
self.json_data ||= {}
self.json_data[field_description[:name].to_s]
end
return __send__(field_description[:name])
end
if "#{field_description[:name]}=" == method.to_s
self.class.__send__(:define_method, "#{field_description[:name]}=".to_sym) do |value|
self.json_data ||= {}
self.json_data[field_description[:name].to_s] = __send__(field_description[:data_type].name, value)
end
return __send__("#{field_description[:name]}=", args[0])
end
end
super
end
end
end
@kreba
Copy link

kreba commented Oct 24, 2014

Hmm, macht das etwas, das mit

class Foo < ActiveRecord::Base
  serialize :first_field, JSON
  serialize :second_field, JSON
end

nicht abgedeckt wäre? Oder sehe ich hier etwas nicht?

@haslo
Copy link
Author

haslo commented Oct 26, 2014

Haben das ja schon besprochen, es macht was ganz anderes 😁 Habe das Gist jetzt noch aktualisiert, die JSON-abstrahierten Datenfelder sind jetzt typisiert und validierbar.

https://github.com/haslo/tournament_tool/blob/master/spec/support/model_with_json_examples.rb

      context 'data types' do
        it 'does allow assignment of Strings to String fields' do
          subject.class.json_data_field_descriptions.each do |field_description|
            if field_description[:data_type] == String
              expect(subject.send("#{field_description[:name]}=", 'string')).to eq('string')
              expect(subject.send(field_description[:name])).to eq('string')
            end
          end
        end
        it 'does not allow assignment of non-Integers to Integer fields' do
          subject.class.json_data_field_descriptions.each do |field_description|
            if field_description[:data_type] == Integer
              expect{subject.send("#{field_description[:name]}=", {invalid: 'string'})}.to raise_error(TypeError)
            end
          end
        end
        it 'does not allow assignment of non-Hashes to Hash fields' do
          subject.class.json_data_field_descriptions.each do |field_description|
            if field_description[:data_type] == Hash
              expect{subject.send("#{field_description[:name]}=", 'not a hash')}.to raise_error(TypeError)
            end
          end
        end
        it 'does allow assignment of Strings to Array fields with implicit conversion' do
          subject.class.json_data_field_descriptions.each do |field_description|
            if field_description[:data_type] == Array
              expect(subject.send("#{field_description[:name]}=", 'string')).to eq(['string'])
              expect(subject.send(field_description[:name])).to eq(['string'])
            end
          end
        end
      end

https://github.com/haslo/tournament_tool/blob/master/spec/models/concerns/model_with_json_data_spec.rb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment