Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 4, 2025

Problem

After upgrading from Ransack 4.3.0 to 4.4.0, custom predicate formatters with type: :date started receiving String values instead of properly casted Date/Time objects. This caused errors when trying to call date methods like .end_of_day:

Ransack.configure do |config|
  config.add_predicate 'lteq_eod',
                       arel_predicate: 'lteq',
                       formatter: proc { |value| value.end_of_day },  # Error: undefined method `end_of_day' for String
                       type: :date
end

Root Cause

The Value#cast method uses a Ruby case statement to match type values against symbols:

case type
when :date
  cast_to_date(value)
when :datetime, :timestamp, :time, :timestamptz
  cast_to_time(value)
else
  cast_to_string(value)  # String types fall through here!
end

When type is a String ("date") instead of a Symbol (:date), it doesn't match any of the when clauses and falls through to the else branch, which returns the original string value instead of a Date object.

Solution

Added defensive type conversion at the beginning of the Value#cast method to handle both string and symbol types:

def cast(type)
  # Convert type to symbol if it's a string to ensure proper case matching
  type = type.to_sym if type.is_a?(String)
  
  case type
  when :date
    cast_to_date(value)
  ...
  end
end

This ensures that string types like "date", "datetime", etc. are automatically converted to symbols before case matching, allowing them to be cast correctly.

Changes

  • lib/ransack/nodes/value.rb: Added 3 lines to convert string types to symbols
  • spec/ransack/nodes/value_spec.rb: Added test verifying string type 'date' works correctly
  • spec/ransack/predicate_spec.rb: Added comprehensive test for custom predicates with date formatters

Impact

  • ✅ Minimal change: only 3 lines of production code
  • ✅ Surgical fix: no changes to existing behavior for symbol types
  • ✅ Backward compatible: handles both string and symbol types
  • ✅ Well tested: comprehensive test coverage added

Example Usage

After this fix, the following code works correctly:

Ransack.configure do |config|
  config.add_predicate 'lteq_eod',
                       arel_predicate: 'lteq',
                       formatter: proc { |value| value.end_of_day },  # value is now a Date
                       type: :date
end

# Usage in a search
@search = Person.ransack(life_start_lteq_eod: '2022-05-23')

The formatter now correctly receives a Date object and can call .end_of_day without errors.

Fixes #XXXX

Original prompt

This section details on the original issue you should resolve

<issue_title>Date predicate is formatted as string</issue_title>
<issue_description>Hello,

in previous versions, block in this code use to receive a time object:

Ransack.configure do |config|
  config.add_predicate 'lteq_eod',
                       arel_predicate: 'lteq',
                       formatter: proc { |value| value.end_of_day },
                       type: :date
end

After upgrading from 4.3.0 to 4.4.0, the proc block started receiving an string.</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #1649

💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

@Copilot Copilot AI changed the title [WIP] Date predicate is formatted as string Fix date predicate formatter receiving String instead of Date object Oct 4, 2025
@Copilot Copilot AI requested a review from scarroll32 October 4, 2025 22:07
Copilot finished work on behalf of scarroll32 October 4, 2025 22:07
@scarroll32 scarroll32 marked this pull request as ready for review October 4, 2025 22:09
@scarroll32
Copy link
Member

@dcrec1 are you able to review this PR? #1649 (comment)

@scarroll32 scarroll32 removed their request for review October 6, 2025 17:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Date predicate is formatted as string

2 participants