One way to mitigate spreading logic between SQL and Ruby is by using SQL views with something like Scenic [0] which can back an ActiveRecord model just like an ordinary table. This is especially nice for complex reporting because it centralizes your query logic in a single view as a sort of virtual table that can be queried from both ActiveRecord and normal Postgres queries.
[0] https://github.com/scenic-views/scenic