Sinatra: NoMethodError at [...] undefined method `body=' for #<String:[...]> - ruby

I got a NoMethodError when trying to return a response in Sinatra. This is the error:
NoMethodError at /contact/book-me.php
undefined method `body=' for #<String:0x00000001911418>
/home/kerrick/.rvm/gems/ruby-1.9.3-p194/gems/sinatra-1.3.2/lib/sinatra/base.rb in body
response.body = value
/home/kerrick/.rvm/gems/ruby-1.9.3-p194/gems/sinatra-1.3.2/lib/sinatra/base.rb in invoke
body res
/home/kerrick/.rvm/gems/ruby-1.9.3-p194/gems/sinatra-1.3.2/lib/sinatra/base.rb in call!
invoke { dispatch! }
/home/kerrick/.rvm/gems/ruby-1.9.3-p194/gems/sinatra-1.3.2/lib/sinatra/base.rb in call
dup.call!(env)
/home/kerrick/.rvm/gems/ruby-1.9.3-p194/gems/rack-protection-1.2.0/lib/rack/protection/xss_header.rb in call
status, headers, body = #app.call(env)
[...]
This is the relevant code:
# Snipped, but basically populate the #error hash if the form wasn't filled out right
if #error.length == 0
#Snipped, but basically handle the success case
else
#response = ''
#error.each do |x, y|
#response << "<li>#{y}</li> \n"
end
return [400, #response]
end
Why is this happening?

Using #response as your return value in Sinatra is what's causing your problem. The same problem is documented on the Ruby on Rails OldWiki, so it's not just Sinatra specific. You should change your code to look something like this and it'll work:
else
#send_errors = ''
#error.each do |x, y|
#send_errors << "<li>#{y}</li> \n"
end
return [400, #send_errors]
end

Related

ruby undefined method string for TempFile?

I have been trying to use the ticketmaster api to obtain some data. However, it throws an error when I try to run the code. I do not know why the error is popping up. I do not know if it is because of the url that I gave. Open method accept the url as string so I converted to string and this url is working in postman if I try. The exact error is
C:/RailsInstaller/Ruby2.3.0/lib/ruby/2.3.0/delegate.rb:87:in `method_missing': u
ndefined method `string' for #<Tempfile:0x28c2d50> (NoMethodError)
from test.rb:20:in `connection'
from test.rb:47:in `<main>'
and my code is ;
require 'open-uri'
require 'openssl'
require 'json'
class Test
#silence_warnings do
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE #unless Rails.env.production?
#end
def initialize()
#url="https://app.ticketmaster.com/discovery/v2/events.json?apikey=XXXXXXXXXXXXXXXXXT&city=Binghamton"
end
def connection
puts "url", #url
result=open(#url)
response_status=result.status
#putstus
if(response_status[0]=="200")
#body=JSON.parse(result.string)
puts("Status is "+ response_status[0],"Server Message is "+ response_status[1])
return #body
else
connection_error
puts("Status is ", response_status[0])
end
end
def connection_error
puts "Connection error with the api"
end
def silence_warnings
with_warnings(nil) { yield }
end
def get_content
raise notImplementedMethod
end
end
a=Test.new
a.connection

Rack middleware server crash

I am trying to write simple rack middleware like this:
class NewMiddleWare
NEW_STRING = <<BEGIN
my new content
BEGIN
def initialize(app)
#app = app
end
def call(env)
status, headers, response = #app.call(env)
response_body = ""
response.each {|part| response_body += part}
response_body += "#{NEW_STRING}"
headers["Content-Length"] = response_body.length.to_s
[status, headers, response_body]
end
end
when I run rackup, I got:
Unexpected error while processing request: undefined methodeachfor #<String:0x007fad313bdb30> in terminal.
I couldn't figure out the reason for this error. Response object
should be able to respond each right? Coz I saw some sample code doing
that.
From the Rack spec:
The Body must respond to each and must only yield String values. The Body itself should not be an instance of String, as this will break in Ruby 1.9.
In Ruby 1.8 Strings did respond to each, but that changed in 1.9.
The simplest solution would be to just return an array containing the string:
[status, headers, [response_body]]

Checking if a string is valid json before trying to parse it?

In Ruby, is there a way to check if a string is valid json before trying to parse it?
For example getting some information from some other urls, sometimes it returns json, sometimes it could return a garbage which is not a valid response.
My code:
def get_parsed_response(response)
parsed_response = JSON.parse(response)
end
You can create a method to do the checking:
def valid_json?(json)
JSON.parse(json)
true
rescue JSON::ParserError, TypeError => e
false
end
You can parse it this way
begin
JSON.parse(string)
rescue JSON::ParserError => e
# do smth
end
# or for method get_parsed_response
def get_parsed_response(response)
parsed_response = JSON.parse(response)
rescue JSON::ParserError => e
# do smth
end
I think parse_json should return nil if it's invalid and shouldn't error out.
def parse_json string
JSON.parse(string) rescue nil
end
unless json = parse_json string
parse_a_different_way
end
Let me suggest a shorter variant
def valid_json?(string)
!!(JSON.parse(string)) rescue false
end
> valid_json?("test")
=> false
> valid_json?("{\"mail_id\": \"999129237\", \"public_id\": \"166118134802\"}")
=> true

riak content_type no method error

I have the 4 node riak setup running on my os x machine. I have the following program -
require 'riak'
class RiakClient < Riak::Client
#attr_accessor :bucket
def initialize(hosts="")
return Riak::Client.new(:nodes => [{:http_port => 8091},{:http_port =>8092},{:http_port=>8093},{:http_port =>8094}])
end
def get_me(bucket, key)
obj = self.bucket(bucket).get(key)
puts obj.data
end
def put_me(bucket, key, data, content_type)
obj=self.bucket(bucket).get_or_new(key)
puts obj.class
obj.content_type=content_type
obj.raw_data=data
obj.store
end
end
if __FILE__ == $0
my_client=RiakClient.new
my_client.put_me("doc", "index.html", "some data goes here", "text/html")
hash=my_client.get_me("doc", "index.html")
end
I am getting the following error
NilClass
riak_client.rb:32:in `put_me': undefined method `content_type=' for nil:NilClass (NoMethodError)
from riak_client.rb:42:in `<main>'
Do I have to import the RiakBucket and RiakObject classes? It seems that the RiakBucket methods cannot be accessed here?
The actual question here is: why does get_or_new return nil?
It's probably because your initialize() method returns a new Riak::Client, but the Riak::Client that is your parent object never gets initialized. Try putting a call to super instead of the return Riak::Client.new in initialize.
Subclassing Riak::Client is a bit dubious here. I would tend to delegate to it instead.

Sinatra response.status in "after" filters

For some reason, in a Sinatra "after" filter I can't seem to access the current status code
require 'rubygems'
require 'sinatra'
after do
puts "After hook with code: #{response.status}"
end
get '/hi' do
halt(401, "wtf?")
end
When running curl 127.0.0.1:4567/hi, it results in:
After hook for code: 200
It's basically a function of how the methods are implemented in Sinatra. The methods we need to pay attention to are call!, invoke and dispatch!, all methods in Sinatra::Base (as of v1.3.2).
call! is the top level method, and in there, it calls the following line of code:
invoke { dispatch! }
Now, invoke looks like this:
def invoke
res = catch(:halt) { yield }
res = [res] if Fixnum === res or String === res
if Array === res and Fixnum === res.first
status(res.shift)
body(res.pop)
headers(*res)
elsif res.respond_to? :each
body res
end
end
It actually sets the response code on the basis of the thing you throw with :halt. And dispatch! looks like:
def dispatch!
static! if settings.static? && (request.get? || request.head?)
filter! :before
route!
rescue ::Exception => boom
handle_exception!(boom)
ensure
filter! :after unless env['sinatra.static_file']
end
See that ensure block? That gets run as the :halt symbol that has been thrown sails up the stack trace. Crucially, this is before the status setting code is run.

Resources