### Installation Commands Source: https://www.rubydoc.info/gems/prosopite/file/README.md Commands and configuration lines required to install the Prosopite gem. ```ruby gem 'prosopite' ``` ```ruby gem 'pg_query' ``` ```bash $ bundle install ``` ```bash $ gem install prosopite ``` -------------------------------- ### N+1 Query Detection Output Source: https://www.rubydoc.info/gems/prosopite/file/README.md Example of the output format when Prosopite detects N+1 queries, including the SQL queries and the associated call stack. ```text N+1 queries detected: SELECT `users`.* FROM `users` WHERE `users`.`id` = 20 LIMIT 1 SELECT `users`.* FROM `users` WHERE `users`.`id` = 21 LIMIT 1 SELECT `users`.* FROM `users` WHERE `users`.`id` = 22 LIMIT 1 SELECT `users`.* FROM `users` WHERE `users`.`id` = 23 LIMIT 1 SELECT `users`.* FROM `users` WHERE `users`.`id` = 24 LIMIT 1 Call stack: app/controllers/thank_you_controller.rb:4:in `block in index' app/controllers/thank_you_controller.rb:3:in `each' app/controllers/thank_you_controller.rb:3:in `index': app/controllers/application_controller.rb:8:in `block in ' ``` -------------------------------- ### Setup Prosopite Scan in RSpec Helper Source: https://www.rubydoc.info/gems/prosopite/file/README.md Integrate Prosopite scanning into your RSpec tests by adding `Prosopite.scan` before each test and `Prosopite.finish` after each test in `spec/spec_helper.rb`. ```ruby config.before(:each) do Prosopite.scan end config.after(:each) do Prosopite.finish end ``` -------------------------------- ### Get Current Thread Object Source: https://www.rubydoc.info/gems/prosopite/Prosopite.tc Returns the current thread object. This method is defined in the Prosopite module. ```Ruby def tc Thread.current end ``` -------------------------------- ### Conditionally Raise N+1 Errors in Controllers Source: https://www.rubydoc.info/gems/prosopite/file/README.md Define a controller method `raise_on_n_plus_ones!` to selectively enable N+1 error raising for specific actions. This example shows how to apply it to the `index` action. ```ruby class ApplicationController < ActionController::Base def raise_on_n_plus_ones!(**options) return if Rails.env.production? prepend_around_action(:_raise_on_n_plus_ones, **options) end unless Rails.env.production? around_action :n_plus_one_detection def n_plus_one_detection ... end def _raise_on_n_plus_ones Proposite.start_raise yield ensure Prosopite.stop_raise end end end ``` ```ruby class BooksController < ApplicationController raise_on_n_plus_ones!(only: [:index]) def index @books = Book.all.map(&:author) # This will raise N+1 errors end def show @book = Book.find(params[:id]) @book.reviews.map(&:author) # This will not raise N+1 errors end end ``` -------------------------------- ### Initialize Rack Middleware Source: https://www.rubydoc.info/gems/prosopite/Prosopite/Middleware/Rack%3Ainitialize Initializes the Rack middleware with the given application. This is the standard way to set up Rack middleware. ```ruby def initialize(app) @app = app end ``` -------------------------------- ### Initialize Prosopite Rack Middleware Source: https://www.rubydoc.info/gems/prosopite/Prosopite/Middleware/Rack%3Ainitialize Initializes a new instance of the Prosopite Rack middleware. ```APIDOC ## Initialize Prosopite::Middleware::Rack ### Description Creates a new instance of the Prosopite Rack middleware to be used in the application stack. ### Method Constructor ### Parameters #### Request Body - **app** (Object) - Required - The Rack application instance to be wrapped by the middleware. ### Request Example ```ruby Prosopite::Middleware::Rack.new(app) ``` ### Response #### Success Response (200) - **instance** (Rack) - A new instance of Prosopite::Middleware::Rack. ``` -------------------------------- ### Prosopite::Middleware::Rack Constructor Source: https://www.rubydoc.info/gems/prosopite/Prosopite/Middleware/Rack Initializes the Prosopite Rack middleware with the given application. ```APIDOC ## POST /initialize ### Description Initializes the Prosopite Rack middleware with the given application. ### Method POST ### Endpoint /initialize ### Parameters #### Request Body - **app** (Object) - Required - The Rack application to wrap. ### Request Example ```json { "app": "" } ``` ### Response #### Success Response (200) - **Rack** (Object) - A new instance of Rack. #### Response Example ```json { "instance": "" } ``` ``` -------------------------------- ### Development Environment Integration Source: https://www.rubydoc.info/gems/prosopite/file/README.md Configuring Prosopite in ApplicationController and development environments. ```ruby class ApplicationController < ActionController::Base unless Rails.env.production? around_action :n_plus_one_detection def n_plus_one_detection Prosopite.scan yield ensure Prosopite.finish end end end ``` ```ruby # config/environments/development.rb config.after_initialize do Prosopite.rails_logger = true end ``` -------------------------------- ### Configure Prosopite for Test Environment Source: https://www.rubydoc.info/gems/prosopite/file/README.md Enable Prosopite logging and raising errors in the test environment by adding this to `config/environments/test.rb`. ```ruby config.after_initialize do Prosopite.rails_logger = true Prosopite.raise = true end ``` -------------------------------- ### Prosopite::Middleware::Rack#call Source: https://www.rubydoc.info/gems/prosopite/Prosopite/Middleware/Rack%3Acall The `call` method in Prosopite::Middleware::Rack processes the incoming Rack environment, initiates scanning, calls the next application in the stack, and ensures scanning is finished. ```APIDOC ## Prosopite::Middleware::Rack#call ### Description Processes the incoming Rack environment, initiates scanning, calls the next application in the stack, and ensures scanning is finished. ### Method GET ### Endpoint /websites/rubydoc_info_gems_prosopite ### Parameters #### Path Parameters - **env** (Object) - Required - The Rack environment hash. ### Request Example ```json { "env": { ... } } ``` ### Response #### Success Response (200) - **Object** (Object) - The result of the application's call. #### Response Example ```json { "result": "..." } ``` ``` -------------------------------- ### Rack Middleware Call Method Source: https://www.rubydoc.info/gems/prosopite/Prosopite/Middleware/Rack%3Acall This method is part of a Rack middleware. It initiates scanning with Prosopite, calls the next application in the stack, and ensures scanning is finished. ```ruby def call(env) Prosopite.scan @app.call(env) ensure Prosopite.finish end ``` -------------------------------- ### Scan Arbitrary Code Blocks with Prosopite Source: https://www.rubydoc.info/gems/prosopite/file/README.md Manually scan specific code sections for N+1 queries by wrapping the code with `Prosopite.scan` and `Prosopite.finish`. ```ruby Prosopite.scan Prosopite.finish ``` -------------------------------- ### Prosopite Middleware Source: https://www.rubydoc.info/gems/prosopite/Prosopite/NPlusOneQueriesError Overview of the available middleware components for integrating Prosopite into Rack-based applications and Sidekiq background jobs. ```APIDOC ## Middleware Components ### Description Prosopite provides middleware to automatically monitor and detect N+1 queries in different execution contexts. ### Available Middleware - **Prosopite::Middleware::Rack**: Middleware for monitoring web requests in Rack-based applications. - **Prosopite::Middleware::Sidekiq**: Middleware for monitoring background jobs processed by Sidekiq. ``` -------------------------------- ### Scan Code Blocks Using Block Syntax Source: https://www.rubydoc.info/gems/prosopite/file/README.md Use the block form of `Prosopite.scan` to automatically call `Prosopite.finish` at the end of the block. The result of the scanned code is also returned. ```ruby Prosopite.scan do end ``` -------------------------------- ### Prosopite::Middleware::Rack Call Method Source: https://www.rubydoc.info/gems/prosopite/Prosopite/Middleware/Rack Processes an incoming Rack request, scans for N+1 queries, calls the wrapped application, and finishes the scan. ```APIDOC ## POST /call ### Description Processes an incoming Rack request, scans for N+1 queries, calls the wrapped application, and finishes the scan. ### Method POST ### Endpoint /call ### Parameters #### Request Body - **env** (Object) - Required - The Rack environment hash. ### Request Example ```json { "env": "" } ``` ### Response #### Success Response (200) - **Object** (Object) - The result of calling the wrapped application. #### Response Example ```json { "result": "" } ``` ``` -------------------------------- ### Prosopite::Middleware::Sidekiq Class Source: https://www.rubydoc.info/gems/prosopite/Prosopite/Middleware/Sidekiq Details about the Prosopite Sidekiq middleware class, its inheritance, included modules, and defined methods. ```APIDOC ## Class: Prosopite::Middleware::Sidekiq ### Description This class is a middleware for Sidekiq that integrates with Prosopite for database query analysis. ### Inheritance - Object - Prosopite::Middleware::Sidekiq ### Includes - Sidekiq::ServerMiddleware ### Defined in - lib/prosopite/middleware/sidekiq.rb ## Instance Method: #call ### Description This method is called by Sidekiq to process a job. It initiates Prosopite scanning, yields to the next middleware or the job itself, and ensures Prosopite is finished afterward. ### Method - instance method ### Endpoint N/A (This is a class method within a Ruby gem) ### Parameters - **_worker** (Object) - The Sidekiq worker instance. - **_msg** (Hash) - The job message payload. - **_queue** (String) - The name of the queue the job was processed from. ### Request Body N/A ### Response #### Success Response (Object) - Returns the result of the yielded block. ### Response Example ```ruby # File 'lib/prosopite/middleware/sidekiq.rb', line 6 def call(_worker, _msg, _queue) Prosopite.scan yield ensure Prosopite.finish end ``` ``` -------------------------------- ### Add Prosopite Sidekiq Middleware Source: https://www.rubydoc.info/gems/prosopite/file/README.md Integrate Prosopite middleware for Sidekiq version 6.5.0+ to detect N+1 queries within background jobs. Add this to your Sidekiq initializer. ```ruby Sidekiq.configure_server do |config| unless Rails.env.production? config.server_middleware do |chain| require 'prosopite/middleware/sidekiq' chain.add(Prosopite::Middleware::Sidekiq) end end end ``` -------------------------------- ### Execute Sidekiq Middleware Call Source: https://www.rubydoc.info/gems/prosopite/Prosopite/Middleware/Sidekiq%3Acall Wraps the Sidekiq job execution with Prosopite scan and finish calls to detect N+1 queries. ```ruby def call(_worker, _msg, _queue) Prosopite.scan yield ensure Prosopite.finish end ``` -------------------------------- ### Configure Prosopite Allow List for Call Stacks Source: https://www.rubydoc.info/gems/prosopite/file/README.md Specify substrings or regex patterns in call stacks to ignore for Prosopite notifications. ```ruby Prosopite.allow_stack_paths = ['substring_in_call_stack', /regex/] ``` -------------------------------- ### N+1 Query Detection Scenarios Source: https://www.rubydoc.info/gems/prosopite/file/README.md Various code patterns that trigger N+1 query detection in Prosopite. ```ruby FactoryBot.create_list(:leg, 10) Leg.last(10).each do |l| l.chair end ``` ```ruby Leg.last(4).each do |l| Chair.find(l.chair_id) end ``` ```ruby Chair.last(20).each do |c| c.legs.first c.legs.last c.legs.pluck(:id) end ``` ```ruby Chair.last(20).map{ |c| c.becomes(ArmChair) }.each do |ac| ac.legs.map(&:id) end ``` ```ruby class Leg::Design include Mongoid::Document ... field :cid, as: :chair_id, type: Integer ... def chair @chair ||= Chair.where(id: chair_id).first! end end Leg::Design.last(20) do |l| l.chair end ``` -------------------------------- ### Prosopite::Middleware::Sidekiq#call Source: https://www.rubydoc.info/gems/prosopite/Prosopite/Middleware/Sidekiq%3Acall The `call` method in Prosopite::Middleware::Sidekiq is responsible for scanning and finishing Prosopite's data collection within the Sidekiq worker process. ```APIDOC ## POST /api/users ### Description This endpoint allows for the creation of new user accounts. ### Method POST ### Endpoint /api/users ### Parameters #### Query Parameters - **limit** (integer) - Optional - The maximum number of users to return. #### Request Body - **username** (string) - Required - The desired username for the new account. - **email** (string) - Required - The email address for the new account. ### Request Example ```json { "username": "johndoe", "email": "john.doe@example.com" } ``` ### Response #### Success Response (201) - **id** (integer) - The unique identifier for the newly created user. - **username** (string) - The username of the created user. - **email** (string) - The email address of the created user. #### Response Example ```json { "id": 123, "username": "johndoe", "email": "john.doe@example.com" } ``` ``` -------------------------------- ### Configure Prosopite Ignore Queries Source: https://www.rubydoc.info/gems/prosopite/file/README.md Define regex patterns or exact string matches for SQL queries that Prosopite should ignore. ```ruby Prosopite.ignore_queries = [/regex_match/, "SELECT * from EXACT_STRING_MATCH"] ``` -------------------------------- ### Add Prosopite Rack Middleware Source: https://www.rubydoc.info/gems/prosopite/file/README.md Include the Prosopite Rack middleware in your Rails application by adding this to `config/initializers/prosopite.rb` to automatically detect N+1 queries in all controllers. ```ruby unless Rails.env.production? require 'prosopite/middleware/rack' Rails.configuration.middleware.use(Prosopite::Middleware::Rack) end ``` -------------------------------- ### Wrap Function Calls with Prosopite.scan Source: https://www.rubydoc.info/gems/prosopite/file/README.md Wrap function or method calls with `Prosopite.scan` to capture N+1 queries within those calls and return the result. ```ruby my_object = Prosopite.scan do MyObjectFactory.create(params) end ``` -------------------------------- ### Configure Prosopite with a Custom Logger Instance Source: https://www.rubydoc.info/gems/prosopite/file/README.md Assign a custom logger instance to `Prosopite.custom_logger` for advanced logging configurations, such as sending logs to a specific file or service. ```ruby # Use a completely custom logging instance Prosopite.custom_logger = MyLoggerClass.new ``` -------------------------------- ### Pause and Resume Prosopite Scans Source: https://www.rubydoc.info/gems/prosopite/file/README.md Temporarily pause Prosopite scans during specific code sections using `Prosopite.pause` and resume them with `Prosopite.resume`. `Prosopite.finish` must still be called. ```ruby Prosopite.scan # Prosopite.pause # Prosopite.resume # Prosopite.finish ``` -------------------------------- ### Conditional Sidekiq Middleware for Older Versions Source: https://www.rubydoc.info/gems/prosopite/file/README.md Use this conditional snippet if you are running Sidekiq older than 6.5.0 and want to add the Prosopite middleware. Remove it once you upgrade Sidekiq. ```ruby if Sidekiq::VERSION >= '6.5.0' && (Rails.env.development? || Rails.env.test?) ..... end ``` -------------------------------- ### Prosopite.tc Method Source: https://www.rubydoc.info/gems/prosopite/Prosopite.tc This snippet documents the `tc` method within the Prosopite class, which returns the current thread. ```APIDOC ## Prosopite.tc ### Description Returns the current thread. ### Method GET (Implicit) ### Endpoint N/A (Instance Method) ### Parameters None ### Request Example None ### Response #### Success Response (200) - **thread** (Object) - The current thread object. #### Response Example ```ruby Thread.current ``` ``` -------------------------------- ### Prosopite::NPlusOneQueriesError Source: https://www.rubydoc.info/gems/prosopite/Prosopite/NPlusOneQueriesError Details regarding the NPlusOneQueriesError exception class used by Prosopite to signal detected N+1 query issues. ```APIDOC ## Exception: Prosopite::NPlusOneQueriesError ### Description This exception is raised by the Prosopite gem when an N+1 query pattern is detected during application execution. ### Inheritance - StandardError - Object ### Defined in lib/prosopite.rb ``` -------------------------------- ### Configure Prosopite to Use Rails Logger Source: https://www.rubydoc.info/gems/prosopite/file/README.md Set `Prosopite.custom_logger = Rails.logger` to disable Prosopite's default red highlighting while still sending logs to the Rails logger. This is useful for JSON logging. ```ruby # Turns off logging with red highlights, but still sends them to the Rails logger Prosopite.custom_logger = Rails.logger ``` -------------------------------- ### Disable Default Prosopite Raising Behavior Source: https://www.rubydoc.info/gems/prosopite/file/README.md Set `Prosopite.raise = false` to disable N+1 query raising by default. This allows you to selectively enable raising in specific scenarios. ```ruby Proposite.raise = false ``` -------------------------------- ### Pause Scans Within a Block Source: https://www.rubydoc.info/gems/prosopite/file/README.md Use the block form of `Prosopite.pause` to automatically resume scans after the block. This is useful for isolating code sections with potential N+1 queries. ```ruby Prosopite.scan # result = Prosopite.pause do # end Prosopite.finish ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.