All Projects → franckverrot → no_querying_views

franckverrot / no_querying_views

Licence: other
No more querying views in your Rails apps

Programming Languages

ruby
36898 projects - #4 most used programming language
HTML
75241 projects

Projects that are alternatives of or similar to no querying views

Octopus
Database Sharding for ActiveRecord
Stars: ✭ 2,496 (+4060%)
Mutual labels:  activerecord
embedded
Rails/Activerecord plugin to make value objects embedded into active record objects
Stars: ✭ 48 (-20%)
Mutual labels:  activerecord
blade-jdbc
🐜 move to https://github.com/biezhi/anima
Stars: ✭ 36 (-40%)
Mutual labels:  activerecord
Occams Record
The missing high-efficiency query API for ActiveRecord
Stars: ✭ 240 (+300%)
Mutual labels:  activerecord
activerecord-migrations
A gem to simplify activerecord migrations in non-rails projects.
Stars: ✭ 15 (-75%)
Mutual labels:  activerecord
activerecord-debug errors
An extension of activerecord to display useful debug logs on errors
Stars: ✭ 23 (-61.67%)
Mutual labels:  activerecord
Activerecord json validator
🔩 ActiveRecord::JSONValidator makes it easy to validate JSON attributes against a JSON schema.
Stars: ✭ 220 (+266.67%)
Mutual labels:  activerecord
departure
Percona's pt-online-schema-change runner for ActiveRecord migrations.
Stars: ✭ 86 (+43.33%)
Mutual labels:  activerecord
sql-builder
A simple SQL builder for generate SQL for non-ActiveRecord supports databases
Stars: ✭ 34 (-43.33%)
Mutual labels:  activerecord
active snapshot
Simplified snapshots and restoration for ActiveRecord models and associations with a transparent white-box implementation
Stars: ✭ 67 (+11.67%)
Mutual labels:  activerecord
Scenic
Scenic is maintained by Derek Prior, Caleb Hearth, and you, our contributors.
Stars: ✭ 2,856 (+4660%)
Mutual labels:  activerecord
query-objects-example
Example of rails app using Query Objects
Stars: ✭ 37 (-38.33%)
Mutual labels:  activerecord
attribute-depends-calculator
Automatically calculate a collection of depends attribute of ActiveRecord
Stars: ✭ 41 (-31.67%)
Mutual labels:  activerecord
Activerecord Postgres enum
Integrate PostgreSQL's enum data type into ActiveRecord's schema and migrations.
Stars: ✭ 227 (+278.33%)
Mutual labels:  activerecord
ar-search
Provides unified search model for Yii ActiveRecord
Stars: ✭ 31 (-48.33%)
Mutual labels:  activerecord
Seamless database pool
Add support for master/slave database clusters in ActiveRecord to improve performance.
Stars: ✭ 222 (+270%)
Mutual labels:  activerecord
yii2-activerecord-inheritance
ActiveRecord Inheritance is an util to provide the Class Table Inheritance Pattern the to the Yii2 framework
Stars: ✭ 18 (-70%)
Mutual labels:  activerecord
activerecord-crate-adapter
Ruby on Rails ActiveRecord adapter for CrateDB
Stars: ✭ 27 (-55%)
Mutual labels:  activerecord
active dynamic
Gem that allows to add attributes to your active models dynamically
Stars: ✭ 61 (+1.67%)
Mutual labels:  activerecord
sinatra-bootstrap
My opinionated Sinatra base application
Stars: ✭ 14 (-76.67%)
Mutual labels:  activerecord

No Querying Views

This gem will tell you when your team when they are querying the database from a view.

It currently supports SQLite3 and PostgreSQL.

Requirements

  • Rails 5+

INSTALL

Manually, you can install the gem:

gem install no_querying_views

In your gemspec:

gem 'no_querying_views', '~> 6.0.0'

(There are no versions 3 to 6, I decided to align this gem's version with Rails major versions.)

Context

Rails is a MVC framework. The separation of concern should be respected to prevent bad things to happen in your application.

Example: An order has N order lines. Each of these order lines has 1 related item, and each of these items belongs to 1 category.

In Ruby code, your models would look like this:

# app/models/order.rb
class Order < ActiveRecord::Base
  has_many :lines
end


# app/models/line.rb
class Line < ActiveRecord::Base
  has_one :item
end


# app/models/item.rb
class Item < ActiveRecord::Base
  belongs_to :category
end


# app/models/category.rb
class Category < ActiveRecord::Base
end

Now, if you want to display them on a single page, here is a naive version of order_controller.rb:

# app/controllers/order_controller.rb
class OrderController < ApplicationController
  def show
    @order = Order.find(params[:id])  # 1 query
  end
end

And a naive version of the views used to display the result:

# app/views/orders/show.html.haml
%h1
  = @order.title
%h2
  %span Items
  %ul
    = render :partial => 'lines', :collection => order.lines   # 1 query, so far: 2 queries

# app/views/orders/_lines.html.haml executed for **each single line**
%li
  %span
    = line.item.title          # 1 query
    = line.price
  %div{:class => 'item_description'}
    = line.item.description    # 0 query (cached)
    = line.item.category       # 1 query

The problem

If you use a tool that generates execution traces (like NewRelic RPM), you will see that - for 1 order, 40 lines, 30 items, 20 categories - you will execute: 1 (select * from order)

  • 1 (select * from lines inner join ... where order_id = foo)
  • 40 (select * from items inner join ... where line.item_id = bar)
  • 40 (select * from categories inner join ... where item.category_id = baz)

82 queries against the database!

This is called the N + 1 problem and it can be solved by an eager-loading strategy.

"Yeah, but my database is so small and so fast that I don't even see that!"

This is true if you are the only user of the website. But Rails will also have troubles generating the page (HAML, ERB, whatever) and NewRelic won't tell you that the queries are slowing down the application: the queries are fast as hell.

The combination of the rendering and the querying is slowing down the application, because:

  1. Rendering a partial is slower than inline code
  2. Executing a query costs time (retrieving the DB connection within the pool, executing and fetching the results, ...): the resources are not being used for free on your machine.

The solution

Silver bullets don't exist, but most of the time you can speed up the performance by eager-loading the data you expect in your views.

From an architectural point of view, it is wrong to query the DB from a view. There are many reasons not to do so and the internet is full of literature about it.

Right now, here is a piece of code to help you remove any DB query from your views.

What does this code do?

It will raise an exception everytime you and your people try to query the database from within a view.

It only overrides the execute method of the adapter and checks the call stack.

License

MIT License. Copyright 2014 - Franck Verrot [email protected]

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].