Convert Figma logo to code with AI

basecamp logomarginalia

Attach comments to ActiveRecord's SQL queries

1,754
143
1,754
12

Top Related Projects

56,803

Ruby on Rails

6,266

A toolkit for data mapping and language integrated query.

SQL query builder, written in c#, helps you build complex queries easily, supports SqlServer, MySql, PostgreSql, Oracle, Sqlite and Firebird

1,471

A Clojure library for using SQL.

6,370

jOOQ is the best way to write SQL in Java

19,674

A query builder for PostgreSQL, MySQL, CockroachDB, SQL Server, SQLite3 and Oracle, designed to be flexible, portable, and fun to use.

Quick Overview

Marginalia is a Ruby gem that adds comments to ActiveRecord queries, helping developers identify the source of database queries in their Rails applications. It automatically annotates SQL queries with information about the originating controller, action, and line number, making it easier to debug and optimize database performance.

Pros

  • Improves query debugging by providing context for each SQL statement
  • Minimal setup required, works out of the box with Rails applications
  • Customizable annotation format to suit specific needs
  • Lightweight and low-overhead solution for query tracing

Cons

  • Limited to Ruby on Rails applications using ActiveRecord
  • May slightly increase query execution time due to added comments
  • Requires manual configuration for non-standard setups or custom ORMs
  • Could potentially expose sensitive information if SQL logs are not properly secured

Code Examples

  1. Basic usage with default configuration:
# In config/application.rb
config.marginalia.application_name = "MyApp"
  1. Customizing comment components:
Marginalia::Comment.components = [:application, :controller, :action, :line]
  1. Adding custom information to query comments:
Marginalia::Comment.components = [:application, :controller, :action, :line, :custom]

Marginalia::Comment.customize_controller do |controller|
  controller.instance_variable_get("@current_user")&.id
end

Getting Started

To get started with Marginalia, follow these steps:

  1. Add the gem to your Gemfile:

    gem 'marginalia'
    
  2. Run bundle install to install the gem.

  3. Configure the application name in config/application.rb:

    config.marginalia.application_name = "YourAppName"
    
  4. Restart your Rails server, and Marginalia will automatically start annotating your SQL queries.

Competitor Comparisons

56,803

Ruby on Rails

Pros of Rails

  • Comprehensive full-stack web application framework
  • Large, active community with extensive documentation and resources
  • Built-in tools for testing, database management, and asset pipeline

Cons of Rails

  • Steeper learning curve for beginners
  • Can be overkill for smaller projects
  • Opinionated structure may limit flexibility in some cases

Code Comparison

Rails (config/application.rb):

module MyApp
  class Application < Rails::Application
    config.load_defaults 6.1
    config.autoloader = :zeitwerk
  end
end

Marginalia (lib/marginalia.rb):

module Marginalia
  def self.comment
    @comment_block.call if @comment_block
  end
end

Summary

Rails is a full-featured web application framework, offering a complete solution for building web applications. It provides a wide range of tools and conventions out of the box, making it suitable for large-scale projects. However, this comprehensiveness can be overwhelming for beginners and may be excessive for smaller applications.

Marginalia, on the other hand, is a focused gem that adds comments to ActiveRecord queries. It's a lightweight solution for improving database query visibility and debugging. While not as feature-rich as Rails, Marginalia excels in its specific use case and can be easily integrated into existing Rails projects.

6,266

A toolkit for data mapping and language integrated query.

Pros of Ecto

  • More comprehensive database toolkit with query building, migrations, and schemas
  • Supports multiple databases (PostgreSQL, MySQL, SQLite) out of the box
  • Active development with frequent updates and a large community

Cons of Ecto

  • Steeper learning curve due to its extensive feature set
  • Requires more setup and configuration compared to simpler solutions
  • May be overkill for small projects or simple database interactions

Code Comparison

Ecto query example:

query = from u in User,
  where: u.age > 18,
  select: u.name
Repo.all(query)

Marginalia query example:

User.where("age > 18").select(:name)

Key Differences

  • Ecto is a full-featured database toolkit for Elixir, while Marginalia is a Ruby gem focused on adding SQL comments
  • Ecto provides a more robust query DSL, while Marginalia enhances existing ActiveRecord queries
  • Ecto handles database interactions directly, whereas Marginalia works alongside ActiveRecord

Use Cases

  • Choose Ecto for comprehensive database management in Elixir projects
  • Opt for Marginalia when you need to add context to SQL queries in Ruby on Rails applications

