You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

探究Rails.application.configure块未传变量却可运行的原理

How Rails' Configure Block Works Without Passing a config Argument

Great question! The difference between Rails' configure pattern and Clearance's comes down to a clever Ruby metaprogramming trick: changing the execution context of the block using instance_eval (or module_eval), instead of passing the configuration object via yield.

Let’s break this down step by step:

1. The Core: instance_eval in Ruby

When you call instance_eval on an object and pass a block, Ruby changes the value of self inside that block to be the object you called instance_eval on. That means any method calls inside the block (without an explicit receiver) will be called directly on that object.

Rails leverages this in its configure method. Instead of yielding the configuration object to the block (like Clearance does), it runs the block in the context of the configuration object itself.

2. Rails' Simplified Implementation

Here’s a stripped-down version of how Rails might implement its configure logic to make this clear:

module Rails
  class << self
    def application
      @application ||= Application.new
    end
  end

  class Application
    def configure(&block)
      # Get or initialize the configuration object
      @config ||= Configuration.new
      # Run the block in the context of @config
      @config.instance_eval(&block)
    end
  end

  class Configuration
    attr_accessor :some_option, :another_option

    # The magic: define a `config` method that returns `self`
    def config
      self
    end

    def initialize
      # Set default values
      @some_option = "default_value"
    end
  end
end

# Usage (just like Rails!)
Rails.application.configure do
  # `self` here is the Configuration instance
  config.some_option = "custom_value"
  # You could even skip `config` entirely:
  another_option = "another_custom_value"
end

3. Why config Works Without Being Passed

Inside the configure block:

  • self is the Configuration instance (thanks to instance_eval).
  • Rails adds a config method to the Configuration class that simply returns self. So when you write config.some_option, you’re actually calling the config method on the current self (the Configuration instance), getting back the same instance, and then calling some_option= on it.

You could even omit config entirely and just write some_option = "value"—since self is the Configuration instance, Ruby will look for the setter method on self first.

4. Comparing to Clearance's Approach

Clearance uses the more straightforward yield(configuration) pattern, which requires the block to accept an argument (e.g., {|config| ...}). This is totally valid, but Rails' approach makes the syntax a bit cleaner by removing the need for the block parameter.

5. The Configurable Module

You mentioned Rails' Configurable module—this is where Rails encapsulates this logic. It provides the configure method, handles initializing the configuration object, and sets up the config method so you can reference the configuration instance easily inside the block.

内容的提问来源于stack exchange,提问作者sandre89

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:59:36