The ever useful rack-test gem let’s you easily integration test any rack project. All you have to do is include the Rack::Test::Methods and define an app method that returns your rack app. So people usually have a config.ru that just references their my_application.rb that they reference in their config.ru and then in their test file they can also reference that app and return it. Something to to this effect:
1 2 3 4 5 |
class MySweetRackApp
def initialize
Proc.new { |env| [200, {‘Content-Type’ => ‘text/html’}, [‘success’]] }
end
end
|
I had a project where I was actually trying to better breakdown a more complex app, and I wanted to just be able to use Rack’s built-in map method at the top level of my config.ru to route to different apps. And in at least some of the cases I wanted to be able to test the whole thing. Also, I figured sometimes it’s useful to actually be able to test your rackup file itself, all routing/mapping included. So I dug around in the rack code and found how the rackup command handles the .ru file, and came up with this:
If you use an authenticated_system on your Rails site, with global before_filters for things like requiring login to access pages, be careful of missing formats in the respond_to. I just tracked down a bug on an app where we were getting DoubleRenderErrors because of unauthenticated request directly to a csv file. We had a before_filter that was denying request and redirecting them to login, in different ways, depending on the format, but hadn’t thought to include csv. In this case, it is wise to include a catch-all at the end using .any
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
def anon_access_denied
respond_to do |accepts|
accepts.html do
store_location
redirect_to login_path
end
accepts.xml do
headers[“Status”] = “Unauthorized”
headers[“WWW-Authenticate”] = %(Basic realm=”Web Password”)
render :text => “Could’t authenticate you”, :status => ‘401 Unauthorized’
end
accepts.js do
render(:update) { |page| page.redirect_to login_path }
end
end
end
|
Apparently when using the three standard pipes (stdin, stdout, stderr)
in your own programming, it is REALLY easy to block or deadlock on
them. At first I figured there were problems in the ruby *open3
library, but this is not ruby specific, I found message board
discussions about similar problems using perl open3 libraries.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #http://github.com/ahoward/open4 is an alternative that handles pid and exit status
#http://github.com/ahoward/session a more fleshed our shell utility
require ‘open3’
Open3.popen3(“dc”) do |stdin, stdout, stderr|
t = Thread.new(stderr) do |terr|
while (line = terr.gets)
puts “stderr: #{line}”
end
end
puts “pushing 5 to stack”
stdin.puts(5)
puts “pushing 10 to stack”
stdin.puts(10)
puts “pushing + to stack”
stdin.puts(”+”)
puts “sending print command”
stdin.puts(“p”)
result = stdout.gets
puts “stdout: #{ result }”
puts “\ntrying an unsupported command”
stdin.puts(“b”)
extra_info_not_in_stderror = stdout.gets
puts “stdout: #{extra_info_not_in_stderror}”
puts “\nclosing stdin to avoid deadlock with stderr”
stdin.close
# puts “let’s give stderr a chance to run”
# t.run or sleep 1
puts “joining”
t.join
end
|
1 2 3 4 5 6 7 8 9 | #javac HelloWorld.java && jar cvf HelloWorld.jar HelloWorld.class
require ‘java’
require ‘HelloWorld.jar’
import ‘HelloWorld’
puts HelloWorld.new.hello
#=> “Hello cruel world”
#jruby hello_world.rb
|
If you are on Rails 2.3.x (pre-Bundler) and want to organize some of your shared functionality into gems, but they are for internal use only, you could set-up a private gem server and point the :source at this server. And then you could deal with authentication, and then…
Or as a quick hack you could just allow for config.gem to reference the gemfile directly, which would then mean ‘rake gems:install’ would work, even if the gem were stored locally, or on a file-server, etc. Also useful as you could then just point at a .gem file on github.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ## require in config/environment.rb before init starts
#require ‘config/add_explicit_path_to_config_gem’
#Rails::Initializer.run do |config|
#config.gem ‘my_gem’, :version => ‘0.0.1’, :explicit_path => “#{RAILS_ROOT}/vendor/local_gemfiles/my_gem-0.0.1.gem” #or
#config.gem ‘my_gem’, :version => ‘0.0.1’, :explicit_path => “http://github.com/myname/myrepo/raw/master/mygem.gem” #or
module Rails
class GemDependency
def initialize_with_explicit_path(name, options = {})
@explicit_path = options[:explicit_path]
initialize_without_explicit_path(name, options = {})
end
alias_method_chain :initialize, :explicit_path
private
def install_command
cmd = %w(install) « (@explicit_path || name)
cmd « “—version” « %(“#{requirement.to_s}”) if requirement
cmd « “—source” « @source if @source
cmd
end
end
end
|
If you have a Rails metals that has enough code to have its own subdirectories that live in your Rails load_paths you can get stuck in dependency hell. The combinations of autoloading, rails reloading on development, and running through the metal can intersect in nasty ways: on the first request you get “Object is not missing constant XXX” and subsequent requests kick off “A copy of YYY has been removed from the module tree but is still active.”
The easiest solution is to kill magic reloading for this metal’s code by adding the metal’s directories of code to the Rails load_once_paths and then using explicit require_dependency calls for any files that give you trouble. For example, I have a MadMetal that referenced a Mad which has a whole sub-directory structure of code that, for now, lives under lib/mad:
#config/environment.rb config.load_once_paths += Dir["#{RAILS_ROOT}/lib/mad/**/"] #app/metal/mad_metal.rb require_dependency 'mad' class MadMetal def self.call(env) if (env["PATH_INFO"] == '/the_path_to_my_metal') Mad.call(env) else [404, {"Content-Type" => "text/html"}, ["Not Found"]] end end end And wallah, no more conflicts between development auto-reloading and metal.
Of course, now you need to restart the server if you change code in lib/mad. In this case it’s not a problem for me because the app is also a stand-alone rack app that I run with shotgun when I want development environment reloading.
So my buddy Tammer’s recent post about the Gang of Four’s Template Pattern reminded me of some code I saw recently. A start-up’s greenfield project had it’s authorization done in a pretty clean way using the template pattern. Basically every object determined what could be done to it, something like this:
After continuing this approach to fully cover CRUD you make a straight-forward set of accessors that can be used to easily enforce permissions in the controller in a programmatic way (this project was using on of the inherited resourceful-controller plugins, so that was a big plus). The developer who implemented this commented that the trade-off for this simplicity was having to look in each individual model file to figure out what a user can do overall. I figured I liked everything about this scheme except that trade-off, and since ruby is so dynamic, why settle for almost. Why not just reopen each class in the authorization file and add the methods. You still get the simplicity and encapsulation of having the model able to determine it’s own permissions, based on it’s state and methods, and there is still one place to look to review/change the permissions for the whole project:
Thoughts?
http://github.com/blog/543-new-resque-web-ui
http://github.com/defunkt/resque
Yet another queuing system, but I do like the look of the included
Sinatra mini-app for managing it. And isn’t redis all the hot thing
now? Or is that a negative?
Or the wrong one. It just seems like over-inheriting is definitely one of the bigger maintainability nightmares I have had; and pulling the constructor entirely into the parent…. Well it better be exactly the parent, and cleanly done.
It’s like those overly abstracted resource_controllers. They seem like a great idea, but once you start deviating at all, you spend more code and more time thinking about how to write that code to get out of the straight-jacket over over-inheritance than you would have had in the first place.
I’m starting to feel that while abstract constructors *can* be done right they are often are a smell. Compare these three approaches and let me know what you think: