All Projects → cveneziani → query-objects-example

cveneziani / query-objects-example

Licence: other
Example of rails app using Query Objects

Programming Languages

ruby
36898 projects - #4 most used programming language
HTML
75241 projects
SCSS
7915 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to query-objects-example

Coloquent
Javascript/Typescript library mapping objects and their interrelations to JSON API, with a clean, fluent ActiveRecord-like (e.g. similar to Laravel's Eloquent) syntax for creating, retrieving, updating and deleting model objects.
Stars: ✭ 149 (+302.7%)
Mutual labels:  activerecord
Activerecord Turntable
ActiveRecord Sharding Plugin
Stars: ✭ 206 (+456.76%)
Mutual labels:  activerecord
Octopus
Database Sharding for ActiveRecord
Stars: ✭ 2,496 (+6645.95%)
Mutual labels:  activerecord
Activejpa
A simple active record pattern library in java that makes programming DAL easier
Stars: ✭ 172 (+364.86%)
Mutual labels:  activerecord
Ar Softdelete
Soft delete behavior for ActiveRecord
Stars: ✭ 188 (+408.11%)
Mutual labels:  activerecord
Anima
Minimal database operation library.
Stars: ✭ 210 (+467.57%)
Mutual labels:  activerecord
Graphql Query Resolver
Minimize N+1 queries generated by GraphQL and ActiveRecord
Stars: ✭ 148 (+300%)
Mutual labels:  activerecord
Scenic
Scenic is maintained by Derek Prior, Caleb Hearth, and you, our contributors.
Stars: ✭ 2,856 (+7618.92%)
Mutual labels:  activerecord
Jsonapi Utils
Build JSON API-compliant APIs on Rails with no (or less) learning curve.
Stars: ✭ 191 (+416.22%)
Mutual labels:  activerecord
Seamless database pool
Add support for master/slave database clusters in ActiveRecord to improve performance.
Stars: ✭ 222 (+500%)
Mutual labels:  activerecord
Ldaprecord Laravel
Multi-domain LDAP Authentication & Management for Laravel.
Stars: ✭ 178 (+381.08%)
Mutual labels:  activerecord
Groupify
Add group and membership functionality to your Rails models
Stars: ✭ 187 (+405.41%)
Mutual labels:  activerecord
Secondbase
Seamless second database integration for Rails.
Stars: ✭ 216 (+483.78%)
Mutual labels:  activerecord
Ldaprecord
A fully-featured LDAP framework.
Stars: ✭ 159 (+329.73%)
Mutual labels:  activerecord
Activerecord Postgres enum
Integrate PostgreSQL's enum data type into ActiveRecord's schema and migrations.
Stars: ✭ 227 (+513.51%)
Mutual labels:  activerecord
Querybuilder
SQL query builder, written in c#, helps you build complex queries easily, supports SqlServer, MySql, PostgreSql, Oracle, Sqlite and Firebird
Stars: ✭ 2,111 (+5605.41%)
Mutual labels:  activerecord
Randumb
Adds ability to pull back random records from Active Record
Stars: ✭ 208 (+462.16%)
Mutual labels:  activerecord
n1 loader
Loader to solve N+1 issues for good. Highly recommended for GraphQL API.
Stars: ✭ 182 (+391.89%)
Mutual labels:  activerecord
Occams Record
The missing high-efficiency query API for ActiveRecord
Stars: ✭ 240 (+548.65%)
Mutual labels:  activerecord
Activerecord json validator
🔩 ActiveRecord::JSONValidator makes it easy to validate JSON attributes against a JSON schema.
Stars: ✭ 220 (+494.59%)
Mutual labels:  activerecord

Query Objects - Example

This is an example of a rails application that defines and uses Query Objects.

Getting started

Have a look at app/queries/ folder.

3 implementations are provided:

  • Delegating to ActiveRecord::Relation (default one)
  • Delegating to ActiveRecord::Relation with chaining ActiveRecord conditions in between
  • Extending ActiveRecord::Relation

Usage

Defining a Query Object

class ArtistQuery < BaseQuery
  # defines the default model on which queries will be made
  def self.relation(base_relation=nil)
    super(base_relation, Artist)
  end

  # a first scope
  def available
    where(available: true)
  end

  # another scope
  def by_genre(genre)
    where(genre: genre)
  end
end

Making queries

ArtistQuery.relation
# =>  Returns all artists.
#     Based on `all` relation provided by `ActiveRecord`).

ArtistQuery.relation.available
# =>  Returns all available artists.
#     Based on `available` scope method provided by `ArtistQuery`.

ArtistQuery.relation.available.by_genre('Metal')
# =>  Returns all available Metal artists.
#     Based on `available` and `by_genre(name)` scope methods provided by `ArtistQuery`.

ArtistQuery.relation.available.by_genre('Metal').order(:name)
# =>  Returns all available metal artists ordered by name.
#     Based on `available` and `by_genre(name)` scope methods provided by `ArtistQuery`
#     and based on `order` method provided by `ActiveRecord`.

awesome_label = Label.first
ArtistQuery.relation(awesome_label.artists).available
# =>  Returns all available artists for awesome label.
#     Based on the following association: `label` has many `artists`.

Chaining with ActiveRecord conditions in between

By default, this feature is not provided.

# PROVIDED
ArtistQuery.relation.available.order(:name)

# NOT PROVIDED
ArtistQuery.relation.order(:name).available
# =>  NoMethodError:
#     undefined method `available' for #<Artist::ActiveRecord_Relation:0x000000033208b8>

To enable this feature - which isn't recommended - switch to the second implementation.

Why isn't it recommended?

The purpose of query objects is to extract scopes from models and to have relevant queries. Thus introducing ActiveRecord conditions between relevant queries is an anti-pattern. Try to avoid this behaviour.

Tests

There are tests for the 3 implementations. To run the tests:

$ rspec

Benchmark

A benchmark is provided between 2 implementations: delegator (default one) and extend. Just run the following command:

$ rake benchmark

Results

Warming up --------------------------------------
delegator -- without model 12.047k i/100ms
delegator -- with model    15.510k i/100ms
extend -- without model     8.431k i/100ms
extend -- with model        8.397k i/100ms
Calculating -------------------------------------
delegator -- without model 170.047k (± 3.8%) i/s -    855.337k in   5.037890s
delegator -- with model    169.862k (± 3.5%) i/s -    853.050k in   5.029212s
extend -- without model     77.498k (±12.7%) i/s -    379.395k in   5.009203s
extend -- with model        81.004k (±14.7%) i/s -    394.659k in   5.005465s

Comparison:
delegator -- without model: 170047.0 i/s
delegator -- with model:    169862.0 i/s - same-ish: difference falls within error
extend -- with model:        81004.4 i/s - 2.10x slower
extend -- without model:     77497.9 i/s - 2.19x slower

Running the app

Requirements

  • Ruby 2.4+
  • SQLite

Installation

$ bundle install
$ rake db:create db:migrate db:seed

Credits

Thanks to Bert Goethals for his help in optimizing the Query Objects.

License

This project is released under the WTFPL License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].