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.

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 tests

1
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
you have to use eval

eval myobj.name = tim
however if you type

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

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
Then open up a command prompt and run autotest
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.

more references

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 &lt; 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 machine

Free 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.

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">]
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

  1. 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)
  2. search for "def generate_secret_with_urandom", in Rails 2.0.2 it should be on line #85
  3. copy the line just below "def generate_secret_with_urandom....":

    puts "Before Read"

  4. 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

Here are my tips for the railscasts.com competition.