SQL query builder, written in c#, helps you build complex queries easily, supports SqlServer, MySql, PostgreSql, Oracle, Sqlite and Firebird

Pros of SqlKata

  • Supports multiple database providers (SQL Server, PostgreSQL, MySQL, SQLite)
  • Offers a fluent API for building complex queries
  • Provides query compilation and parameter binding for improved security

Cons of SqlKata

  • Lacks built-in performance monitoring and optimization features
  • May require more setup and configuration compared to Marginalia
  • Does not offer automatic query annotation or logging capabilities

Code Comparison

SqlKata:

var query = new Query("users")
    .Where("id", 1)
    .OrWhere("email", "user@example.com")
    .Select("name", "email");

Marginalia:

User.where(id: 1)
    .or(email: "user@example.com")
    .select(:name, :email)
    .annotate(application: "web", feature: "user_search")

Summary

SqlKata is a versatile query builder supporting multiple databases with a fluent API, while Marginalia focuses on query annotation and performance monitoring in Ruby on Rails applications. SqlKata offers more flexibility in database choice but lacks built-in performance optimization features. Marginalia excels in automatic query annotation and logging but is specific to Ruby on Rails. The choice between the two depends on the project's requirements, programming language, and database ecosystem.

1,471

A Clojure library for using SQL.

Pros of Yesql

  • Allows writing raw SQL queries in separate .sql files, promoting better separation of concerns
  • Supports multiple database systems, offering greater flexibility
  • Enables easier collaboration between developers and database administrators

Cons of Yesql

  • Requires manual mapping of query results to Clojure data structures
  • May lead to less type safety compared to using an ORM or DSL
  • Potential for SQL injection if not used carefully

Code Comparison

Marginalia:

Book.select(:title, :author)
    .where("published_at > ?", 1.year.ago)
    .order(published_at: :desc)
    .limit(10)

Yesql:

