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

Unions sometimes fail unexpectedly when chained, and create side effects. #102

Open
sjjbirch opened this issue Apr 19, 2024 · 0 comments
Open

Comments

@sjjbirch
Copy link

Sometimes when preceding model scopes change in ways that seem like they shouldn't matter some of the methods in the gem begin to fail and produce odd side effects. Removing the chaining seems to make them work again, even if the same association that was calling in the method chain is just converted to an argument.

For example the below started happening when a change was made to the preceding scope (introducing strictest_dates scope to replace between_dates, both shown at the very bottom to reduce clutter), which suddenly made the union_except stop returning the correct new association and also has side effects on preceding associations chained with it

class Match < ApplicationRecord
#...
  scope :had_circle, -> (circle_phase) { left_joins(:circles).where('circles.phase = ?', circle_phase) }
  scope :missing_circle, -> (circle_phase) { union_except(all, had_circle(circle_phase)) } 
  scope :test_missing_circle, -> (existing_assoc, circle_phase) { union_except(existing_assoc, had_circle(circle_phase)) }
#...
end
irb(main):008> q1 = Match.strictest_dates(m_from, m_to, minor_version_start,minor_version_end)
=> [#<Match:0x00007cade8abe420
irb(main):009> q1.count
=> 4478
irb(main):010> q2 = Match.test_missing_circle(q1, missing_circle+1)
=> [#<Match:0x00007cade8a13f20
irb(main):011> [q1.count, q2.count]
=> [4478, 4478]
irb(main):017> q3 = q1.had_circle(7)
=> 
[#<Match:0x00007cae018cbcd0
irb(main):018> [q1.count, q2.count, q3.count]
=> [4478, 4478, 2638]
irb(main):019> q4 = q1.missing_circle(missing_circle+1)
=> [0, 4478, 0, 0]

The change triggered the unexpected behaviour was replacing between_dates in the calling function with strictest_dates shown below. I've had similar misbehaviour before with some other scopes using any_of but didn't investigate and just factored them out. All of the below is on PostgreSQL 14.11 (Ubuntu 14.11-0ubuntu0.22.04.1) and Rails 7.0.8:

class Match < ApplicationRecord
  scope :after_date, ->(start_date) { where(creation_time: start_date.end_of_day..) }
  scope :before_date, ->(end_date) { where(creation_time: ..end_date.beginning_of_day) }
  scope :between_dates, ->(start_date, end_date) { where(creation_time: start_date.end_of_day..end_date.beginning_of_day) }
  scope :inside_version, ->(version_number) { where(creation_time: convert_pc_version_to_exclusive_date_range(version_number) ) }
  scope :between_versions, ->(start_version, end_version) {
    where(creation_time: convert_pc_version_to_exclusive_date_range(start_version).first..convert_pc_version_to_exclusive_date_range(end_version).last )
  }
  scope :strictest_dates, ->(start_date, end_date, start_version=nil, end_version=nil) {
    if start_version && end_version
      matches = union_intersect(between_dates(start_date, end_date), between_versions(start_version, end_version))
    else
      matches = between_dates(start_date, end_date)
    end
    matches
  }
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

No branches or pull requests

1 participant