How does Sinatra define and invoke the get method?
It is spread out in a few places, but if you look in lib/sinatra/main.rb
, you can see this line at the bottom:include Sinatra::Delegator
If we go into lib/sinatra/base.rb
we see this chunk of code around like 1470.
# Sinatra delegation mixin. Mixing this module into an object causes all
# methods to be delegated to the Sinatra::Application class. Used primarily
# at the top-level.
module Delegator #:nodoc:
def self.delegate(*methods)
methods.each do |method_name|
define_method(method_name) do |*args, &block|
return super(*args, &block) if respond_to? method_name
Delegator.target.send(method_name, *args, &block)
end
private method_name
end
end
delegate :get, :patch, :put, :post, :delete, :head, :options, :template, :layout,
:before, :after, :error, :not_found, :configure, :set, :mime_type,
:enable, :disable, :use, :development?, :test?, :production?,
:helpers, :settings
class << self
attr_accessor :target
end
self.target = Application
end
This code does what the comment says: if it is included, it delegates all calls to the list of delegated methods to Sinatra::Application
class, which is a subclass of Sinatra::Base
, which is where the get
method is defined. When you write something like this:
require "sinatra"
get "foo" do
"Hello World"
end
Sinatra will end up calling the get
method on Sinatra::Base
due to the delegation it set up earlier.
Definition of the get method in Sinatra (Ruby)
As Simone pointed out, parentheses are optional in ruby, so your get
method can be called either with or without the parentheses.
It looks like "get" is defined optionally as {} or &block, why is that so?
The get
function takes three parameters. The first parameter is the path
, the second is a Hash with a default value of empty, and the third is a block.
Blocks in ruby can be written as {}
or as do...end
. So in both of your examples you are passing a block to the get
function
Method definition in ruby (like sinatra)
The answers can be found here: https://github.com/sinatra/sinatra/blob/master/lib/sinatra/main.rb
When you do Sinatra in its simple mode, all methods like get
or set
or post
are delegated through Sinatra::Delegator, which is defined here: https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1977 and is mixed into global scope inside main.rb
Leaving all Sinatra tricks alone, for your own module you can achieve the effect with really simple code:
module MyMixin
def testme
puts 'testme'
end
end
extend MyMixin
testme # => testme
In ruby with sinatra, How to get I response with get method on rest client?
Method 'get' from the 'RestClient' class return some object with attributes. So response have few values. Which of them do you need? Access to them you can get by their names, its described here.
In your case, after response = RestClient.get get_url...
you should have variable response
and ability to call response.headers
, response.code
or response.body
.
But im afraid that you have some problems with autorization, which means that imp_uid
or token
is not correct. Thats why remote server sended to you responce with http-code 401 (Unauthorized). If it is so you should try to check your imp_uid
and token
. If everything is correct try to reach support of iamport.kr .
how can I override sinatra's get method?
The get
method adds a route handler to the Sinatra app; it's only used for building the app during startup. When the app is up and running, the incoming HTTP requests no longer call get
, they call the internally stored proc instead. (And the same goes for post
etc.)
Based on your description, it looks like you want a before
handler - its contents will be run for every incoming HTTP request before the actual route handlers are run.
So try replacing the def get ... end
block in your code with the following:
before do
puts "URL: #{request.url} AT: #{Time.now}"
end
Then again, if you just want to log the incoming requests to the console, the easiest way is to say enable :logging
inside your class definition. See more detail here: http://www.sinatrarb.com/configuration.html
Calling a Sinatra app instance method from TestCase
Sinatra aliases the new
method to new!
before redefining it, so the simplest solution is to use that instead:
def app
MyApp.new!
end
Of course I only noticed that after I’d come up with the following, which I’ll leave in as it could be useful/informative.
A possible way to get round Sinatra redefining the new
method and returning a complete Rack app a get hold of an instance your actual base class is to do what the “real” new
method does yourself:
def app
a = MyApp.allocate
a.send :initialize
a
end
This is a bit of a hack, but it might be useful for testing.
Another technique would be to “walk” the middleware stack until you got to your class. The following is a little fragile, as it depends on all the middleware involved to use the name @app
to refer to the next app in the stack, but this is fairly common.
def app
a = MyApp.new
while a.class != MyApp
a = a.instance_variable_get(:@app)
end
a
end
That won’t work on the yet to be released Sinatra 1.4 though (at least not on the current master, which is commit 41840746e866e8e8e9a0eaafc53d8b9fe6615b12), as new
now returns a Wrapper
class and the loop never ends. In this case you can grab the base class directly from the @instance
variable:
def app
MyApp.new.instance_variable_get :@instance
end
(note this last technique may well change before the final 1.4 release).
Calling Sinatra from within Sinatra
I was able to hack something up by making a quick and dirty rack request and calling the Sinatra (a rack app) application directly. It's not pretty, but it works. Note that it would probably be better to extract the code that generates this resource into a helper method instead of doing something like this. But it is possible, and there might be better, cleaner ways of doing it than this.
#!/usr/bin/env ruby
require 'rubygems'
require 'stringio'
require 'sinatra'
get '/someresource' do
resource = self.call(
'REQUEST_METHOD' => 'GET',
'PATH_INFO' => '/otherresource',
'rack.input' => StringIO.new
)[2].join('')
resource.upcase
end
get '/otherresource' do
"test"
end
If you want to know more about what's going on behind the scenes, I've written a few articles on the basics of Rack you can read. There is What is Rack? and Using Rack.
Related Topics
How to Push a Custom Gem to Heroku Master
How to Cancel Evaluating a Required Ruby File? (A.K.A. Top-Level Return)
How Does Sinatra Define and Invoke the Get Method
Active Resource Complaining About Expects an Hash
Jekyll:New Posts Not Being Generated
How to Sort an Alphanumeric Array in Ruby
Gem Install Debugger -V '1.5.0' Fails
Error in Install Ruby-Debug-Base on Ruby 2.0.0P247
Why Capypara + Rspect Tests Still Pass Even Though I Delete Application.Js File
Iterate JSON with Ruby and Get a Key,Value in an Array
Ruby ".Downcase! " and "Downcase" Confusion
Kaminari Undefined Method 'Total_Pages'
Ruby 2.4 on MAC Os Mojave:Image Not Found ... Related to Openssl.Bundle
Bundler::Rubyversionmismatch: Your Ruby Version Is 1.9.3, But Your Gemfile Specified 2.0.0
Gem Install Therubyracer -V 0.11.4 Fails on Os X 10.10