Rails 3, Webrick, Mac OS X, Error: missing :action (ArgumentError)
I was making some changes in a routes.rb file and fat fingered the wrong line:
match '/public_html', "domains#public_html", :as => 'public'
Ran rails server, hit localhost:3000 and quickly saw a huge stack trace with this little gem of an error at the top:
/Users/miker/projects/projects/logthingy/vendor/bundle/ruby/1.8/gems/actionpack-3.0.7/lib/action_dispatch/routing/mapper.rb:171:in `default_controller_and_action': missing :action (ArgumentError)
To me, that error message is not the most helpful. Because the only change I had made was in routes.rb I knew the issue was there. By the way, this is where I feel a little bit sorry for newcomers to Ruby and Rails... The error messages are not always entirely clear. For those of us who have been in Ruby long enough to know the "breadcrumb logic" we can get by, but for those who don't it can be a nightmare.
The fix was simple and subtle... was missing some punctuation:
match '/public_html' => "domains#public_html", :as => 'public'
Two variations on Ruby array#flatten
Implement Ruby's flatten method for an Array (without taking any peaks at the source!). Probably not the hardest thing you'll ever have to do, but there are many ways to do it... Jon and I each take a blind stab at it. Here's our effort:
Mike's variation
def mikes_flatten arr, level = nil result = [] arr.each do |elem| recursive_flatten(result, elem,level,0) end result end def recursive_flatten(result, elem,level,current_level) if elem.is_a?(Array) elem.each do |el| if level.nil? || current_level < level recursive_flatten(result, el,level,current_level+1) else result << el end end else result << elem end result end
Jon's variation
def flatten values, level=-1 flat = [] values.each do |value| if level != 0 && value.kind_of?(Array) flat.concat(flatten(value, level-1)) else flat << value end end flat end
Perf different can be seen by Jon's benchmark code (flatten.rb):
#!/usr/bin/ruby require 'benchmark' # Insert flatten methods here def random_value if rand(3) < 1 (rand(5)+1).times.map { |i| random_value } else rand(10000) end end VALUE = 100.times.map { |i| random_value} ITERATIONS = 1000 Benchmark.bm do |b| puts "Iterations: #{ITERATIONS}" b.report("Mikes version") do ITERATIONS.times { |i| mikes_flatten(VALUE)} end b.report("Jons version") do ITERATIONS.times { |i| flatten(VALUE)} end end
Jon's is pretty succinct. When I first went about writing things out I was going for the "get it to work." Either way, I don't see a huge performance difference... They toggle back and forth by about a half a second.
[13:57:11 miker@laughwhat-lm ~/Downloads] $ ruby flatten.rb user system total real Iterations: 10000 Mikes version 2.920000 0.010000 2.930000 ( 2.933274) Jons version 2.990000 0.000000 2.990000 ( 3.017929) [13:57:25 miker@laughwhat-lm ~/Downloads] $ ruby flatten.rb user system total real Iterations: 10000 Mikes version 3.010000 0.010000 3.020000 ( 3.030987) Jons version 2.980000 0.010000 2.990000 ( 2.999335) [13:57:34 miker@laughwhat-lm ~/Downloads] $ ruby flatten.rb user system total real Iterations: 100000 Mikes version 26.860000 0.050000 26.910000 ( 26.973855) Jons version 24.050000 0.050000 24.100000 ( 24.126557) [13:58:34 miker@laughwhat-lm ~/Downloads] $ ruby flatten.rb user system total real Iterations: 100000 Mikes version 24.120000 0.050000 24.170000 ( 24.201227) Jons version 25.080000 0.050000 25.130000 ( 25.196811)
Write your own and submit as a comment. Let's see some other ways to do this
Releasing LogThingy.com, a Domain Manager/Content Server
This last weekend was filled with a hackishly fun project: build a rails app that can route domain names to dynamically generated html content. The need arose from having too many domains and them being parked all over the place. I needed something all-inclusive. Ideally, a web site that lets me add newly parked domains and serve up the full html page creation dynamically.
Thus began a journey lasting about one week. Monday of last week I embarked to build said application and can report back today that I have launched it to a production environment, still in early beta stages. LogThingy.com, for lack of a better name, is a domain social network with content-parking capabilities. You can add domain names to your account, we'll fetch all the name servers and expiration details, and then once your domain is parked onto my server the application will begin serving requests to that domain the html that you've stored.
This is an invite-only pre-release. There are numerous feature gaps, but things are running stable and you can see the net result by visiting some of the domains: synced.org, comparestrains.com, logthingy.com, answerwise.com
All domains serve a standard "Coming Soon" image unless content has been defined via the backend. You'll see LogThingy.com is a "Coming Soon," while the other domains have content (albeit slim). Thoughts and feedback welcome. Here are some screenshots of what things look like..
More updates to come =) Oh, and don't forget about SimplyFor.US, updates were just rolled out over there.
Hanging in the Treetops
I wanted to find a way to parse short urls without making any database calls. Since I have a pattern for short urls I figured, for a bit of fun, a parser would make this possible.
Enter Treetop: "Treetop is a language for describing languages. Combining the elegance of Ruby with cutting-edge parsing expression grammars, it helps you analyze syntax with revolutionary ease." Treetop
The grammar defined is straight forward: (FILE: message_grammar.treetop)
grammar MessageGrammar rule message [0-9] / 'X' message / ('Y' / 'Z') message message end end
So here are some valid codes: 0, X0, XY00, XX0, XY09
Invalid codes: T0, P, PPPPP0, X0X0X00
Make sure you've got treetop installed. Drop into terminal in the directory of the grammar file and run
tt message_grammar.treetop
This will result in a file called message_grammar.rb which you can include in another file to use as your parser...
File: message_parser.rb
require "rubygems" require "treetop" require "polyglot" require "message_grammar" # MessgeGrammarParser is a generated Parsing class based on the grammar # defined in message_grammar.treetop parser = MessageGrammarParser.new STDIN.each do |string| # for each string, split on whitespace string.split(" ").each do |message| # print status of whether the message could be parsed or not puts "#{message} #{parser.parse(message) ? 'VALID' : 'INVALID'}" end end
And we're Done-zo Washington. Parse away.







