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

调用路由时,我遇到了丢失实例和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在没有上下文的情况下获取代码块的方式。 对于任何简单的模板渲染来说这似乎都很好,但是如果你需要做更多花哨的事情,或者想要通过不使用静态和单例来保持代码模块化,那么你似乎没有办法解决这个问题……

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

==编辑==

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

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

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

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

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

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

 def setup_routes calculator = @calculator @sinatra.get "/add" do return calculator.add(1,1) end end 
 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