Skip to content
This repository has been archived by the owner on Apr 17, 2018. It is now read-only.

Commit

Permalink
Inherit DB field type from superclass
Browse files Browse the repository at this point in the history
Problem: All custom DataMapper::Properties (e.g. in dm-types) have database field types based upon their Ruby primitives. Especially Properties inheriting from DataMapper::Property::Text like DataMapper::Property::JSON have some problems with that behavior (since they will result in VARCARs instead of LOBs).

This commit adds logic to try to find a database field type based upon the superclasses of the (custom) property. Only if no superclass has a direkt mapping from `property.class` to field type the fallback to the Ruby primitive (returned by `dump_as`) will take place.
  • Loading branch information
tillsc committed May 25, 2016
1 parent d19faa2 commit 4ac3158
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 5 deletions.
15 changes: 13 additions & 2 deletions lib/dm-migrations/adapters/dm-do-adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,9 @@ def create_unique_index_statements(model)
# @api private
def property_schema_hash(property)
dump_class = property.dump_class
type_map = self.class.type_map
type_by_property_class = self.class.type_by_property_class(property.class)

schema = (type_map[property.class] || type_map[dump_class]).merge(:name => property.field)
schema = (type_by_property_class || self.class.type_map[dump_class]).merge(:name => property.field)

schema_primitive = schema[:primitive]

Expand Down Expand Up @@ -293,6 +293,17 @@ def type_map
Property::Text => { :primitive => 'TEXT' },
}.freeze
end

# Finds a type for a given property.
#
# @return [Hash | nil] type matching the given property or one of the properties ancestors
#
# @api private
def type_by_property_class(property_class)
return nil unless property_class < DataMapper::Property

type_map[property_class] || type_by_property_class(property_class.superclass)
end
end
end

Expand Down
5 changes: 2 additions & 3 deletions lib/dm-migrations/sql/table_creator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,13 @@ def build_type(type_class)
if type_class.kind_of?(String)
schema[:primitive] = type_class
else
type_map = @adapter.class.type_map
primitive = type_class.respond_to?(:dump_as) ? type_class.dump_as : type_class
options = (type_map[type_class] || type_map[primitive])
options = @adapter.class.type_by_property_class(type_class) || @adapter.class.type_map[primitive]

schema.update(type_class.options) if type_class.respond_to?(:options)
schema.update(options)

schema.delete(:length) if type_class == DataMapper::Property::Text
schema.delete(:length) if type_class <= DataMapper::Property::Text
end

schema.update(@opts)
Expand Down
1 change: 1 addition & 0 deletions spec/unit/sql/table_creator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@

@adapter.stub!(:quote_column_name).and_return(%{'id'})
@adapter.class.stub!(:type_map).and_return(Integer => {:type => 'int'})
@adapter.class.stub!(:type_by_property_class).and_return(Integer => {:type => 'int'})
@adapter.stub!(:property_schema_statement).and_return("SOME SQL")
@adapter.stub!(:with_connection).and_yield(connection)
@c = SQL::TableCreator::Column.new(@adapter, 'id', Integer, :serial => true)
Expand Down

0 comments on commit 4ac3158

Please sign in to comment.