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

[英]Working around the lack of context in Sinatra's route methods


I have been having an issue with missing instances and nilClass errors when calling my routes. After delving around within the source it seems like the generate_method call basically creates a new method using the block of the initial method.

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

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

So in the above method there could very well be a local variable within that class called some_local_instance, however when the rote is actually evaluated it has no context as to where the method was defined, so it will fail.

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

The reason I ask is because as part of my script I have external classes which are loaded when Sinatra is loaded which register routes and when those routes are called I need to access some local variables on these classes. An example would be:

我问的原因是因为作为我的脚本的一部分,我有外部类,当加载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!

Forgive any spelling/syntax mistakes this is just a quick example, but as you can see a class registers routes and when that route is hit returns some value generated by an instance of the calculator it took when it was instantiated.

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

Problem I have is that in this example when I try and run the /add route it tells me that @calculator is a nilClass, and I believe it to be down to the way that Sinatra just takes the block of code without context. This seems fine for any simple template rendering, but if you need to do anything more fancy, or want to keep your code modular by not using statics and singletons you do not seem to have any way around this...

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

Are my assumptions correct here? and if so is there any way to keep context as it feels like it is forcing me to write bad and hard to maintain code if I have to write everything as statics and singletons to interact from a route.

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

== Edit ==

==编辑==

Have restructured the question and content to more accurately reflect the actual problem, now that I have a firmer understanding of the library.

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

3 个解决方案

#1


0  

I may not accept this answer, but after doing more research it may be that in a dynamic language like Ruby static classes are not such as nightmare from a maintenance point of view.

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

It seems that most major Ruby libraries work against static instances (or consts) which get setup then used... this does still seem a little odd to me, as in a database provider point of view. It is very easy to just call your database static class and connect to your database and then start querying, however what if you need to connect to 2 separate databases at the same time. You would need to keep swapping servers with the same static class which would be troublesome.

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

Anyway it seems at the moment like the answer is just make a constant for everything you need to expose to a route, then when you are testing just set that const to a mock. It still seems a bit crazy calling these things consts, when really they are not consts in the true sense of the word as they can be changed at any time... like many things to new ruby developers it just seems confusing for the sake of it (i.e elsif, @@blah, variable case defining if its const or not).

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

As I said I will not accept this answer if someone else can show me a better pattern of doing this, but for the moment will give it a few more days.

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

#2


0  

The block passed to get is evaluated in a different context than the Calculator object. Sinatra is probably calling instance_eval or one of its cousins. However, it should be possible to capture local variables from the surrounding scope, using something like the following (untested, alas) approach:

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

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

#3


-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

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.silva-art.net/blog/2011/11/22/146b2478d7ba3b6f099a575cb79660dd.html



 
© 2014-2018 ITdaan.com 粤ICP备14056181号