[Unreleased]
π Fixes
- π§ Fix literal strings containing parentheses breaking CTE-parsing.
0.6.0
Releasedate: 2-1-2026
Rubygems: https://rubygems.org/gems/appquery/versions/0.6.0
β¨ Features
- ποΈ
AppQuery::BaseQueryβ structured query objects with explicit parameter declaration ```ruby class ArticlesQuery < AppQuery::BaseQuery bind :author_id bind :status, default: nil var :order_by, default: "created_at DESC" cast published_at: :datetime end
ArticlesQuery.new(author_id: 1).entries ArticlesQuery.new(author_id: 1, status: "draft").first
Benefits over `AppQuery[:my_query]`:
- Explicit `bind` and `var` declarations with defaults
- Unknown parameter validation (catches typos)
- Self-documenting: `ArticlesQuery.binds`, `ArticlesQuery.vars`
- Middleware support via concerns
- π **`AppQuery::Paginatable`** β pagination middleware (Kaminari-compatible)
```ruby
class ApplicationQuery < AppQuery::BaseQuery
include AppQuery::Paginatable
per_page 25
end
# With count (full pagination)
articles = ArticlesQuery.new.paginate(page: 1).entries
articles.total_pages # => 5
# Without count (large datasets, uses limit+1 trick)
articles = ArticlesQuery.new.paginate(page: 1, without_count: true).entries
articles.next_page # => 2 or nil
πΊοΈ
AppQuery::Mappableβ map results to Ruby objectsclass ArticlesQuery < ApplicationQuery include AppQuery::Mappable class Item < Data.define(:title, :url, :published_on) end end
articles = ArticlesQuery.new.entries articles.first.title # => "Hello World" articles.first.class # => ArticlesQuery::Item
# Skip mapping ArticlesQuery.new.raw.entries.first # => => "Hello", ...
- π **`Result#transform!`** β transform result records in-place
```ruby
result = AppQuery[:users].select_all
result.transform! { |row| row.merge("full_name" => "#{row['first']} #{row['last']}") }
- Add
any?,none?- efficient ways to see if there's any results for a query. - π― Cast type shorthands β use symbols instead of explicit type classes
ruby query.select_all(cast: {"published_on" => :date}) # instead of query.select_all(cast: {"published_on" => ActiveRecord::Type::Date.new})Supports all ActiveRecord types including adapter-specific ones (:uuid,:jsonb, etc.). - π Indifferent access β for rows and cast keys ```ruby row = query.select_one row["name"] # works row[:name] # also works
# cast keys can be symbols too query.select_all(cast: :date)
## [0.5.0] - 2025-12-21
### π₯ Breaking Changes
- π **`select:` keyword argument removed** β use positional argument instead
```ruby
# before
query.select_all(select: "SELECT * FROM :_")
# after
query.select_all("SELECT * FROM :_")
β¨ Features
- πΎ Add paginate ERB-helper
ruby SELECT * FROM articles <%= paginate(page: 1, per_page: 15) %> # SELECT * FROM articles LIMIT 15 OFFSET 0 - π§° Resolve query without extension
AppQuery[:weekly_sales]loadsweekly_sales.sqlorweekly_sales.sql.erb. - π Nested result queries via
with_selectβ chain transformations using:_placeholder to reference the previous resultruby active_users = AppQuery("SELECT * FROM users").with_select("SELECT * FROM :_ WHERE active") active_users.count("SELECT * FROM :_ WHERE admin") - π New methods:
#column,#ids,#count,#entriesβ efficient shortcuts that only fetch what you needruby query.column(:email) # SELECT email only query.ids # SELECT id only query.count # SELECT COUNT(*) only query.entries # shorthand for select_all.entries
π Fixes
- π§ Fix leading whitespace in
prepend_ctecausing parse errors - π§ Fix binds being reset when no placeholders found
- β‘
select_onenow usesLIMIT 1for better performance
π Documentation
- π Revised README with cleaner intro and examples
- π Added example Rails app in
examples/demo
[0.4.0] - 2025-12-15
features
- add insert, update and delete
- API docs at eval.github.io/appquery
- add ERB-helpers values, bind and quote .
- enabled trusted publishing to rubygems.org