For me, the upper limit of acceptable commute time is 10 minutes, but a longer commute time does give me time to think up of things while navigating a familiar route. One such idea came from a sudden desire to write a book. Having gotten Stanza for my iPod, and having a mind that cross-links ideas together like an encyclopedia, I'd want to publish it via epub and on a MediaWiki platform. I'm getting too old for copy-and-paste editing, so having a source document written in ERB would be ideal. In fact, I even got as far as a vague notion of using Nokogiri and/or XML as some sort of intermediate representation.
Turns out, while (as usual) searching for something completely unrelated, I found that someone has already implemented this tool: http://snk.tuxfamily.org/lib/erbook/.
Tuesday, July 6, 2010
Friday, June 25, 2010
Stealing Let from Rspec
Since Rspec 1.3, you could define variables in example groups that cascaded down, thus more or less eliminating the need for a before block. You do this by calling let(). By defining them with the right words, the spec code gets simplified and reads more naturally. I found it weird that it would be named after something I kept seeing around in Lisp, so I looked it up and found this. I did not understand it at all. When I cracked open the Rspec, I found an absurdly simple implementation: the Let module defines a memoized method when you call let. Since Rspec 2 breaks up examples into their own class, you get the cascading effect simply from Ruby inheritance and scoping. Dead simple. Most of the text in that file is actually documentation.
This memoized patterns happens all over the place. One example is in inherited_resources:
The neatest thing I had found about let() in Rspec was easily making an implicit DSL inside my spec. The fact that I can carry this over to my controller is simply too cool not to share.
This memoized patterns happens all over the place. One example is in inherited_resources:
I have some similar code, but since I am working on a pure web service project, I'm not actually using any assigns. But the technique is similar. inherited_resource calls out methods that are sensible defaults most of the time. To customize it, you would override one of several of the hooks, such as object, collection, end_of_association_chain. But this looks a lot nicer using the let() syntax:
class ProjectsController < InheritedResources::Base
protected
def collection
@projects ||= end_of_association_chain.paginate(:page => params[:page])
end
end
class ProjectsController < InheritedResources::BaseAnd then I dropped this into app/concerns. This was actually extracted from my (working) Rails 3 web services project:
include Let
let(:collection) { @projects ||= end_of_association_chain.paginate(:page => params[:page]) }
end
# http://gist.github.com/453389I stole this from Rspec 2, then ripped out the documentation and refactored it using ActiveSupport::Concern. I added a line to make the let() bindings protected so it won't show up as an action for the controller. This is probably the behavior you'd want in non-controller anyways.
module Let
extend ActiveSupport::Concern
included do
extend Let::ClassMethods
end
private
def __memoized # :nodoc:
@__memoized ||= {}
end
module ClassMethods
def let(name, &block)
define_method(name) do
__memoized[name] ||= instance_eval(&block)
end
protected(name)
end
end
end
The neatest thing I had found about let() in Rspec was easily making an implicit DSL inside my spec. The fact that I can carry this over to my controller is simply too cool not to share.
Thursday, June 24, 2010
Friday, June 11, 2010
Remarkable 4.0.0.alpha4
Rails 3.0 Beta4 is out! and thanks to Louis T. we have released a alpha4 that tracks Rails 3.0 Beta4. You will need to run RSpec 2.0 alpha11 in order to run this version.
As usual, remarkable/rails does not work. I know a lot of people have asked for this. I personally don't have a need for those macros, though there are a few who looks like they are stepping up to the plate. If you want an alternative, I highly recommend looking at the Rspec let feature which lets you do much of the same thing, minus i18n. I may publish a remarkable/rack, or at least, publish a blog post on how to do it with let. If you have not already, I highly recommend looking at the Pure RSpec slides.
As usual, remarkable/rails does not work. I know a lot of people have asked for this. I personally don't have a need for those macros, though there are a few who looks like they are stepping up to the plate. If you want an alternative, I highly recommend looking at the Rspec let feature which lets you do much of the same thing, minus i18n. I may publish a remarkable/rack, or at least, publish a blog post on how to do it with let. If you have not already, I highly recommend looking at the Pure RSpec slides.
Changes
- The only real change was a fix for validate_numericality_of resulting from a patch submitted for Beta4. It is Rails #4406 if you are curious.
Tuesday, June 8, 2010
Remarkable 4.0.0.alpha3
Remarkable 4.0.0.alpha3 has been released, thanks to João Vitor and Louis T..
Changes
- alpha3 requires Rspec 2.0.0.alpha11
- In keeping with Rspec 2.0.0.alpha11, the module Rspec was changed to RSpec
- This required changes in the i18n localization files. You will now need to use r_spec instead of rspec
- {{}} was changed to %{} as per deprecation warnings in the i18n gem
- A Gemfile is used for the convenience of developers to install the required gems. However, we are not (yet) using Bundler.require
Wednesday, May 26, 2010
Remarkable 4.0.0.alpha2
Remarkable 4.0.0.alpha2 now released. This release reorganizes and simplifies loading of the component. Here's how you install it:
This release also fixes the bug in alpha1 where the English localization was not properly loading for remarkable/active_model.
Requiring remarkable/active_record should automatically require remarkable/active_model, which should in turn require remarkable. The version dependencies themselves are described in the gemspec file. Further, users should just be able to require a single file without having to mess with Remarkable.include_matchers! to get things done.
By moving the files from remarkable/lib/remarkable to remarkable/lib/remarkable/core, it opens it up developers to add to the remarkable namespace. For example, we can have a require 'remarkable/foreigner' by making a lib/remarkable/foreigner.rb inside the gem and dropping the rest of the files into lib/remarkable/foreigner/.
Instead of using lines such as
But how do we avoid loading the system gems when we want to run tests? We throw custom load paths into $LOAD_PATH or its alias, $:
For details, see remarkable_activemodel and remarkable_activerecord for examples on how the loading is done.
Add Remarkable to your Gemfile:sudo gem install remarkable_activerecord --pre
In spec/spec_helper.rb add:group :test do
gem 'rspec', '>= 2.0.0.alpha7'
gem 'rspec-rails', '>= 2.0.0.alpha7'
gem 'remarkable', '>=4.0.0.alpha2'
gem 'remarkable_activemodel', '>=4.0.0.alpha2'
gem 'remarkable_activerecord', '>=4.0.0.alpha2'
end
If you just want Remarkable core, use:require 'rspec/rails'
require 'remarkable/active_record'
If you just want Remarkable::ActiveModel, use:require 'remarkable/core'
All locales inside the gem are now automatically loaded. So if anyone wants to provide a translation for say, Traditional Chinese, feel free to fork and send a pull request.require 'remarkable/active_model'
This release also fixes the bug in alpha1 where the English localization was not properly loading for remarkable/active_model.
Changes for Macro Developers
Although I wrote about improving macro registration, I googled around some more and found "Gem Packaging: Best Practices". The system I was proposing would overlap the functionality of Rubygems and Bundler (in so far as dependency checking). It would have been over-architected.Requiring remarkable/active_record should automatically require remarkable/active_model, which should in turn require remarkable. The version dependencies themselves are described in the gemspec file. Further, users should just be able to require a single file without having to mess with Remarkable.include_matchers! to get things done.
By moving the files from remarkable/lib/remarkable to remarkable/lib/remarkable/core, it opens it up developers to add to the remarkable namespace. For example, we can have a require 'remarkable/foreigner' by making a lib/remarkable/foreigner.rb inside the gem and dropping the rest of the files into lib/remarkable/foreigner/.
Instead of using lines such as
we just have# Load Remarkable ActiveModel files[ src ]
dir = File.dirname(__FILE__)
require File.join(dir, 'remarkable_activemodel', 'base')
# Load Remarkable[ src ]
require 'remarkable/core'
require 'remarkable/active_model/base'
But how do we avoid loading the system gems when we want to run tests? We throw custom load paths into $LOAD_PATH or its alias, $:
To help load these paths, I've added a path_helpers.rb that you can take a look at.
# In spec/spec_helpers.rb
$:.unshift(File.dirname(__FILE__), '..', 'lib')
For details, see remarkable_activemodel and remarkable_activerecord for examples on how the loading is done.
Tuesday, May 18, 2010
The knife is out for ruby ... ORLY?
Warning: Link Bait
From Hacker News, comes "The Knife is out for Ruby". "Dynamic languages are coming to the end of their honeymoon period. This is bad for Python and maybe PHP, but it is nothing short of a disaster for Ruby."
... leaving aside the religious war of Static vs. Typed language, how about viewing this from the point of view of Pragmatic Extropy?
... X is better because it is more challenging to work with. Does that mean that the programmer has to be smarter?
... X is better because it forces you to think through about issues Y?
Scrolling down to the comments, the author reveals a bit about himself:
I was talking to folks on #pragmatic_extropy about my experience geocaching with a friend. I watched my friend get so dependent on the GPS, missing out obvious environmental cues and clues. I promised myself that I wouldn't do that if I held the GPS in my hand. My friend got a call and handed me to the GPS, and within five minutes, he was pointing out cues I missed because I was navigating with the GPS.
The GPS had easily become an extension. The neural net of the brain adapts to the external interface, in which the external interface becomes part of the complete circuit. There's a paper written about the phenomena of two neural nets forming an internal language idiosyncratic to those two particular neural nets. You can see it in two intimately-close people who have been around each other for a long time. Likewise, I remember an article about how family groups would socially (and unconsciously) assign specialty knowledge to specific family members. The same is true for any tool we use -- tab completion on the command line for example. I don't feel right without being able to hit the tab key since I remember filenames more on the first few letters and the number of tabs I have to hit. Other tools include code snippets, VIM cursor controls, distributed version control ... and IDE-based type inference and whatnot.
Some languages, however, such as Lisp, has the rare ability to transform how we think because the language is powerfully expressive enough. Its power derives from having very little syntax and does not require external tools to grok. Someone programming in .NET, for example, require an IDE to be productive because the IDE forms the complete neural circuit. Something like Lisp (within certain cases) has the complete neural circuit held inside the head. There is more transformative value for a Lisp-user than a .NET-user, even with a better IDE. While it can be argued that the IDE closes the gap in terms of productivity, it does not close the gap in terms of arete, though it may go with the grain of extropy.
From Hacker News, comes "The Knife is out for Ruby". "Dynamic languages are coming to the end of their honeymoon period. This is bad for Python and maybe PHP, but it is nothing short of a disaster for Ruby."
... leaving aside the religious war of Static vs. Typed language, how about viewing this from the point of view of Pragmatic Extropy?
"Type safe static languages like C#, Java and Managed COBOL are much more challenging to work with, or at least they were."
... X is better because it is more challenging to work with. Does that mean that the programmer has to be smarter?
"However, the gap is closing or may have completely closed. Type inference, generics and much better IDEs have made static languages really easy to work with. The permissive nature of dynamic languages is only really treating the symptom that programmers do not want to have to remember and key-in everything's type."
... X is better because it forces you to think through about issues Y?
Scrolling down to the comments, the author reveals a bit about himself:
"My day job is in a compiler writing team. I spend a lot of time in a lot of different languages. My view is that dynamic languages make sense for code bases which do no justify heavy tooling and which are not going to be around for a very long time. I used to think that dynamic languages were a lot more useful than that because of productivity - but recent advances in IDEs and type systems have convinced me that even if it is not the case now, over the next few years the difference in productivity will diminish a lot."
I was talking to folks on #pragmatic_extropy about my experience geocaching with a friend. I watched my friend get so dependent on the GPS, missing out obvious environmental cues and clues. I promised myself that I wouldn't do that if I held the GPS in my hand. My friend got a call and handed me to the GPS, and within five minutes, he was pointing out cues I missed because I was navigating with the GPS.
The GPS had easily become an extension. The neural net of the brain adapts to the external interface, in which the external interface becomes part of the complete circuit. There's a paper written about the phenomena of two neural nets forming an internal language idiosyncratic to those two particular neural nets. You can see it in two intimately-close people who have been around each other for a long time. Likewise, I remember an article about how family groups would socially (and unconsciously) assign specialty knowledge to specific family members. The same is true for any tool we use -- tab completion on the command line for example. I don't feel right without being able to hit the tab key since I remember filenames more on the first few letters and the number of tabs I have to hit. Other tools include code snippets, VIM cursor controls, distributed version control ... and IDE-based type inference and whatnot.
Some languages, however, such as Lisp, has the rare ability to transform how we think because the language is powerfully expressive enough. Its power derives from having very little syntax and does not require external tools to grok. Someone programming in .NET, for example, require an IDE to be productive because the IDE forms the complete neural circuit. Something like Lisp (within certain cases) has the complete neural circuit held inside the head. There is more transformative value for a Lisp-user than a .NET-user, even with a better IDE. While it can be argued that the IDE closes the gap in terms of productivity, it does not close the gap in terms of arete, though it may go with the grain of extropy.
Subscribe to:
Posts (Atom)