2011-11-22 56 views
7

缺乏背景下的叫我的路由时,我一直有缺失情况和nilClass错误的问题。在源代码中进行深入研究后,似乎generate_method调用基本上使用初始方法的块创建了一个新方法。工作围绕Sinatra的途径方法

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

所以在上面的方法有很可能是该类称为some_local_instance内的局部变量,但是当死记硬背实际上是评估它没有上下文来定义的方法,其中,所以它会失败。

我之所以这样问是因为我的脚本的一部分,我有西纳特拉时加载哪个寄存器路线,当这些路由是我需要访问这些类的一些局部变量被加载外部类。一个例子是:

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! 

原谅任何拼写/语法错误,这只是一个简单的例子,但你可以看到一个类注册路线,当这条路被击中返回该计算器的情况下产生一定的价值它在实例化时花费了。

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

我的假设在这里正确吗?如果是的话有没有什么办法让上下文感觉它逼着我写的不好,难以维护的代码,如果我有写的一切,静态和单身从路由交互。

== ==编辑

已经重构的问题和内容,以更准确地反映实际的问题,现在我有库的一个更稳固的理解。

+1

通过源多一些期待之后,它似乎不只是复制和粘贴与使用define_method的新路径一起使用的方法。所以这个方法之外没有任何背景......这意味着唯一的解决办法就是将所有东西都变成静态的,这似乎是错误的......因为它很难以这种方式进行改变和测试......我可以完全虽然Ruby对我来说仍然是一种新语言,但它错误地做了什么。 – Grofit

+0

一直试图使用常量对象模式来解决这个问题,但这仍然使事情真的很讨厌,因为一切都必须是静态的,这样才能工作...是否有一个原因,他们将方法体复制到一个新的方法所以它失去了所有的情况?因为我看不到任何好处,只是缺点...虽然我对此还是很陌生,因此可能无法完全理解某些需要这样做的复杂因素。我只能想到的一点是,方法主体对象可能被清除,或者方法可能在被调用之前被更新或从实例中取走,但看起来不太可能 – Grofit

回答

0

我不能接受这个答案,但这样做更多的研究后,它可能是在像Ruby静态类的动态语言都没有,如从一个维修点的噩梦。

看来,最重要的Ruby库对静态实例(或consts),它得到的设置,然后使用工作......这确实还显得有些奇怪了吧,如在查看数据库提供商点。只需调用数据库静态类并连接到数据库然后开始查询是非常简单的,但是如果您需要同时连接到2个独立的数据库,该怎么办?你需要继续使用相同的静态类来交换服务器,这很麻烦。

无论如何它似乎此刻的答案只是使你需要暴露给路线的所有东西都保持不变,然后当你正在测试时,只需将该常量设置为模拟。它似乎仍然有点疯狂调用这些东西consts的时候,确实他们不是在这个词的真正意义上的consts,因为他们可以在任何时候改变......像许多事新Ruby开发者似乎只是为了贪图混乱它(即elsif,@@ blah,变量大小写是否定义)。

正如我所说的,我不会接受这个答案,如果别人能告诉我这样做的更好的模式,但目前将会给它几天。

+0

它看起来像使用助手,你可以把一些逻辑内,但仍然不觉得很好。我在看Padrino,因为它至少提供了一个控制器和每个控制器助手的外观,更好地封装了你的数据和逻辑,但是这些都是建立在sinatra之上的,所以必须有能力在默认的Sinatra版本。 – Grofit

-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 
+1

导致异常:未定义的局部变量或方法'计算器'为#<#:0x29c9a60>,我看到你在那里试图做什么,但它仍然看起来很奇怪。正如当你注册PATTERN-X的时候你所说的一条路线叫做METHOD-Y,但是Sinatra是否会采取这种方法,并且围绕它进行分类?所以它不再具有该方法之外的范围的任何上下文? – Grofit

0

传递到get的块在与Calculator对象不同的上下文中进行评估。 Sinatra可能会拨打instance_eval或其堂兄弟。然而,应该可以从周围的范围捕捉局部变量,使用类似以下的(未经测试,唉)做法:

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