解决Sinatra路线方法缺乏背景的问题

时间:2011-11-22 11:12:30

标签: ruby sinatra webrick

我在调用路由时遇到了丢失实例和nilClass错误的问题。在源代码中钻研之后,似乎generate_method调用基本上使用初始方法的块创建了一个新方法。

get "/" do
    @some_local_instance.do_something()
end

所以在上面的方法中,很可能在该类中有一个名为some_local_instance的局部变量,但是当实际评估死记硬背时,它没有关于方法定义位置的上下文,因此它将失败。

我问的原因是因为作为我脚本的一部分,我有外部类,当加载Sinatra时会加载哪些注册路由,当调用这些路由时,我需要访问这些类的一些局部变量。一个例子是:

class SomeRouteClass
    def initialize(sinatra, calculator)
        @calculator = calculator
        @sinatra = sinatra
    end

    def setup_routes
        @sinatra.get "/add" do
            return @calculator.add(1,1)
        end
    end
end

class Calculator
    def add(a,b)
        return a+b;
    end
end

sinatra = Sinatra.new
calculator = Calculator.new

routing_class = SomeRouteClass.new(sinatra, calculator)
routing_class.setup_routes

sinatra.run!

原谅任何拼写/语法错误这只是一个简单的例子,但正如你可以看到一个类注册路由以及当该路由被命中时返回一个由实例化它的计算器实例生成的值。

我遇到的问题是,在这个例子中,当我尝试运行/ add路由时,它告诉我@calculator是一个nilClass,我相信它可以归结为Sinatra只是在没有上下文的情况下获取代码块的方式。对于任何简单的模板渲染来说这似乎都很好,但是如果你需要做更多花哨的事情,或者想通过不使用静态和单例来保持你的代码模块化,你似乎没有办法解决这个问题......

我的假设在这里是否正确?如果是这样的话,有任何方法可以保持上下文,因为如果我必须将所有内容都写成静态和单例以便从路径进行交互,那么它就会迫使我编写糟糕且难以维护的代码。

==编辑==

重新构建问题和内容以更准确地反映实际问题,现在我对图书馆有了更深入的了解。

3 个答案:

答案 0 :(得分:0)

我可能不接受这个答案,但在做了更多研究之后,可能是在像Ruby这样的动态语言中,静态类从维护的角度来看并不像是噩梦。

似乎大多数主要的Ruby库都可以使用静态实例(或consts)来获取设置然后使用...这对我来说似乎有些奇怪,就像数据库提供者的观点一样。只需调用数据库静态类并连接到数据库然后开始查询就很容易了,但是如果需要同时连接到2个单独的数据库,该怎么办呢。您需要使用相同的静态类交换服务器,这很麻烦。

无论如何它似乎,就像答案只是为你需要暴露给路径的所有东西做一个常量,然后当你测试时只需将const设置为mock。调用这些东西似乎有点疯狂,当真正意义上它们不是真正意义上的,因为它们可以在任何时候被改变......就像许多东西对于新的红宝石开发者而言,它似乎让人感到困惑它(即elsif,@ @ blah,变量大小写,如果它的const是否定义)。

正如我所说,如果其他人可以向我展示更好的做法,我将不会接受这个答案,但目前还会再给它几天。

答案 1 :(得分:0)

传递给get的块在与Calculator对象不同的上下文中进行评估。 Sinatra可能正在呼叫instance_eval或其表兄之一。但是,应该可以使用以下(未经测试的,唉)方法从周围范围捕获局部变量:

def setup_routes
    calculator = @calculator
    @sinatra.get "/add" do
        return calculator.add(1,1)
    end
end

答案 2 :(得分:-2)

class SomeRouteClass
    def initialize(sinatra, calculator)
        @calculator = calculator
        @sinatra = sinatra
    end

    def calculator
        @calculator
    end

    def setup_routes
        @sinatra.get "/add" do
            return calculator.add(1,1)
        end
    end
end