Why is Sinatra copying a route method block?

This is a more focused version of a previous question about my work around Sinatra route processing methods.

From my understanding of the source code, Sinatra takes a method block in the route and passes a new method containing the same ie body:

get "some/url" do return "Hello World" # this gets taken out end 

So, in this example, the body of the method seems to be copied to a new method that applies to the Sinatra object. I'm just wondering why this is happening, I tried to switch to my IRC channel, but no one was there and the mailing list is not so busy.

The main part of the source code that I am talking about within them is within base.rb around line 1180:

  def generate_method(method_name, &block) define_method(method_name, &block) method = instance_method method_name remove_method method_name method end 

So is there any specific reason why they do this, and not just a link to this method?

The reason I'm asking this question is because since Sinatra is currently dealing with this, it makes it impossible to have a method that has knowledge outside of itself and breaks up encapsulation of classes just by using one method without context.

+4
source share
3 answers

As in the comments above, this generates a method. The correct method. If Sinatra does not delete the method again in generate_method , you can call it by doing something like send("GET some/url") . The question is, why is Sinatra deleting this method again? Simple, there may be more than one handler per route:

 get 'some/route' do pass if request.referrer == '/foo' "didn't come from /foo" end get 'some/route' do "did come from /foo" end 

Both methods have the same name.

As for your comments about subclasses and methods, this should work:

 class MyApp < Sinatra::Base def content return "did come from /foo" if request.referrer == '/foo' "didn't come from /foo" end get('some/route') { content } end 

Or when you are running a classic application:

 helper do def content return "did come from /foo" if request.referrer == '/foo' "didn't come from /foo" end end get('some/route') { content } 
+4
source

I assume that they want to have a complete method (with access to other instance and class methods) for each route, but they don’t want to pollute the namespace. The method name is generated as "#{verb} #{path}" , so if, for example, you have several routes with different conditions for the same path collisions, this is inevitable if you do not delete the method immediately after defining and storing it in another location. And that’s exactly what they do. The method is unbound, but this is not a problem, since they can subsequently bind it to any instance of the class.

Please note this is just a hunch. I am not familiar with Sinatra, so this implementation may have a completely different idea.

+3
source

I assume it just mimics instance_exec to support Ruby older than 1.8.7

0
source

Source: https://habr.com/ru/post/1383675/


All Articles