(def get-recent-books
  (yesql/defquery "SELECT title, author
                   FROM books
                   WHERE published_at > :published_after
                   ORDER BY published_at DESC
                   LIMIT 10"))

(get-recent-books db {:published_after (-> 1 t/years t/ago)})

Marginalia uses a Ruby-based DSL for query building, while Yesql allows writing raw SQL in separate files and executing them with parameters.

6,370

jOOQ is the best way to write SQL in Java

Pros of jOOQ

  • Comprehensive SQL builder and ORM framework for Java
  • Supports multiple database systems and advanced SQL features
  • Extensive documentation and active community support

Cons of jOOQ

  • Steeper learning curve due to its extensive feature set
  • Requires code generation step for optimal usage
  • Commercial licensing for some database systems

Code Comparison

jOOQ:

Result<Record> result = create.select()
    .from(AUTHOR)
    .where(AUTHOR.FIRST_NAME.like("J%"))
    .orderBy(AUTHOR.LAST_NAME)
    .fetch();

Marginalia:

(sql/query db
  (sql/format
    {:select [:*]
     :from [:author]
     :where [:like :first_name "J%"]
     :order-by [:last_name]}))

Key Differences

  • jOOQ is Java-based, while Marginalia is Clojure-based
  • jOOQ offers a more comprehensive SQL toolkit, whereas Marginalia focuses on SQL query generation
  • Marginalia provides a simpler, more lightweight approach to SQL generation
  • jOOQ has a stronger focus on type safety and compile-time checks

Use Cases

  • jOOQ: Large-scale Java applications with complex database interactions
  • Marginalia: Clojure projects requiring simple SQL generation and database querying
19,674

A query builder for PostgreSQL, MySQL, CockroachDB, SQL Server, SQLite3 and Oracle, designed to be flexible, portable, and fun to use.

Pros of Knex

  • More comprehensive SQL query builder with support for multiple database systems
  • Larger community and more frequent updates
  • Provides migration and seeding tools for database schema management

Cons of Knex

  • Steeper learning curve due to more complex API
  • Heavier dependency with larger codebase
  • May be overkill for simple database operations

Code Comparison

Marginalia example:

Post.where(published: true).annotate("Finding published posts")

Knex example:

knex('posts')
  .where({ published: true })
  .comment('Finding published posts')

Summary

Knex is a more feature-rich SQL query builder that supports multiple databases, while Marginalia focuses specifically on adding comments to SQL queries in Ruby on Rails applications. Knex offers a broader range of functionality, including migrations and seeding, but comes with a steeper learning curve. Marginalia is simpler and more lightweight, designed for a specific use case in Rails applications.

Both libraries allow adding comments to SQL queries, but Knex provides this functionality as part of a larger query-building ecosystem, while Marginalia is dedicated to this specific task. The choice between the two depends on the project requirements, database complexity, and the developer's familiarity with the respective ecosystems.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

marginalia Build Status

Attach comments to your ActiveRecord queries. By default, it adds the application, controller, and action names as a comment at the end of each query.

This helps when searching log files for queries, and seeing where slow queries came from.

For example, once enabled, your logs will look like:

Account Load (0.3ms)  SELECT `accounts`.* FROM `accounts` 
WHERE `accounts`.`queenbee_id` = 1234567890 
LIMIT 1 
/*application:BCX,controller:project_imports,action:show*/

You can also use these query comments along with a tool like pt-query-digest to automate identification of controllers and actions that are hotspots for slow queries.

This gem was created at 37signals. You can read more about how we use it on our blog.

This has been tested and used in production with the mysql2 and pg gems, and is tested on Rails 5.2 through 6.1, and Ruby 2.6 through 3.0. It is also tested for sqlite3. As of Rails 7, Marginalia is a part of Rails itself and does not need to be separately included.

Rails version support will follow supported versions in the Ruby on Rails maintenance policy and Ruby support will follow maintained versions in the Ruby maintenance policy.

Patches are welcome for other database adapters.

Installation

# Gemfile
gem 'marginalia'

Customization

Optionally, you can set the application name shown in the log like so in an initializer (e.g. config/initializers/marginalia.rb):

Marginalia.application_name = "BCX"

The name will default to your Rails application name.

Components

You can also configure the components of the comment that will be appended, by setting Marginalia::Comment.components. By default, this is set to:

Marginalia::Comment.components = [:application, :controller, :action]

Which results in a comment of application:#{application_name},controller:#{controller.name},action:#{action_name}.

You can re-order or remove these components. You can also add additional comment components of your desire by defining new module methods for Marginalia::Comment which return a string. For example:

module Marginalia
  module Comment
    def self.mycommentcomponent
      "TEST"
    end
  end
end

Marginalia::Comment.components = [:application, :mycommentcomponent]

Which will result in a comment like application:#{application_name},mycommentcomponent:TEST The calling controller is available to these methods via @controller.

Marginalia ships with :application, :controller, and :action enabled by default. In addition, implementation is provided for:

  • :line (for file and line number calling query). :line supports a configuration by setting a regexp in Marginalia::Comment.lines_to_ignore to exclude parts of the stacktrace from inclusion in the line comment.
  • :controller_with_namespace to include the full classname (including namespace) of the controller.
  • :job to include the classname of the ActiveJob being performed.
  • :hostname to include Socket.gethostname.
  • :pid to include current process id.
  • :db_host to include the configured database hostname.
  • :socket to include the configured database socket.
  • :database to include the configured database name.

Pull requests for other included comment components are welcome.

Prepend comments

By default marginalia appends the comments at the end of the query. Certain databases, such as MySQL will truncate the query text. This is the case for slow query logs and the results of querying some InnoDB internal tables where the length of the query is more than 1024 bytes.

In order to not lose the marginalia comments from your logs, you can prepend the comments using this option:

Marginalia::Comment.prepend_comment = true

Inline query annotations

In addition to the request or job-level component-based annotations, Marginalia may be used to add inline annotations to specific queries using a block-based API.

For example, the following code:

Marginalia.with_annotation("foo") do
  Account.where(queenbee_id: 1234567890).first
end

will issue this query:

Account Load (0.3ms)  SELECT `accounts`.* FROM `accounts`
WHERE `accounts`.`queenbee_id` = 1234567890
LIMIT 1
/*application:BCX,controller:project_imports,action:show*/ /*foo*/

Nesting with_annotation blocks will concatenate the comment strings.

Caveats

Prepared statements

Be careful when using Marginalia with prepared statements. If you use a component like request_id then every query will be unique and so ActiveRecord will create a new prepared statement for each potentially exhausting system resources. Disable prepared statements if you wish to use components with high cardinality values.

Contributing

Start by bundling and creating the test database:

bundle
rake db:mysql:create
rake db:postgresql:create

Then, running rake will run the tests on all the database adapters (mysql, mysql2, postgresql and sqlite):

rake