Story Runner Debug Trick
May 4th, 2008
Before I found the plugin has_many_polymorph, in the article has_many_polymorphs for dummies I had been following the article The other side of polymorphic :through associations. However the code was not doing exactly what I wanted, and each time I made a change to the model I had to reload my console to test it. I found myself doing a lot of repetitive typing. When I decided to try out has_many_polymorph, I decided a better way to learn this plugin and do testing was with rspec's story runner.
Set up
Story runner comes with rspec and rspec_on_rails. See Testing with RSPec for setup details
When I installed RSpec into my project it generated some files for Story Runner under $project/stories
1 2 |
cd $project ruby script/generate rspec |
Create a story
A story is just a text file. As a convention end the file name with _story.rb and place in $project/stories
emacs $project/stories/display_article_with_content_story.rb |
See the section 'Story Runner - Testing Object Intergration' in Testing with RSPec for a screencast and articles on setting up Story Runner
I created the following story display_article_with_content_story.rb which loaded the repetetitive data I kept loading into the console. Then set it to brake into the debugger. I was then able to play around with the code to see how it worked.
See Ruby Debug for setting up the debugger and making it act more like the irb console.
Run the story
1 2 3 |
cd $project export RAILS_ENV=test && rake db:migrate ruby stories/display_article_with_content_story.rb |
It will now load all your settings to get you into the state were you can do some testing. It will then open the ruby debugger, where you can experiment by doing various tests, and check various settings.
The advantage of doing this instead of writing your tests directly into the story is that you might not be skilled enough to know what code you need yet to write your tests, and this method gives you instant feedback of what can and can not be done, and the type things you can test for.
display_article_with_content_story.rb
May 4th, 2008
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 |
require File.expand_path(File.dirname(__FILE__) + "/helper") Story "Display an article", %{ As a user I want to view an article So that I can read its contents easily }, :type => RailsStory do Scenario "anonymous user" do Given "there is the following article in the system", "Article Numero Unero" do | title | article = Article.create(:title => title ) @article_id = article.id end Given "this article contains a note", @article_id, "some note contents" do | article_id, note_contents | note = Note.create(:title => "My Note", :description => note_contents) ArticleSection.create( :article_id => @article_id, :content_id => note.id, :content_type => note.content_type) end Given "this article contains a link", @article_id, "http://some.domain.com" do | article_id, url | link = Link.create(:title => "My Link", :url => url ) ArticleSection.create( :article_id => article_id, :content_id => link.id, :content_type => link.content_type) end Then "we do not know yet, well just jump into debugger mode and have a look around", @article_id do | article_id | require "rubygems"; require "ruby-debug"; debugger # The following line was added because here the debugger is the last statement and it will load with # out the test environment we've just created false end end end |
Ruby Debug
May 4th, 2008
With the gem ruby-debug, you can get your code to jump into a debugger. In the debugger you can examine and manipulate your code similar to how you would in the interactive ruby console.
gem instal ruby-debug |
Calling the debugger
One way to get your code to call the debugger is with the keyword debugger.
One case where I found this useful was when an rspec was failing unexpectedly.
NOTE: debugger require's rubygems and ruby-debug. In the following code I have added the require's on the same line as the call to debugger, because I will delete the whole line once I've found the problem. This is because I don't want unnecessary code lying around in my tests1 2 3 4 5 6 7 |
it "should find note, given id" do note_id = 1 do_get note_id Note.should_receive(:find).with(note_id).and_return(mock_note) get :edit 1 require "rubygems"; require "ruby-debug"; debugger end |
When it hit the debugger line a prompt came up. I used it to print the value of note_id and params[:id], and saw the reason it failed was due to the compared values being of different types.
1 2 3 4 |
(rdb:1) p note_id 1 (rdb:1) p params[:id] "1" |
Making the debugger behave more like the console
If you want to set a value in the console, by default you can't do
myobj.name = tim |
eval myobj.name = tim |
set autoeval |
you no longer need to use eval keyword.
Also, if you don't want to have to use the function p (print) to display an objects value you can set the autolist option
set autolist |
Debug Configuration File
You can preload options into the debugger, by creating the file .rdebugrc in your home directory and adding them there
1 2 3 4 |
set autolist set autoeval set autoreload set forcestep |
Tip from: Ruby-debug quick tips: init file and -n option
Ruby Debug screencast
I found the screencast Ruby Debug Basics really useful.
Testing With RSpec
May 4th, 2008
I love testing in ruby because it save's me time and helps me understand the code better (see Learn Ruby by testing). It gives me peace of mind about code regression and allows me to make major changes to my code with confidence. I also end up with documentation that can be used for remembering programming decisions made and processes taken.
I use rspec a Behaviour Driven Development framework for Ruby. It is a lot more intuitive to use than Test::Unit and from what I've read it seems more powerful and aims to displace Test::Unit.
Getting Started
A very good intoduction to rspec is RSpec on Rails
I started with the Official Installation Notes. I learnt how to use rspec by reading a good article called An introduction to RSpec, by David Chelimsky.
Also these articles were very helpful
- Mark Clarks asks How would you test this?
- Easy Controller Tests and Expressing Intent Through Expectations
- Testing Controllers with RSpec
- Wincent.com: Rspec Articles
1 2 3 4 |
# Install rspec and rspec_on_rails plugins cd $project ruby script/plugin install <a href="http://rspec.rubyforge.org/svn/tags/CURRENT/rspec">http://rspec.rubyforge.org/svn/tags/CURRENT/rspec</a> ruby script/plugin install <a href="http://rspec.rubyforge.org/svn/tags/CURRENT/rspec_on_rails">http://rspec.rubyforge.org/svn/tags/CURRENT/rspec_on_rails</a></p> |
1 2 3 |
# Once the plugin is installed, you must bootstrap your Rails app with RSpec. cd $project ruby script/generate rspec |
RSpec - Testing the behavour of an obejct
To test the behaviour of an object you create a file with the naming convention <name_of_object_to_test>_spec.rb
If you are testing a rails object, the spec file require's $project/spec/spec_helper.rb which allows the object to be tested in the relevant rails environment.
require File.dirname(__FILE__) + '/../spec_helper' |
This will be automatically added to your spec file's if you auto generate them You can auto generate rspec files when you generate your models and controllers by prefixing 'rspec_' in front of model, controller, or scaffold when you use script/generate. ( script/generate will behave as normal with the exception of generating some rspec files and place them in $project/spec ).
script/generate rspec_scaffold blog title:string description:text |
Run your spec
Then once you've written you tests. ( see vendor\plugins\rspec_on_rails\spec\rails\example ). You can run it from the command line with
1 2 3 4 |
cd $project # Test the behaviour of file app/models/credit_card.rb # -fs makes the output be displayed in format called specdoc script/spec -fs spec/models/credit_card_spec.rb |
Autotest
Is a must have for BDD testing. It automatically runs your tests when ever you change your code. This saves you typing on the command line, reduces the chance of code regression, and is quicker because it doesn't run tests on some of the files where you have not made any changes.
To use it you need to install the ZenTest gem
gem install ZenTest |
1 2 |
cd $project autotest |
You can speed autotest up a little by limiting scope of autotest
BDD Views
I found this article, Behaviour Driven Development of Rails Views,very helpful on deciding wether to be strict about using BDD on views.
I decided to only test things I was worried about i.e. can non admin users see my links, is the no products partial shown when no products and hidden when there are products. Or I'll use it if I've done a major change and want to check it was implemented on all the right pages.
Story Runner - Testing Object Intergration
Rspec comes with story runner, which allows you to do integration and acceptance testing. To get you started see Pat Maddox's screencast RSpec Story Runner and his blog article User stories with RSpec's Story Runner.
Database with Rails
May 4th, 2008
Getting Started
Database access is done through the ActiveRecord object.
Make sure you know what a virtual attribute is. I recommend you view all the active record screencasts from railscast.com.
You setup and manipulate your database using migrations. A helpful Rails Migration Cheetsheet can be found at dizzy.co.uk
Table Associations
In Rails, databases are tied together behind the scenes by ActiveRecord. By adding an appropriate directive in the model class you inform ActiveRecord how to handle these relationships. Examples of these directives include: has_many, has_one, belongs_to, has_many :through, has_many_polymorphs
1 2 3 |
class Person < ActiveRecord::Base has_many_polymorphs :ownables, :from => [:dvds, :cars, :books], :through => :ownerships end |
One of the best places to find articles on associations that I have found is at blog.hasmanythrough.com
IS A - What's polymorph
Recently I strugged to work out how to represent an IS A relationship between my models.
See my notes IS A - What's a polymorph for my first attempt at solving it and some links to good articles on polymorph.IRB Console
May 4th, 2008
1 2 |
cd $PROJECT ruby script/console development |
You need to learn the console. It allows you to examine and manipulate your code in a real-time environment. I recommend you read the following article, Secrets of the rails console ninja's, and follow its links.
The console configuration file
You can preload code into the console to make you time in it a little easier. The place to put or call this code is in a file called .irbrc. You need to create this file and place it in your $HOME directory.
Here is my .irbrc file, it just contains code I've copied from sites found through reading Secrets of the rails console ninja's. Some of the features it adds to my console are syntax highlighting (wirble), tab completion, accessing rails helpers from the console, and command history. Links to where I found these features can be found in my .irbrc file
Rails Documentation
May 4th, 2008
A Good Rails Book
I started with a great rails book called Building a social networking website with Ruby on Rails. The title is a little mis-leading. Although the theme is around a social networking site, the book concentrates on the basic skills you will need to build any database backed website. This book is great for anyone new to Rails. It is concise, practical and covers Rails 2, REST, Authenication, RJS, emails, testing.
API
If you want to view the Rails API online, the Official Ruby On Rails API is not as user friendly as the AJAX enhanced API.
You can also download the CHM Documentation, or set up RDoc and ri documentation (see next section).
1 2 |
# You can download the latest docs from here. wget -r -w 1 http://api.rubyonrails.com |
RDoc and ri
"RDoc is the embedded documentation generator for the Ruby programming language. It analyzes the Ruby source code, generating a structured collection of pages for Ruby objects and methods.... RDoc also provides the engine for creating Ruby ri data files. ri is (more or less) Ruby's version of man pages, serving up API information from the command line." wikipedia.org
I've made some notes on setting up Rdoc, ri, and gem server on your local machineFree Ruby Book
To be good at rails you are going to need a good understanding of ruby, so check out this free online book, Programming Ruby
Free Screencasts
rubyplus.org
So far I've only seen one screencast from here, but it was very helpful. This screencast Contact Us Feature using Rails 2.0 explains the code Simply Rich Authenticator, which is a default Rails application with a contact form using RESTful concepts.
railscasts.com
Lots of great rails tips! Don't forget to check out the ones your not interested in as well, because they may contain hidden gems.
Howto's
There are some Howto's on the rails wiki which I didn't find straight away.
How to get started with Rails
May 4th, 2008
Download Ruby and RubyGems from http://www.rubyonrails.org. Rails is a RubyGem, and RubyGems contains a program called gem that is used to install Rails.
I learnt how to install Rails by following the article Rolling with ruby on rails, it was written for rails 1.2 but had enough in there to get me started. You can find more articles at http://www.rubyonrails.org/docs.
I set Ruby on Rails up in a Cygwin and Windows environment. I made some personal setup notes, and they include a /dev/random error that I faced.
Later, I read Why the Lucky Stiff's (poignant) guide to Ruby, a comic that introduces you to Ruby. It has some great insights, but if your rushed for time you may want to skip to the content around the code sections and leave the story til later.
Why I chose Rails
May 4th, 2008
I resisted learning Ruby and Rails for a long time because I didn't want to learn another language. But the following facts made me change my mind.
- I enjoyed the expressiveness of Prototype, which is inspired by Ruby and mirrors the language fairly well.
- I had a choice of doing a project in PHP or Ruby and although I've used PHP before there was still a learning curve involved
- I tried PHP Cake, a framework based on rails, and liked how easy it was to get a database backed website running.
- Steve Yegge wrote an article that mentions how Ruby is displacing Perl, Python, and other scripting languages. He talks about how Ruby takes the best of list processing from Lisp, the best of OO from Smalltalk and other languages, the best of iterators from CLU, the best of Perl and pretty much the best of everything from everyone.
- I tried a 15 minute tutorial using an interactive ruby prompt in your browser and found it really easy to pick up.
- I tried a short Rails tutorial, Rolling with ruby on rails, and had a rails environment and a database website running in no time.
IS A - What's polymorph
May 4th, 2008
Polymorph is useful because it allows you treat objects of different types uniformly.
NOTE: There is a plugin that saves you from writing the following code, and it also adds extra functionality. See the tutorial has_many_polymorphs for dummies
This article contains some code and irb tests I did when learning about polymorph from these articles.
An Article_Section is made up of various types of content.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class ArticleSection < ActiveRecord::Base belongs_to :article has_many :article_contents # This code is better than that below and it works # has_many :notes, :through => :article_contents, :source => :contentizable, # :source_type => 'Note' has_many :notes, :through => :article_contents, :source => :note, :conditions => "article_contents.contentizable_type = 'Note'" has_many :links, :through => :article_contents, :source => :link, :conditions => "article_contents.contentizable_type = 'Link'" def contentizables self.notes + self.links end end |
Content can be placed in many articles.
Content can be of various type i.e. text, code, url's
1 2 3 4 5 6 7 8 9 10 11 12 |
class ArticleContent < ActiveRecord::Base belongs_to :article_sections belongs_to :contentizable, :polymorphic => true # This code is better than that below and works. # has_many :notes, :as => :contentizable belongs_to :note, :class_name => "Note", :foreign_key => "contentizable_id" belongs_to :link, :class_name => "Link", :foreign_key => "contentizable_id" end |
Note Object is of type Content
1 2 3 4 5 |
class Note < ActiveRecord::Base has_many :article_contents, :as => :contentizable has_many :article_sections, :through => :article_contents end |
Link object is of type Content
1 2 3 4 5 |
class Link < ActiveRecord::Base has_many :article_contents, :as => :contentizable has_many :article_sections, :through => :article_contents end |
Testing using the irb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
>> a = Article.create(:title => "a1") => #<Article id: 12, title: "a1", published_at: nil, author: nil, keywords: nil, state: nil, created_at: "2008-05-01 18:07:41", updated_at: "2008-05-01 18:07:41"> >> as = ArticleSection.create(:article_id => a.id ) => #<ArticleSection id: 11, article_id: 12, content_id: nil, content_type: nil, order: nil, created_at: "2008-05-01 18:07:44", updated_at: "2008-05-01 18:07:44"> >> as.notes => [] >> as.links => [] >> l = Link.create(:url => "some.domain.com") => #<Link id: 3, content_id: nil, url: "some.domain.com", description: nil, title: nil, contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 18:08:20", updated_at: "2008-05-01 18:08:20"> >> as.links << l => [#<Link id: 3, content_id: nil, url: "some.domain.com", description: nil, title: nil, contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 18:08:20", updated_at: "2008-05-01 18:08:20">] >> n = Note.create(:description => "hi", :title => "something") => #<Note id: 9, description: "hi", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 18:08:41", updated_at: "2008-05-01 18:08:41", title: "something", content_id: nil> >> as.notes << n => [#<Note id: 9, description: "hi", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 18:08:41", updated_at: "2008-05-01 18:08:41", title: "something", content_id: nil>] >> as.article_contents => [#<ArticleContent id: 1, article_section_id: 11, contentizable_id: 3, contentizable_type: nil, created_at: "2008-05-01 18:08:25", updated_at: "2008-05-01 18:08:25">, #<ArticleContent id: 2, article_section_id: 11, contentizable_id: 9, contentizable_type: nil, created_at: "2008-05-01 18:08:49", updated_at: "2008-05-01 18:08:49">] >> as.article_contents.length => 2 |
Another test using the irb
1 2 3 4 5 6 7 |
>> n = Note.create(:title => "t", :description => "d") => #<Note id: 14, description: "d", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 19:08:46", updated_at: "2008-05-01 19:08:46", title: "t", content_id: nil> >> as.notes << n => [#<Note id: 12, description: "d", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 19:07:51", updated_at: "2008-05-01 19:07:51", title: "t", content_id: nil>, #<Note id: 13, description: "d", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 19:08:06", updated_at: "2008-05-01 19:08:06", title: "t", content_id: nil>, #<Note id: 14, description: "d", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 19:08:46", updated_at: "2008-05-01 19:08:46", title: "t", content_id: nil>] >> n.article_contents => [#<ArticleContent id: 6, article_section_id: 21, contentizable_id: 14, contentizable_type: "Note", created_at: "2008-05-01 19:08:50", updated_at: "2008-05-01 19:08:50">] |
Interactive Ruby Console Configuration File - .irbc
May 4th, 2008
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
require 'utility_belt' # Tracing irb # http://blog.bleything.net/2006/12/11/tracing-method-execution def enable_trace( event_regex = /^(call|return)/, class_regex = /IRB|Wirble|RubyLex|RubyToken/ ) puts "Enabling method tracing with event regex #{event_regex.inspect} and class exclusion regex #{class_regex.inspect}" set_trace_func Proc.new{|event, file, line, id, binding, classname| printf "[%8s] %30s %30s (%s:%-2d)\n", event, id, classname, file, line if event =~ event_regex and classname.to_s !~ class_regex } return end def disable_trace puts "Disabling method tracing" set_trace_func nil end # ------------------------------------------------------------------ # Wirble - Colors in irb # http://pablotron.org/software/wirble/ # load libraries require 'rubygems' require 'wirble' # start wirble (with color) Wirble.init Wirble.colorize # ------------------------------------------------------------------ # Tab Completion # http://whytheluckystiff.net/clog/ruby/tabCompletionInIRb.html require 'irb/completion' # ------------------------------------------------------------------ # simple irb prompt IRB.conf[:PROMPT_MODE] = :SIMPLE # ------------------------------------------------------------------ # Accessing rails helpers in console # http://errtheblog.com/posts/41-real-console-helpers def Object.method_added(method) return super(method) unless method == :helper (class<<self;self;end).send(:remove_method, :method_added) def helper(*helper_names) returning $helper_proxy ||= Object.new do |helper| helper_names.each { |h| helper.extend "#{h}_helper".classify.constantize } end end helper.instance_variable_set("@controller", ActionController::Integration::Session.new) def helper.method_missing(method, *args, &block) @controller.send(method, *args, &block) if @controller && method.to_s =~ /_path$|_url$/ end helper :application rescue nil end if ENV['RAILS_ENV'] # ------------------------------------------------------------------ # Command History # http://blog.nicksieger.com/articles/2006/04/23/tweaking-irb module Readline module History LOG = "#{ENV['HOME']}/.irb-history" def self.write_log(line) File.open(LOG, 'ab') {|f| f << "#{line} "} end def self.start_session_log write_log(" # session start: #{Time.now} ") at_exit { write_log(" # session stop: #{Time.now} ") } end end alias :old_readline :readline def readline(*args) ln = old_readline(*args) begin History.write_log(ln) rescue end ln end end Readline::History.start_session_log # ------------------------------------------------------------------ require 'irb/ext/save-history' IRB.conf[:SAVE_HISTORY] = 10000 IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history" #------------------------------------------------------------------ def ri arg puts `ri #{arg}` end class Module def ri(meth=nil) if meth if instance_methods(false).include? meth.to_s puts `ri #{self}##{meth}` else super end else puts `ri #{self}` end end end # ------------------------------------------------------------------ # http://woss.name/2006/07/12/using-the-shell-within-irb/ require 'shell' # Override the command processor widget for inserting system commands so # that it behaves more like path-processing: earlier commands take precedence. require 'shell/command-processor' module FixAddDelegateCommandToShell def self.extended(obj) class << obj alias_method :add_delegate_command_to_shell_override, :add_delegate_command_to_shell unless method_defined?(:add_delegate_command_to_shell_override) alias_method :add_delegate_command_to_shell, :add_delegate_command_to_shell_no_override end end def add_delegate_command_to_shell_no_override(id) id = id.intern if id.kind_of?(String) name = id.id2name if Shell.method_defined?(id) or Shell::Filter.method_defined?(id) Shell.notify "warn: Not overriding existing definition of Shell##{name}." else add_delegate_command_to_shell_override(id) end end end Shell::CommandProcessor.extend(FixAddDelegateCommandToShell) # Allow Shell system commands to take :symbols too, to save a little typing. require 'shell/system-command' class Shell class SystemCommand alias_method :initialize_orig, :initialize def initialize(sh, command, *opts) opts.collect! {|opt| opt.to_s } initialize_orig sh, command, *opts end end end # Provide me with a shell inside IRB to save quitting and restarting, or # finding that other terminal window. def shell unless $shell Shell.install_system_commands '' # no prefix $shell = Shell.new end $shell end #------------------------------------------------------------------ # it loads a rails project into irb, useful if you really should have run ./script/console def self.load_rails(from="./") require File.expand_path(File.join(from,"config/boot")) require File.join(RAILS_ROOT, 'config', 'environment') end # ------------------------------------------------------------------ # Iterative development in irb # http://po-ru.com/diary/iterative-development-in-irb # To use it, just type: # loop_execute('myfile.rb') # in irb. Control-C will return control to the regular irb shell. def loop_execute(file) old_mtime = nil loop do # print("\e[sWaiting...") sleep(0.2) while (mtime = File.stat(file).mtime) == old_mtime # print("\e[u\e[K") begin r = eval(File.read(file)) puts("=> #{r.inspect}") rescue IRB::Abort puts("Abort") return rescue Exception => e puts("#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}") end old_mtime = mtime end end # ------------------------------------------------------------------ class Object # p30 the rails way # set some environment variables, that are normally sent to # the dispatcher. # then fool the dispatcher into thinking it is getting a request. # # The following command will return the contents of the webpage request # # request( :controller => "pages", :action => 'show', :id => 'home') # def request(options = {}) method = options.delete(:method) || :get options.reverse_merge!(:only_path => true) ENV['REQUEST_URI'] = app.url_for(options) ENV['REQUEST_METHOD'] = method.to_s Dispatcher.dispatch end end # ------------------------------------------------------------------ # pm object # pm object, :more - shows all methods including base Object methods # pm object, :more, /to/ - shows all methods filtered by regexp # Coded by sebastian delmont ANSI_BOLD = "\033[1m" ANSI_RESET = "\033[0m" ANSI_LGRAY = "\033[0;37m" ANSI_GRAY = "\033[1;30m" def pm(obj, *options) # Print methods methods = obj.methods methods -= Object.methods unless options.include? :more filter = options.select {|opt| opt.kind_of? Regexp}.first methods = methods.select {|name| name =~ filter} if filter data = methods.sort.collect do |name| method = obj.method(name) if method.arity == 0 args = "()" elsif method.arity > 0 n = method.arity args = "(#{(1..n).collect {|i| "arg#{i}"}.join(", ")})" elsif method.arity < 0 n = -method.arity args = "(#{(1..n).collect {|i| "arg#{i}"}.join(", ")}, ...)" end klass = $1 if method.inspect =~ /Method: (.*?)#/ [name, args, klass] end max_name = data.collect {|item| item[0].size}.max max_args = data.collect {|item| item[1].size}.max data.each do |item| print " #{ANSI_BOLD}#{item[0].rjust(max_name)}#{ANSI_RESET}" print "#{ANSI_GRAY}#{item[1].ljust(max_args)}#{ANSI_RESET}" print " #{ANSI_LGRAY}#{item[2]}#{ANSI_RESET}\n" end data.size end #------------------------------------------------------------------ # In honor of Labor Day, here's a hack that might save you some. I spend a lot of time in the Rails console, and most of that time I'm finding stuff. Typing find is so... laborious. But drop this in your ~/.irbrc file, and your work is made light. # # Creates shortcut methods for finding models. # def define_model_find_shortcuts # model_files = Dir.glob("app/models/**/*.rb") # table_names = model_files.map { |f| File.basename(f).split('.')[0..-2].join } # table_names.each do |table_name| # Object.instance_eval do # define_method(table_name) do |*args| # table_name.camelize.constantize.send(:find, *args) # end # end # end # end # # Called when the irb session is ready, after # # the Rails goodies used above have been loaded. # IRB.conf[:IRB_RC] = Proc.new { define_model_find_shortcuts } |
RDoc, ri and gem server
May 4th, 2008
Installing Documentation
You can view the Rails API and other documentation on your local machine instead of the online Rails API. To do this install Rails API, gem documentation and other docs on local machine, by running these command's
1 2 |
# Install ri, RDoc, documentation gem rdoc --all |
Now the rdocs should be available to the gem server.
NOTE: When you install new gems there is no rdoc and ri documentation generated for it by default, but you can easily install it with
1 2 |
# Generates RDOC documentation for the given $gemname gem rdoc $gemname |
Gem Server - View local documentation in your browser
To view the local rails documentation in a web browser you need to start the gem server, and then browse http://localhost:8808
1 2 3 4 |
# Start gem_server > gem server # Open web browser firefox http://localhost:8808 |
ri - View documenation from the command line
1 2 |
# View the documentation for the method zip from the Enumerable class ri Enumberable#zip |
or with color
1 2 |
# View the documentation for the method gsub from the String class ri -Tf ansi String#gsub |
Rails Cygwin Setup Notes
May 4th, 2008
Install Cygwin and the Cygwin version of Ruby.
Cygwin is a bunch of programs that allows you to create a Linux like environment on windows. It can be installed with a one click installer.
I found the following article helpful in setting up Rails on cygwin, Install Rails on Windows Using Cygwin
The installer is very simple. The only defaults I changed were where to intall the files, I choose the root of my drive ( x:\ ) and I added a few extra programs. One of the extra programs I choose to install was Ruby.
For reference, the other programs I added were: cron, unzip, bash-debugger, ctags, gcc ( java, c++, c ), gdb, make, subversion, docbook-4.4, docbook-xsl, perl manpage, expect, perl-5.8.7-5, ruby, python, perl-win32-gui, perl-libwin-32, whois, xinetd, ping, ncftpget, curl, bash-completion, mc, rxvt, OpenSp, aspell, aspell-docs, openjade, tetext, texmf-base, texmf-extra, w3m, patch, patch-utils, rxvt, web, lynx, tidy, wget, tcp_wrapper, zlib, openssh, git
Install Rails
Rails is packaged in a Ruby gem. The RubyGem package manager is a program that helps the managing and installation of ruby packages/gems/programs/libraries.
I downloaded rubygems-1.0.1.tgz from http://rubyforge.org/frs/?group_id=126 and unzipped to c:\
GOTCHA: If you have previously installed the windows one-click installer, it sets an environment variable RUBYOPT=rubygems. This variable tells ruby to load the rubygems library when running a ruby file. However, in our new cygwin environment we have not installed Rugy Gems yet and this environment will cause setup.rb execution to fail.
Open up your cygwin bash prompt and enter the following commands to install RubyGems and Rails
1 2 3 4 5 6 7 8 9 |
# Unset enviroment variable unset RUBYOPT # change to rubygems installation directory cd /cygdrive/c/rubygems-1.0.1 # Install RubyGems ruby setup.rb # Install rails using gems gem install rails |
Rails Cygwin problem - "/dev/urandom" not found.
When you go to create a new rails project, you might get the error
"/dev/urandom" not found.
This can be easily fixed and I found the solution in this article: Configuring my workspace
- locate the file 'secret_key_generator.rb' (the location on my machine was x:\lib\ruby\gems\1.8\gems\rails-2.0.2\lib\rails_generator\secret_key_generator.rb)
- search for "def generate_secret_with_urandom", in Rails 2.0.2 it should be on line #85
- copy the line just below "def generate_secret_with_urandom....":
puts "Before Read"
- save the file and it should work
This has been fixed with Ruby 1.9
MySQL Cygwin Setup
I found the following article helpful in setting up MySQL on Cygwin: Install Rails on Windows Using Cygwin
Make sure patch, tar, gcc and make have been installed under Cygwin
I download the mysql source and extracted it to c:/
Then I opened cygwin prompt and typed
1 2 3 |
cd \cygdrive\c\mysql-5.0.51a ./configure make install |
Rails - More than 5 tips to get you started.
May 3rd, 2008
Here are my tips for the railscasts.com competition.