lib/lockbox/model.rb in lockbox-1.1.2 vs lib/lockbox/model.rb in lockbox-1.2.0

- old
+ new

@@ -17,14 +17,16 @@ # options[:type] = :string # when Integer # options[:type] = :integer # when Float # options[:type] = :float + # when BigDecimal + # options[:type] = :decimal # end custom_type = options[:type].respond_to?(:serialize) && options[:type].respond_to?(:deserialize) - valid_types = [nil, :string, :boolean, :date, :datetime, :time, :integer, :float, :binary, :json, :hash, :array, :inet] + valid_types = [nil, :string, :boolean, :date, :datetime, :time, :integer, :float, :decimal, :binary, :json, :hash, :array, :inet] raise ArgumentError, "Unknown type: #{options[:type]}" unless custom_type || valid_types.include?(options[:type]) activerecord = defined?(ActiveRecord::Base) && self < ActiveRecord::Base raise ArgumentError, "Type not supported yet with Mongoid" if options[:type] && !activerecord @@ -48,11 +50,11 @@ name = name.to_sym options[:attribute] = name.to_s options[:encrypted_attribute] = encrypted_attribute - options[:encode] = true unless options.key?(:encode) + options[:encode] = Lockbox.encode_attributes unless options.key?(:encode) encrypt_method_name = "generate_#{encrypted_attribute}" decrypt_method_name = "decrypt_#{encrypted_attribute}" class_eval do @@ -319,13 +321,19 @@ options[:type] end attribute name, attribute_type - serialize name, JSON if options[:type] == :json - serialize name, Hash if options[:type] == :hash - serialize name, Array if options[:type] == :array + if ActiveRecord::VERSION::STRING.to_f >= 7.1 + serialize name, coder: JSON if options[:type] == :json + serialize name, type: Hash if options[:type] == :hash + serialize name, type: Array if options[:type] == :array + else + serialize name, JSON if options[:type] == :json + serialize name, Hash if options[:type] == :hash + serialize name, Array if options[:type] == :array + end elsif !attributes_to_define_after_schema_loads.key?(name.to_s) # when migrating it's best to specify the type directly # however, we can try to use the original type if its already defined if attributes_to_define_after_schema_loads.key?(original_name.to_s) attribute name, attributes_to_define_after_schema_loads[original_name.to_s].first @@ -529,10 +537,23 @@ message = [message].pack("q>") when :float message = ActiveRecord::Type::Float.new.serialize(message) # double precision, big endian message = [message].pack("G") unless message.nil? + when :decimal + message = + if ActiveRecord::VERSION::MAJOR >= 6 + ActiveRecord::Type::Decimal.new.serialize(message) + else + # issue with serialize in Active Record < 6 + # https://github.com/rails/rails/commit/a741208f80dd33420a56486bd9ed2b0b9862234a + ActiveRecord::Type::Decimal.new.cast(message) + end + # Postgres stores 4 decimal digits in 2 bytes + # plus 3 to 8 bytes of overhead + # but use string for simplicity + message = message.to_s("F") unless message.nil? when :inet unless message.nil? ip = message.is_a?(IPAddr) ? message : (IPAddr.new(message) rescue nil) # same format as Postgres, with ipv4 padded to 16 bytes # family, netmask, ip @@ -577,9 +598,11 @@ message = ActiveRecord::Type::Time.new.deserialize(message) when :integer message = ActiveRecord::Type::Integer.new(limit: 8).deserialize(message.unpack1("q>")) when :float message = ActiveRecord::Type::Float.new.deserialize(message.unpack1("G")) + when :decimal + message = ActiveRecord::Type::Decimal.new.deserialize(message) when :string message.force_encoding(Encoding::UTF_8) when :binary # do nothing # decrypt returns binary string