Work on lack of context in Sinatra route methods

I had a problem with missing instances and nilClass errors when calling my routes. After going around inside the source, it seems that calling generate_method basically creates a new method using the block of the original method.

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

Thus, in the above method, there may well be a local variable inside this class called some_local_instance, however, when the actual rote evaluation has no context as to where the method was defined, so it will fail.

The reason I'm asking is because, as part of my script, I have external classes that load when Sinatra loads, that register routes and when these routes are called, I need to access some local variables in these classes. An example is:

 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 / parsing errors, this is just a quick example, but since you can see the classes register the routes and when that route hits, it returns some value generated by the calculator instance that was required when creating it.

The problem is that in this example, when I try to start / add a route, it tells me that @calculator is nilClass, and I believe that this is not the way Sinatra just takes a code block without context, It seems perfect for any simple rendering of the template, but if you need to do something more interesting or want your code to be modular without using statics and singleton, you seem to have no way around this ...

Are my assumptions correct here? and if so, then there is some way to maintain the context, because it feels that it makes me write poorly and it’s hard to maintain code if I need to write everything like static and singleton to interact with the route.

== Edit ==

I rebuilt the question and the content in order to more accurately reflect the real problem, now that I am more clearly versed in the library.

+7
source share
3 answers

I cannot accept this answer, but after doing more research, it may happen that in a dynamic language like Ruby, static classes are not like a nightmare in terms of service.

It seems that most of the major Ruby libraries work against static instances (or constants), which then use the tuning ... this still seems a little strange to me, as from the perspective of the database provider. It is very simple to simply call the static database class and connect to your database, and then start the query, however what if you need to connect to two separate databases at the same time. You will need to keep swapping servers with the same static class as troublesome.

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

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

0
source

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

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

All Articles