RoR的“神奇”命名空间解析如何工作?

时间:2013-01-17 20:35:36

标签: ruby-on-rails ruby

我来自使用Python,我对Ruby on Rails的“魔力”如何运作感到非常困惑。

1。在任何地方都没有任何需要声明

在Python中,为了从任何地方访问函数,您必须导入。我认为基础红宝石也是如此。但是当使用rails时,我可以调用其他模块中定义的隐藏变量和函数,而不需要在页面顶部使用任何require语句。

E.g。我可以有一个文件:

class CartsController < ApplicationController
....
def show
        begin
            @cart = Cart.find(params[:id])
        rescue ActiveRecord::RecordNotFound
            logger.error "Attempt to access invalid cart #{params[:id]}"
            redirect_to store_url, notice: 'Invalid cart'
        end
 end

记录器重定向,等等都没有定义。它只是从ApplicationController继承了一些复杂的树,还是以某种方式通过其他机制访问这些命名空间?

2。使用不存在的方法

这是有效的rails代码

current_item = line_items.find_by_product_id(product_id)

其中 find_by_products_id 尚未在任何地方定义,但Rails会以某种方式动态“创建”该方法。关于如何做到的任何技术见解?

感谢您的帮助!

3 个答案:

答案 0 :(得分:9)

Rails'“Magic”广泛使用method_missingconst_missing

当您尝试调用未定义的方法时,ruby会触发对method_missing的调用。 像ActiveRecord这样的库使用它来实现动态查找器。

method_missing示例:

SomeModel.find_by_some_field("some_value")未定义。

这会调用SomeModel.method_missing(:find_by_some_field, "some_value")

ActiveRecord然后将此调用转换为`SomeModel.where(:some_field =&gt;“some_value”)

(出于性能目的,ActiveRecord然后动态定义此方法,因此下次定义find_by_some_field时)

const_missing示例:

SomeModel尚未被要求。

Ruby解释器使用参数const_missing

调用"SomeModel

遵循惯例的Rails "SomeModel"应该在名为some_model.rb的文件中定义,因此const_missing只会尝试require "some_model"

答案 1 :(得分:0)

确定。你在其中一个问了很多问题。在一个答案中很难解释所有ruby和rails魔法,但我会尝试给你一些有用的资源,你可以找到一些答案。

1)关于要求声明。如果您不熟悉ruby和rails,那么很难理解rails应用程序是如何初始化的。这是一个教程,你可以得到一些有用的信息:
http://guides.rubyonrails.org/initialization.html
如果您需要有关特定方法的更多信息,可以随时查看文档。例如redirect_to方法信息:
http://apidock.com/rails/ActionController/Base/redirect_to

2)关于“使用不存在的方法”。这是称为元编程的ruby语言最美妙的特征之一。这也是高级主题。以下是一些有用的资源:
http://www.amazon.com/Metaprogramming-Ruby-Program-Like-Pros/dp/1934356476
Ruby metaprogramming online tutorial
http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/
http://rubylearning.com/blog/2010/11/23/dont-know-metaprogramming-in-ruby/

答案 2 :(得分:0)

由于现有的答案都没有提到它:是的,redirect_to之类的东西是通过ApplicationController继承的。在这种特殊情况下,redirect_to在模块ActionController::Redirecting中定义,它包含在ActionController :: Base中(ApplicationController从中继承)。