Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport #25364 to 4-2-stable #25565

Merged
merged 1 commit into from Jun 29, 2016

Conversation

kamipo
Copy link
Member

@kamipo kamipo commented Jun 29, 2016

This PR is backport #25364 to 4-2-stable.

Currently Type::Date#serialize does not cast a value to a date object.
It should be cast to a date object for finding by date column correctly
working.

Fixes #25354.

r? @rafaelfranca

@rails-bot
Copy link

warning Warning warning

  • Pull requests are usually filed against the master branch for this repo, but this one is against 4-2-stable. Please double check that you specified the right target!

@rafaelfranca
Copy link
Member

Tests are failing with sqlite3, but I don't think it is related to this. I'll investigate.

@rafaelfranca
Copy link
Member

Yes, seems it is related.

@kamipo
Copy link
Member Author

kamipo commented Jun 29, 2016

Failing test was removed at 19537ec on master.
Can we remove the test on 4-2-stable?

@rafaelfranca
Copy link
Member

Weird. But they are passing in 4-2-stable. Why they are broken in your branch?

@kamipo kamipo force-pushed the fix_serialize_for_date_type branch from c7a15e7 to 8b49662 Compare June 29, 2016 03:37
assert_equal '10.1', @conn.type_cast('10.1', c)

c = Column.new(nil, 1, Type::Date.new)
assert_equal '10.1', @conn.type_cast('10.1', c)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this assert is unexpected behavior, I think.
Previously type casting against Type::Date was not worked.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, now I understand it. So those tests still make sense because the column information is still being used differently from 5.0, but this assertion needs to be changed or removed

Currently `Type::Date#serialize` does not cast a value to a date object.
It should be cast to a date object for finding by date column correctly
working.

Fixes rails#25354.
@kamipo kamipo force-pushed the fix_serialize_for_date_type branch from 8b49662 to 226e1a3 Compare June 29, 2016 04:16
@@ -71,7 +71,7 @@ def test_type_cast_string
assert_equal '10.1', @conn.type_cast('10.1', c)

c = Column.new(nil, 1, Type::Date.new)
assert_equal '10.1', @conn.type_cast('10.1', c)
assert_equal '2016-05-11', @conn.type_cast('2016-05-11 19:00:00', c)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this assertion to expected behavior!

@@ -9,6 +9,10 @@ def klass
::Date
end

def type_cast_for_database(value)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kamipo I'm not sure this is sufficient to fix the underlying problem. I tried this same solution last night (as module included onto ActiveRecord::Type::Date to monkey patch it), and I am seeing this method called in some cases, such as when persisting records; however, when calling where on the model, it is still coercing to a UTC date time string. Here is an example (rspec) test:

describe 'querying dates with times works around day boundaries' do
    let(:model_class) do
      model_class = Class.new(ActiveRecord::Base)
      model_class.table_name = 'date_serialization_test'
      model_class
    end

    let!(:old_record)       { model_class.create!(a_date_field: Date.new(2016, 6, 8)) }
    let!(:boundary_record)  { model_class.create!(a_date_field: Date.new(2016, 6, 9)) }
    let!(:newer_record)     { model_class.create!(a_date_field: Date.new(2016, 6, 10)) }

    before(:context) do
      ActiveRecord::Migration.new.create_table(:date_serialization_test) do |t|
        t.date :a_date_field
      end
    end

    after(:context) do
      ActiveRecord::Migration.new.drop_table(:date_serialization_test)
    end

    it 'coerces TimeWithZone to Date in current locale' do
      date = Time.new(2016, 6, 9, 23, 0, 0, '-05:00').in_time_zone
      byebug
      query = model_class.where('a_date_field >= ?', date)

      expect(query).to include boundary_record, newer_record
      expect(query).not_to include old_record
    end

    it 'coerces Time to Date in current locale' do
      date = Time.new(2016, 6, 9, 23, 0, 0, '-05:00')
      query = model_class.where('a_date_field >= ?', date)

      expect(query).to include boundary_record, newer_record
      expect(query).not_to include old_record
    end

    it 'coerces DateTime to Date in current locale' do
      date = DateTime.new(2016, 6, 9, 23, 0, 0, '-5')
      query = model_class.where('a_date_field >= ?', date)
      binding.pry
      expect(query).to include boundary_record, newer_record
      expect(query).not_to include old_record
    end

    it 'queries still work correctly using a Date object' do
      date = Date.new(2016, 6, 9)
      query = model_class.where('a_date_field >= ?', date)

      expect(query).to include boundary_record, newer_record
      expect(query).not_to include old_record
    end
  end

I suspect that because the where clause uses an SQL string, it may not be able to determine the column type? I am finding that my issue may not be quite the same as the case this and the relate rails 5 PR solves.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect that because the where clause uses an SQL string, it may not be able to determine the column type?

Right, AR cannot determine the column type if using where with an SQL string for now.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, after further investigation I determined we need to just type cast the values ourselves. Thanks @kamipo

@rafaelfranca rafaelfranca merged commit 0a45950 into rails:4-2-stable Jun 29, 2016
@kamipo kamipo deleted the fix_serialize_for_date_type branch June 29, 2016 19:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants