diff --git a/lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb b/lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb index 8db09cd..001cd89 100644 --- a/lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb +++ b/lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb @@ -46,7 +46,7 @@ def type_cast_with_extended_types(value) when :inet, :cidr then klass.string_to_cidr_address(value) when :numrange,:int4range,:int8range then klass.string_to_numeric_range(value,type) when :daterange then klass.string_to_date_range(value) - when :tsrange then klass.string_to_datetime_range(value) + when :tsrange,:tstzrange then klass.string_to_datetime_range(value) else type_cast_without_extended_types(value) end @@ -87,7 +87,7 @@ def type_cast_code_with_extended_types(var_name) when :inet, :cidr then "#{klass}.string_to_cidr_address(#{var_name})" when :numrange,:int4range,:int8range then "#{klass}.string_to_numeric_range(#{var_name},#{type.inspect})" when :daterange then "#{klass}.string_to_date_range(#{var_name})" - when :tsrange then "#{klass}.string_to_datetime_range(#{var_name})" + when :tsrange,:tstzrange then "#{klass}.string_to_datetime_range(#{var_name})" else type_cast_code_without_extended_types(var_name) end @@ -98,7 +98,7 @@ def type_cast_code_with_extended_types(var_name) if RUBY_PLATFORM =~ /java/ def default_value_with_extended_types(default) case default - when /\A'(.*)'::(?:(num|int[48]|date|ts)range)\z/ + when /\A'(.*)'::(?:(num|int[48]|date|ts(tz)?)range)\z/ $1 else default_value_without_extended_types(default) @@ -112,7 +112,7 @@ class << self unless RUBY_PLATFORM =~ /java/ def extract_value_from_default_with_extended_types(default) case default - when /\A'(.*)'::(?:(num|int[48]|date|ts)range)\z/ + when /\A'(.*)'::(?:(num|int[48]|date|ts(tz)?)range)\z/ $1 else extract_value_from_default_without_extended_types(default) @@ -378,7 +378,9 @@ def type_cast_extended(value, column, part_array = false) type_cast_without_extended_types(value, column) end when Date, DateTime, Time - if [:tsrange].include?(column.type) + if column.type == :tstzrange + quoted_date(value) + elsif column.type == :tsrange value.to_s(:db) else type_cast_without_extended_types(value, column) diff --git a/spec/dummy/config/application.rb b/spec/dummy/config/application.rb index 9d3060d..d1087f7 100644 --- a/spec/dummy/config/application.rb +++ b/spec/dummy/config/application.rb @@ -27,7 +27,7 @@ class Application < Rails::Application # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - # config.time_zone = 'Central Time (US & Canada)' + config.time_zone = 'Eastern Time (US & Canada)' # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] diff --git a/spec/models/ranges/tstzrange_spec.rb b/spec/models/ranges/tstzrange_spec.rb new file mode 100644 index 0000000..3cf2bff --- /dev/null +++ b/spec/models/ranges/tstzrange_spec.rb @@ -0,0 +1,89 @@ +require 'spec_helper' + +describe 'Models with tstzrange columns' do + let!(:adapter) { ActiveRecord::Base.connection } + + context 'no default value, range' do + before do + adapter.create_table :tstz_rangers, :force => true do |t| + t.tstzrange :best_estimate + end + class TstzRanger < ActiveRecord::Base + attr_accessible :best_estimate + end + end + + after do + adapter.drop_table :tstz_rangers + Object.send(:remove_const, :TstzRanger) + end + + describe '#create' do + it 'creates an record when there is no assignment' do + range = TstzRanger.create() + range.reload + range.best_estimate.should eq nil + end + + it 'creates an record with a range' do + ts_range = Time.new(2011, 01, 01, 12, 34)..Time.new(2012, 01, 31, 8, 0, 1) + range = TstzRanger.create( :best_estimate => ts_range) + range.reload + range.best_estimate.should eq ts_range + end + end + + describe 'range assignment' do + it 'updates an record with an range string' do + ts_range = Time.new(2011, 01, 01, 12, 34)..Time.new(2012, 01, 31, 8, 0, 1) + new_ts_range = Time.new(2012, 01, 01, 11, 0, 0)..Time.new(2012, 02, 01, 13, 0, 0) + range = TstzRanger.create( :best_estimate => ts_range) + range.best_estimate = new_ts_range + range.save + + range.reload + range.best_estimate.should eq new_ts_range + end + + it 'converdate empty strings to nil' do + range = TstzRanger.create + range.best_estimate = '' + range.save + + range.reload + range.best_estimate.should eq nil + end + end + end + + context 'default value, ts range' do + before do + adapter.create_table :tstz_default_rangers, :force => true do |t| + t.tstzrange :best_estimate, :default => Time.new(2011, 01, 01, 12, 34, 0, '-07:00')..Time.new(2011, 01, 31, 1, 0, 0, '-07:00') + end + class TstzDefaultRanger < ActiveRecord::Base + attr_accessible :best_estimate + end + end + + after do + adapter.drop_table :tstz_default_rangers + Object.send(:remove_const, :TstzDefaultRanger) + end + + describe '#create' do + it 'creates an record when there is no assignment' do + range = TstzDefaultRanger.create() + range.reload + range.best_estimate.should eq Time.new(2011, 01, 01, 12, 34,0, '-07:00')..Time.new(2011, 01, 31, 1, 0, 0, '-07:00') + end + + it 'creates an record with a range' do + new_ts_range = Time.new(2012, 01, 01, 9, 0, 0, '-05:00')..Time.new(2012, 12, 31, 9, 0, 0, '-05:00') + range = TstzDefaultRanger.create(:best_estimate => new_ts_range) + range.reload + range.best_estimate.should eq new_ts_range + end + end + end +end