I have a sinatra app that is using thin as it's web server. I interact with my database via ActiveRecord.
If in an endpoint, I do this:
get '/test' do
Model.create(.....)
end
Does the Model.create(.....) block the event loop (thin uses eventmachine internally)? If so, how bad is this and what are the alternatives?
Thanks
My understanding is that thin is threaded by default, unless you disable that. So your request handler can be executed asynchronously using Eventmachine::Defer.
Yes, as the comment by #user2246674 says, if your handler is executed in the reactor thread then it will block everything.
As to the alternatives, I just searched Google for ActiveRecord and Eventmachine and the first hit was this post with some code: http://www.mikeperham.com/2010/03/30/using-activerecord-with-eventmachine/. You might find it useful to take a look at "em-synchrony": https://github.com/igrigorik/em-synchrony that has support for ActiveRecord.
Here is also my own question on a related subject: async requests using sinatra streaming API There I use Sinatra's streaming API to implement asynchronous request processing.
I personally would use direct DB access from my Sinatra app. That is what I always do. ActiveRecord is too heavy for me.
Yes, it does block. If you are on Mysql you can make requests using mysql2 gem, it supports async requests.
https://github.com/brianmario/mysql2
Related
I'm using capybara-webkit to test integration with a third party website (I need javascript).
I want to use vcr to record requests made during the integration test but capybara-webkit doesn't go over net http so vcr is unable to record them. How would I go about writing an adaptor for vcr that would allow me to record the reqeusts?
Unfortunately, VCR is very much incompatible with capybara-webkit. The fact is that capybara webkit is using webkit, which is in c. Webmock and Fakeweb, which are the basis for VCR, can only be used for Ruby web requests. Making the two work together would likely be a monumental task.
I've solved this problem two ways:
The first (hacky, but valid) is to add a new javascript file to the application that is only included in the test environment. This file stubs out the JS classes which make external web requests. Aside from the pure hackatude of this approach, it requires that every time a new request is added or changed you must change the stubs as well.
The second approach is to route all external requests through my own server, effectively proxying all external requests through my server. This has the huge disadvantage that you have to have an action for everything you want to consume (you could genericize it, with some work). It also suffers from the fact that it could as much as double the time for the request to complete. However, since the requests are now being made by Ruby you can use VCR in all it's glory.
In my situations, approach #2 has been much more to my advantage thanks to the fact that I need ruby to manipulate the data so that I can keep my javascript source-agnostic. I was, however, using approach #1 for quite a while successfully.
I've written a small ruby library (puffing-billy) for rspec+capybara that does exactly this -- it injects a proxy in between your browser and the outside world and allows you to fake responses to specific requests.
Example:
describe 'fetching badges from stackoverflow API' do
it 'should show a nice message when you have no badges' do
# stub some JSONP
proxy.stub('http://api.stackoverflow.com/1.1/users/1/badges',
:jsonp => { :badges => [] })
visit '/my_badges'
page.should have_content("You don't have any badges :(")
end
end
We're using NewRelic to monitor a Sinatra app. We don't want the probe URL varnish uses to check if the app is online to be instrumented by NewRelic. How do we tell NewRelic to ignore a certain Sinatra route? (The documentation only seems to refer to how to do this in Rails: https://newrelic.com/docs/ruby/blocking-controller-instrumentation)
You could try calling NewRelic::Agent.abort_transaction! within the code path for the probe request. See the API docs for details.
Have you tried what their docs suggest https://newrelic.com/docs/ruby/sinatra-support-in-the-ruby-agent
newrelic_ignore '/ping'
As of version 3.6.3 of the NewRelic gem, you can should be able to use the 'newrelic_ignore' method to ignore endpoints. If you are using Sinatra, you may need to call this class method explicitly, like so:
NewRelic::Agent::Instrumentation::Sinatra::newrelic_ignore('/route/to/ignore')
But, it doesn't work as expected. I am filing a bug report with NewRelic.
I wrote my own FaceBook library that uses actual Curl requests, not libcurl.
Is there a way to test it? I'm asking this because most solutions involve using something like fakeweb which as far as I can tell will not work here.
The existing code can be found on my github page.
One approach would be to use a different host/port in test mode (eg localhost:12345)
Then in your test run a sinatra or webrick servlet on that port that you configure to respond to the requests your code should be making
You could mock Request.dispatcher with an expected behavior, pretty much like Fakeweb would do.
There are a few examples on this file, specially https://github.com/chrisk/fakeweb/blob/master/lib/fake_web/ext/net_http.rb#L44.
When running your tests/specs, monkey-patch the run method of your Request class to hook into the Marston VCR library. See the existing library_hooks subdir for examples and ideas on how to do this -- the fakeweb implementation is a good place to start.
VCR works well with live services like Facebook's because it captures interactions "as is", and VCRs can be easily re-recorded when the services change.
I'm running into problems with your library, however. You need to require the cgi and json libraries; it also looks like it requires a Rails environment (it's failing to find with_indifferent_access on Hash).
What framework do you recommand for writing simple web applications in ruby, between WebRick, Mongrel and Sinatra ?
I would like to answer in json to requests from a client. I would like to have my own code decoupled from the Http framework as much as possible.
Do you know any other framework ?
I wouldn't recommend using WEBrick, period. You would best be served by a Rack-compatible framework. You could write directly in Rack for speed, but it's really unnecessary since Sinatra is so much more pleasant and still very fast.
You may also want to check out Halcyon. I don't know if it's still maintained, but it's designed for writing APIs that respond in JSON.
WEBrick and Mongrel are servers, not frameworks for building web applications. As such, they have APIs that are lower level and tied to their own idiosyncrasies which makes them a bad place to start if you want to design your web application so that it can run on different servers.
I would look for a framework that builds on Rack, which is the standard base layer for building web apps and web frameworks in Ruby these days.
If you are making something really simple, learning Rack's interface by itself is a good place to start.
E.G., a Rack Application that parses json out of a post request's body and prints it back out prettified.
# in a file named config.ru
require 'json'
class JSONPrettyPrinterPrinter
def call env
request = Rack::Request.new env
if request.post?
object = JSON.parse request.body
[200, {}, [JSON.pretty_generate(object)]]
else
[200, {}, ["nothing to see here"]]
end
end
end
run JSONPrettyPrinterPrinter
you can run it by running rackup in the same dir as the file.
Or, if you want something a bit more high level, you can use sinatra, which looks like this
require 'sinatra'
post '/' do
object = JSON.parse request.body
JSON.pretty_generate(object)
end
Sinatra's README is a good introduction to it's features.
Im developing a ruby API library for some web application (not rails based).
Library (in short overview) consists of the following objects:
Client - main api class
Request - module that handles all data transfers
Item (record) - object with attributes (result of api operations)
Im having a hard time figuring out whats the best way to test such libraries?
Currently using RSpec2 and actual (live) requests. But also might use fixtures.
Any suggestions?
You can use WebMock to mock requests. It has RSpec helpers to aid you in your tests.
I haven't personally used WebMock, but once used Fakeweb to accomplish a similar task. The only disadvantage of using mock requests is that if the remote code changes,