Articles

*** extconf.rb failed ***

In Uncategorized on June 25, 2011 by dyba

The Error Impeding My Contributions

On my way to contribute to the Rails Guides, after pulling from my cloned copy of the docrails repository on Github and running the bundle install command, an error stopped me:

danieldyba@P4R15 Sat Jun 25 19:35 [ ~/Ruby/docrails ]
>_ bundle install
 #... installation of other gems omitted
 Installing pg (0.11.0) with native extensions /Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems/installer.rb:533:in `rescue in block in build_extensions': ERROR: Failed to build gem native extension. (Gem::Installer::ExtensionBuildError)
/Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/bin/ruby extconf.rb
 checking for pg_config... no
 No pg_config... trying anyway. If building fails, please try again with
 --with-pg-config=/path/to/pg_config
 checking for libpq-fe.h... no
 Can't find the 'libpq-fe.h header
 *** extconf.rb failed ***
 Could not create Makefile due to some reason, probably lack of
 necessary libraries and/or headers. Check the mkmf.log file for more
 details. You may need configuration options.
Provided configuration options:
 --with-opt-dir
 --without-opt-dir
 --with-opt-include
 --without-opt-include=${opt-dir}/include
 --with-opt-lib
 --without-opt-lib=${opt-dir}/lib
 --with-make-prog
 --without-make-prog
 --srcdir=.
 --curdir
 --ruby=/Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/bin/ruby
 --with-pg
 --without-pg
 --with-pg-dir
 --without-pg-dir
 --with-pg-include
 --without-pg-include=${pg-dir}/include
 --with-pg-lib
 --without-pg-lib=${pg-dir}/lib
 --with-pg-config
 --without-pg-config
 --with-pg_config
 --without-pg_config
Gem files will remain installed in /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@DocRails/gems/pg-0.11.0 for inspection.
 Results logged to /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@DocRails/gems/pg-0.11.0/ext/gem_make.out
 from /Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems/installer.rb:511:in `block in build_extensions'
 from /Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems/installer.rb:486:in `each'
 from /Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems/installer.rb:486:in `build_extensions'
 from /Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems/installer.rb:159:in `install'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/source.rb:101:in `block in install'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/rubygems_integration.rb:78:in `preserve_paths'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/source.rb:91:in `install'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/installer.rb:58:in `block (2 levels) in run'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/rubygems_integration.rb:93:in `with_build_args'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/installer.rb:57:in `block in run'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/spec_set.rb:12:in `block in each'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/spec_set.rb:12:in `each'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/spec_set.rb:12:in `each'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/installer.rb:49:in `run'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/installer.rb:8:in `install'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/cli.rb:222:in `install'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/vendor/thor/task.rb:22:in `run'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/vendor/thor/invocation.rb:118:in `invoke_task'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/vendor/thor.rb:246:in `dispatch'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/lib/bundler/vendor/thor/base.rb:389:in `start'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.14/bin/bundle:13:in `'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/bin/bundle:19:in `load'
 from /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@global/bin/bundle:19:in `'
 danieldyba@P4R15 Sat Jun 25 19:35 [ ~/Ruby/docrails ]
>_

I am using MacPorts on my machine so if you’re having the same problem and are not using MacPorts then this guide will probably not help you; however, you may learn something that could lead you in the right direction.

Well, I followed the instructions on that error message and looked for my mkmf.log file:

>_ cat /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@DocRails/gems/pg-0.11.0/ext/mkmf.log
 find_executable: checking for pg_config... -------------------- no
--------------------
find_header: checking for libpq-fe.h... -------------------- no
"gcc -o conftest -I/Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1/x86_64-darwin10.7.0 -I/Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1/ruby/backward -I/Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wshorten-64-to-32 -Wno-long-long -fno-common -pipe conftest.c -L. -L/Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/lib -L. -lruby.1.9.1-static -lpthread -ldl -lobjc "
 checked program was:
 /* begin */
 1: #include "ruby.h"
 2:
 3: int main() {return 0;}
 /* end */
"gcc -E -I/Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1/x86_64-darwin10.7.0 -I/Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1/ruby/backward -I/Users/danieldyba/.rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wshorten-64-to-32 -Wno-long-long -fno-common -pipe conftest.c -o conftest.i"
 conftest.c:3:22: error: libpq-fe.h: No such file or directory
 checked program was:
 /* begin */
 1: #include "ruby.h"
 2:
 3: #include /* end */
--------------------
danieldyba@P4R15 Sat Jun 25 20:07 [ ~/Ruby/docrails ]
 >_

One Tool Can’t find Another

The trouble seems to be that Bundler can’t find the executable file pg_config. After a little research, I found out that I need to have Postgresql installed on my machine. So I did that with the command:

sudo port install postgresql90

Next, I checked to see where MacPorts installed Postgresql, in particular, where it installed the pg_config file:

>_ find /opt -name pg_config
 /opt/local/lib/postgresql90/bin/pg_config
 /opt/local/var/macports/software/postgresql90/9.0.4_0/opt/local/lib/postgresql90/bin/pg_config

Looks like the file is saved in /opt/local/lib/postgresql90/bin/pg_config. I will have to tell Bundler about where the pg_config file is located:

bundle config build.pg --with-pg-config=/opt/local/lib/postgresql90/bin/pg_config

That will add a line to my Bundler config file like so:

 >_ cat ~/.bundle/config
 ---
 BUNDLE_BUILD__PG: --with-pg-config=/opt/local/lib/postgresql90/bin/pg_config

And now we’re ready to rock and roll. Run the “bundle install” command again and that error will go away.

Articles

Mixing Modules with Classes – Class Methods

In Uncategorized on February 11, 2011 by dyba Tagged: , , , ,

Ned wanted to add more functionality to the Dog class he created. This time, instead of organizing methods inside a module class and making the module methods available to all instances of the Dog class, he wanted to create a module class that made its methods available to the Dog class as class methods.

“I know this much,” thought Ned, “what I did last time won’t get what I want this time. But what would be the first step?” He pondered a few moments and spoke aloud. “The last time I took instance methods from a module…”

module Actions
  def bark
    "Woof!"
  end
end

“… and included it into the Dog class.”

class Dog
  include Actions
end

Ned began typing.


module Attributes
	def breedable?
		true
	end

	def latin_name
		"Canis"
	end

	def has_four_legs?
		true
	end
end

“So here’s the module whose instance methods I want to include in the Dog class as class methods. And I want to be able to do this…”

ruby-1.9.2-p136 :002 > Dog.has_four_legs?

Having learned from last time, Ned caught himself and said, “Oh, I better get a test suite running first.”

require 'test/unit'
require './module'

class ModuleTest < Test::Unit::TestCase

	def test_canine_attributes
		assert_equal(true, Dog.breedable?)
		assert_equal(true, Dog.has_four_legs?)
		assert_equal("Canis", Dog.latin_name)
	end
end

“And can’t forget the Rakefile to run tests easily…”

require 'rake/testtask'

Rake::TestTask.new do |t|
	t.libs << "test"
	t.test_files = FileList['test/**/*_test.rb']
	t.verbose = true
end

“Now to check my file structure looks good…”

>_ ls -R
Rakefile	module.rb	test

./test:
module_test.rb

“Great!” said Ned. “Just for kicks, I’ll write code I know won’t work.”

module Attributes
	def breedable?
		true
	end

	def latin_name
		"Canis"
	end

	def has_four_legs?
		true
	end
end

class Dog
	include Attributes
end

“And when I run the ‘rake test’ command from the Terminal…”


>_ rake test
(in /Users/Paintdexter/ruby/module_examples/module_example_02)
/Users/Paintdexter/.rvm/rubies/ruby-1.9.2-p136/bin/ruby -I"lib:test" "/Users/Paintdexter/.rvm/gems/ruby-1.9.2-p136@rails3/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/module_test.rb" 
Loaded suite /Users/Paintdexter/.rvm/gems/ruby-1.9.2-p136@rails3/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
E
Finished in 0.000681 seconds.

  1) Error:
test_canine_attributes(ModuleTest):
NoMethodError: undefined method `breedable?' for Dog:Class
    test/module_test.rb:7:in `test_canine_attributes'

1 tests, 0 assertions, 0 failures, 1 errors, 0 skips

Test run options: --seed 33524
rake aborted!
Command failed with status (1): [/Users/Paintdexter/.rvm/rubies/ruby-1.9.2-...]

(See full trace by running task with --trace)

“Just as expected,” nodded Ned. “Ok, I’ll remove that line of code and jump into IRB”.

module Attributes
	def breedable?
		true
	end

	def latin_name
		"Canis"
	end

	def has_four_legs?
		true
	end
end

class Dog
end
>_ irb
ruby-1.9.2-p136 :001 > require './module'
 => true 
ruby-1.9.2-p136 :002 > Dog.methods
 => [:allocate, :new, :superclass, :freeze, :===, :==, :<=>, :<, :<=, :>, :>=, :to_s, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods, :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?, :const_missing, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set, :class_variable_defined?, :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?, :public_method_defined?, :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload, :autoload?, :instance_method, :public_instance_method, :nil?, :=~, :!~, :eql?, :hash, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :__id__, : object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__] 
ruby-1.9.2-p136 :003 >

“That’s a whole lot of methods!” said Ned as his eyes scanned the several lines of output. “Out of all these, I’m gonna pick….” Ned thought for a moment and finally decided, “the extend method.” He typed the following in the Terminal window.

>_ ri extend

Ned watched as the screen gave way to a whole page of content.

= .extend

(from ruby core)
=== Implementation from Object
------------------------------------------------------------------------------
  obj.extend(module, ...)    -> obj

------------------------------------------------------------------------------

Adds to obj the instance methods from each module given as a parameter.

       module Mod
         def hello
           "Hello from Mod.\n"
         end
       end

       class Klass
         def hello
           "Hello from Klass.\n"
         end
       end

       k = Klass.new
       k.hello         #=> "Hello from Klass.\n"
       k.extend(Mod)   #=> #<Klass:0x401b3bc8>
       k.hello         #=> "Hello from Mod.\n"

“This looks close to what I want except I want to use this on a class.” Ned caught himself, “But I can use this on any object, and that includes a class object! But how would I make my example use the extend method?” Just then Rich made his way past Ned’s cubicle. “Hey Rich!” called Ned. “I need you for a minute.” Rich made his way over with a cup of hazelnut coffee on hand. “How can I use the extend method in my class to make the instance methods of my Attributes module available to my Dog class as class methods?” Rich asked, “Well, do you see how that example calls the extend method on ‘k’ which is an instance of Klass?” “Yeah, I see that,” said Ned. Rich continued, “So you need to call the extend method while inside your class object.” Ned said, “You mean like this?”

class Dog
	extend Attributes
end

“Precisely!” said Rich. “Go ahead and run your tests.” Ned ran the ‘rake test’ command in the Terminal:


>_ rake test
(in /Users/Paintdexter/ruby/module_examples/module_example_02)
/Users/Paintdexter/.rvm/rubies/ruby-1.9.2-p136/bin/ruby -I"lib:test" "/Users/Paintdexter/.rvm/gems/ruby-1.9.2-p136@rails3/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/module_test.rb" 
Loaded suite /Users/Paintdexter/.rvm/gems/ruby-1.9.2-p136@rails3/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
.
Finished in 0.000629 seconds.

1 tests, 3 assertions, 0 failures, 0 errors, 0 skips

Test run options: --seed 20387

“Sweet!” cried Ned with excitement. “Do you know why that works?” asked Rich. “Kinda,” hesitated Ned. Rich explained, “What’s implied in your code is that you are calling the extend method on self. And in this case, since you are inside the scope of a class, self is the Dog class. So, what is really happening, looks more like this”

class Dog
	self.extend Attributes
end

“If you look back at the output you got from running the ‘ri’ command, you’ll see that extend adds the instance methods of a module to the object. In this case, your object is self, or the Dog class. So you add the instance methods of the Attributes module to the Dog class. These instance methods become the class methods of the Dog class.”
“Ah!” said Ned. “That makes sense.”

Articles

Mixing Modules with Classes – Where Order Matters

In Uncategorized on February 9, 2011 by dyba Tagged: , , ,

“Confound it!” cried Ned. Frustrated, he shoved his keyboard and crossed his arms. “Why doesn’t it work?” He leaned back in and began a Google search for the answer to his problem. “Hey chap! What’s got you fuming?” inquired Rich. “I’m trying to mix a module in with a class, but I can’t seem to get it right,” complained Ned. “What exactly are you trying to accomplish?” asked Rich. “So, here’s what I’m trying to do. You see, I define a module with a method here. And I’m trying to get an instance of my class to use that method. So I include the module in the class, but it just doesn’t work!”

class Dog
  include Actions
end

module Actions
  def bark
    "Woof!"
  end
end

“What’s the error message you’re getting?” asked Rich. “Well, I’m getting an uninitialized constant error,” said Ned with a sigh.


ruby-1.9.2-p136 :001 > require './module'
NameError: uninitialized constant Dog::Actions
	from /Users/Paintdexter/ruby/module_example_01/module.rb:2:in `<class:Dog>'
	from /Users/Paintdexter/ruby/module_example_01/module.rb:1:in `<top (required)>'
	from <internal:lib/rubygems/custom_require>:29:in `require'
	from <internal:lib/rubygems/custom_require>:29:in `require'
	from (irb):1
	from /Users/Paintdexter/.rvm/rubies/ruby-1.9.2-p136/bin/irb:17:in `<main>'
ruby-1.9.2-p136 :002 > 

Rich poked his eyes around Ned’s screen, “Where’s your test suite?” Embarrassed, Ned managed a broken chuckle, “Oh right!” He pulled up a new window and began typing:

require 'test/unit'
require './module'

class ModuleTest < Test::Unit

Ned stopped typing. "How does that go again?" he asked. Rich spoke, "Your ModuleTest will be a subclass of Test::Unit::TestCase." "Oh right, right!" interjected Ned. "Now, set up the object you'll be testing. In this case, it will be an instance of Dog," continued Rich. "Do you remember the rest?" asked Rich. “Yup,” said Ned confidently, “assert_equal and voila":

require 'test/unit'
require './module'

class ModuleTest < Test::Unit::TestCase

	def setup
		@dog = Dog.new
	end

	def test_an_instance_of_a_dog_should_bark
		assert_equal("Woof!", @dog.bark)
	end
end

“Let’s go ahead and add a Rakefile to make running tests easier,” invited Rich. “Create a file called Rakefile and add the following lines below.”

require 'rake/testtask'

Rake::TestTask.new do |t|
	t.libs << "test"
	t.test_files = FileList['test/**/*_test.rb']
	t.verbose = true
end

Rich went on, “The first line lets you create an instance of Rake::TestTask so you can run your tests. The fourth line includes a directory in your current directory called ‘test’. The fifth line will grab any files in the ‘test’ directory that end in ‘_test.rb’. And the last line gives us more information when we encounter an error in the Terminal after we run the command. Go ahead and create a directory and store your test file there. Your file structure should look like this”

>_ ls -R
Rakefile	module.rb	test

./test:
module_test.rb

“Now, let’s get back to the problem,” continued Rich.


ruby-1.9.2-p136 :001 > require './module'
NameError: uninitialized constant Dog::Actions
	from /Users/Paintdexter/ruby/module_example_01/module.rb:2:in `<class:Dog>'
	from /Users/Paintdexter/ruby/module_example_01/module.rb:1:in `<top (required)>'
	from <internal:lib/rubygems/custom_require>:29:in `require'
	from <internal:lib/rubygems/custom_require>:29:in `require'
	from (irb):1
	from /Users/Paintdexter/.rvm/rubies/ruby-1.9.2-p136/bin/irb:17:in `<main>'
ruby-1.9.2-p136 :002 > 

“If you try running the ‘rake test’ command in the Terminal, you’ll get similar output.” Ned went ahead and did so:

>_ rake test
(in /Users/Paintdexter/ruby/module_example_01)
/Users/Paintdexter/.rvm/rubies/ruby-1.9.2-p136/bin/ruby -I"lib:test" "/Users/Paintdexter/.rvm/gems/ruby-1.9.2-p136@rails3/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/module_test.rb" 
/Users/Paintdexter/ruby/module_example_01/module.rb:2:in `<class:Dog>': uninitialized constant Dog::Actions (NameError)
	from /Users/Paintdexter/ruby/module_example_01/module.rb:1:in `<top (required)>'
	from <internal:lib/rubygems/custom_require>:29:in `require'
	from <internal:lib/rubygems/custom_require>:29:in `require'
	from test/module_test.rb:2:in `<top (required)>'
	from /Users/Paintdexter/.rvm/gems/ruby-1.9.2-p136@rails3/gems/rake-0.8.7/lib/rake/rake_test_loader.rb:5:in `load'
	from /Users/Paintdexter/.rvm/gems/ruby-1.9.2-p136@rails3/gems/rake-0.8.7/lib/rake/rake_test_loader.rb:5:in `block in <main>'
	from /Users/Paintdexter/.rvm/gems/ruby-1.9.2-p136@rails3/gems/rake-0.8.7/lib/rake/rake_test_loader.rb:5:in `each'
	from /Users/Paintdexter/.rvm/gems/ruby-1.9.2-p136@rails3/gems/rake-0.8.7/lib/rake/rake_test_loader.rb:5:in `<main>'
rake aborted!
Command failed with status (1): [/Users/Paintdexter/.rvm/rubies/ruby-1.9.2-...]

(See full trace by running task with --trace)

“It looks like IRB doesn't see the Actions module. Particularly, there seems to be something wrong in line 2, where you call the include method and pass the Actions module as a parameter. Let me ask you something, Ned. Do you think the order of where you defined the Actions module might matter?" Ned pondered for a moment and cocked his head. "Let's try switching the order around," invited Rich. So Ned went right ahead and did just as Rich had said:

module Actions
	def bark
		"Woof!"
	end
end

class Dog
	include Actions
end

Ned returned to the Terminal.

ruby-1.9.2-p136 :001 > require './module'
 => true 
ruby-1.9.2-p136 :002 > 

"Great!" said Ned ecstatically, "That did it! The order DOES matter." He lost no time and proceeded to see his creation work flawlessly:

ruby-1.9.2-p136 :002 > spot = Dog.new
 => #<Dog:0x000001010089d8> 
ruby-1.9.2-p136 :003 > spot.bark
 => "Woof!" 
ruby-1.9.2-p136 :004 > 

"Will you look at that!" reveled Ned, "It works!" He ran the next command:

>_ rake test
(in /Users/Paintdexter/ruby/module_example_01)
/Users/Paintdexter/.rvm/rubies/ruby-1.9.2-p136/bin/ruby -I"lib:test" "/Users/Paintdexter/.rvm/gems/ruby-1.9.2-p136@rails3/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/module_test.rb" 
Loaded suite /Users/Paintdexter/.rvm/gems/ruby-1.9.2-p136@rails3/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
.
Finished in 0.000605 seconds.

1 tests, 1 assertions, 0 failures, 0 errors, 0 skips

Test run options: --seed 15619

A smile broke through Ned’s face.

Articles

Cucumber Ambiguous Match Errors

In Uncategorized on October 15, 2010 by dyba Tagged: , , ,

Have you tried running Cucumber with webrat and had a hard time getting past the “Ambigous match” error? The webrat matchers are a series of Cucumber steps written using Regular Expressions. This means Cucumber will match the Webrat steps against the Cucumber steps you write.

I am going to assume you’ve already got Cucumber and Webrat installed in your machine and configured it for your Rails app. By the way, I’m using Rails 3, Cucumber 0.9.2, Cucumber-rails 0.3.2, Webrat 0.7.2 beta1, and Clearance 0.9.0.rc9. I also ran the command:

rails generate cucumber:install --webrat

Let’s take a simple example: I want to check that I go to the right page on my web app. In Cucumber, you’d write this:

When /^I go to the sign up page$/ do
end

But if you look at your webrat file under /features/step_definitions/web_steps.rb, you’ll find this entry:

When /^(?:|I )go to (.+)$/ do |page_name|
visit path_to(page_name)
end

What this tells you is that Cucumber will match this Webrat step with a statement like “I go to the sign up page”. I tried this:

When /^I go to the sign up page$/ do |sign_up_page|
end

That gave me that nasty “Ambiguous match” error. Well, what’s wrong? I took a look at the regular expression again:

When /^(?:|I )go to (.+)$/ do |page_name|
visit path_to(page_name)
end

Now, I ran a test in irb and saw that this code:

"I go to the sign in page".scan(/^(?:|I )go to (.+)$/)

Gives the output:

=> [["the sign in page"]]

Which basically tells me that the Webrat step should have matched my Cucumber step. Something told me that perhaps I should tweak my Cucumber step. So I did:

When /^I go to the 'sign up page'$/ do |sign_up_page|
end


When /^I go to the "sign up page"$/ do |sign_up_page|
end


When /^I go to the SignUpPage$/ do |sign_up_page|
end


When /^I go to the 'the sign up page'$/ do
end

It turns out that all these examples passed. So that made me conclude that Cucumber couldn’t properly interpret the Webrat statements because it doesn’t like the spaces I had in my Cucumber step. Also, it needed something to clearly point out what (.+) meant in my statement. To get Cucumber to understand what I meant, I enclosed the phrase that would be interpreted as a parameter in single quotes. Perhaps, it couldn’t interpret the (.+) correctly. For now, I’m going to live with it and make it a point to read the cucumber-rails gem to find out what’s really going on.

Articles

RSpec Tutorial #001

In ruby, Tutorial on September 3, 2010 by dyba Tagged: , ,

Requirements
Ruby 1.8.7 (2009-06-12 patchlevel 174)
RSpec 1.3.0

I started learning RSpec a few days ago. Well, I started much earlier than that, but at that time I was still new to Ruby. With a year’s worth of experience with Ruby now, I feel more confident to tackle RSpec to test my Ruby code. When you’re new to Ruby testing doesn’t make much sense: how can I test code when I don’t even know how to write it properly? I definitely think you need to have to play with the language long enough to understand it well enough before you dive into writing unit and more complicated tests.

Here’s some RSpec code I found on the RSpec book by David Chelimsky:

describe Stack do
     before(:each) do
          @stack = Stack.new
          @stack.push :item
     end
     describe "#peek" do
          it "should return the top element" do
               @stack.peek.should == :item
          end
          it "should not remove the top element" do
               @stack.peek
               @stack.size.should == 1
          end
     end
     describe "#pop" do
          it "should return the top element" do
               @stack.pop.should == :item
          end
          it "should remove the top element" do
               @stack.pop
               @stack.size.should == 0
          end
     end
end

The first describe statement is the outermost block. Do you see the do and end keywords? We insert a statement after the describe keyword to give a name to our test. We are testing an object called Stack.

The before(:each) statement is the next block inside the outermost block. Inside the before(:each) block, we specify what code we want to run before running the inner describe statements. For every describe statement, the code in the before(:each) block will run beforehand. In the before(:each) block we create a new Stack object and push an item onto the stack.

Looking at the methods of this Stack object, we see that it acts very much like an Array. An array has a pop method and a push method. Let’s keep that in mind for later.

The next describe statement has a description of “#peek”. By convention, the hash sign signifies that this is a method inside of the Stack object. The it statements specify how the peek method should behave. Note that the peek method should show us what is on top of the stack without removing that item from the stack. The should method is made available via RSpec. You call this method on your target object and check its output with the == sign. So in our case, we want to call the method peek on @stack and it should be equal to 0. Translating this to code RSpec can interpret leads to @stack.peek.should == 0.

The next describe statement has a description of “#pop”. This is your standard pop method that comes with an Array: when you call the pop method, the item on the stack gets removed.

Now, what is the code we should be writing to make these tests pass?

We can start by creating a Stack class that subclasses the Array class:

class Stack < Array
end

Run the test using the ‘spec’ command. We add the color option so we can see red and green colored tests when they fail or pass, respectively. The other option we add, let’s us see the describe statements in a nested fashion:

> spec stack.rb –color –format nested

Stack
     #peek
          should return the top element (FAILED - 1)
          should not remove the top element (FAILED - 2)
     #pop
        should return the top element
        should remove the top element
1) NoMethodError in 'Stack#peek should return the top element'
undefined method `peek' for [:item]:Stack
./stack.rb:12:
2) NoMethodError in 'Stack#peek should not remove the top element'
undefined method `peek' for [:item]:Stack
./stack.rb:16:

You’ll see that we haven’t added any methods to the Stack class. Since we subclasses Stack with Array, we’ve covered the pop method. Now to do something about that peek method. You know that the Array class has a pop method. We want to use that but not on the object itself. Instead, perhaps, we can use a copy of the self object that doesn’t modify the self object.

If you take a look at the methods available on self, one of them is dup. This will create a shallow copy of self, you can modify the new object without a worry that you’ll modify self.

class Stack < Array
     def peek
          self.dup.pop
     end
end

Now, run the ‘spec’ command again, and you’ll get the following output:

> spec stack.rb –color –format nested

Stack
     #peek
          should return the top element
          should not remove the top element
     #pop
          should return the top element
          should remove the top element

Finished in 0.002524 seconds
4 examples, 0 failures
Great! We got our tests to work successfully!

Articles

Git Starter (Tutorial)

In Git, Tutorial on June 13, 2010 by dyba Tagged: ,

I am hard at work on a web startup with a friend of mine. So naturally, I’ve not been able to add any recent posts. I do have ideas for plenty of posts but I’m still stitching the holes in my understanding.

Working on a growing project calls for being able to keep track of all the changes in your files efficiently. Enter Git. I’ve never used Git before. I started about a month ago. Here I would like to explain just enough to get you started on keeping track of your files. If you have been copy-pasting your project directories and renaming them with last revision dates, then you can chuck that way of doing things and simplify your life with Git.

To initialize a Git repository, create a folder, CD into it, and then type:

git init

This will create a hidden .git directory in which you’ll find all of the git files.
I am using Git version 1.7.0. If you’re using this version, you’ll find the files below when you type ‘find .’ in your Terminal window:

.
./.git
./.git/branches
./.git/config
./.git/description
./.git/HEAD
./.git/hooks
./.git/hooks/applypatch-msg.sample
./.git/hooks/commit-msg.sample
./.git/hooks/post-commit.sample
./.git/hooks/post-receive.sample
./.git/hooks/post-update.sample
./.git/hooks/pre-applypatch.sample
./.git/hooks/pre-commit.sample
./.git/hooks/pre-rebase.sample
./.git/hooks/prepare-commit-msg.sample
./.git/hooks/update.sample
./.git/info
./.git/info/exclude
./.git/objects
./.git/objects/info
./.git/objects/pack
./.git/refs
./.git/refs/heads
./.git/refs/tags

We’ll now create a new file:

echo “My First File” > index.html

If you list your files, you’ll now see a file called index.html. If you now type
‘git status’, Git will tell you that index.html is not being tracked:

# On branch master
#
# Initial commit
#
# Untracked files:
# (use “git add …” to include in what will be committed)
#
# index.html
nothing added to commit but untracked files present (use “git add” to track)

If you want Git to track a file, you need to carry out the command ‘git add type_your_file_name’. In our case, we would execute the command ‘git add index.html’. If you’re adding several files, for convenience, you can type the command ‘git add .’. This will tell Git to add all the untracked files.

Before you type the previous command, let’s take a look at what’s currently inside the git/objects directory. If you type ‘find .git/objects/’ you’ll see the following:

.git/objects
.git/objects/info
.git/objects/pack

Now let’s go ahead and type ‘git add index.html’. We have now started to track index.html using Git. Let’s type ‘git status’:

# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use “git rm –cached …” to unstage)
#
# new file: index.html
#

Now let’s run the command ‘find .git/objects’:

.git/objects
.git/objects/e4
.git/objects/e4/6f9d05b91b7ea6825a94d2a5f0b6f04f409d4e
.git/objects/info
.git/objects/pack

We now have a new object. So what just happened? Git performed some operations on the contents of the index.html file, calculated its SHA1 hash, and entered the contents of the file into the object store as a file. The name of this file is the hexadecimal representation of the SHA1 hash ‘e46f9d05b91b7ea6825a94d2a5f0b6f04f409d4e’. Note also how there’s a directory called ‘e4′ and then there’s another directory with a longer hexadecimal string ’6f9d05b91b7ea6825a94d2a5f0b6f04f409d4e’. Git breaks up the first two hexadecimal numbers of the hash and creates a directory out of it. The reason it does this is to optimize searching for files. Using this technique for storing objects, Git would only have to search
through a maximum of 16 * 16 = 256 different folders during the first run through rather than searching through ‘n’ files. (Note: Every hexadecimal number has 16 possible values). But what happened to our original index.html file? Run this command ‘git cat-file -p e46f9d05b91b7ea6825a94d2a5f0b6f04f409d4e’

My First File

But that’s exactly the contents of the file index.html we created earlier. Have you noticed how often I have harped on the contents of the file as being the primary thing Git focuses on when tracking files? Let’s try an experiment. Create a new directory and call it ‘new’. If you run ‘find .git/objects’, you’ll notice that nothing has changed. Running ‘git status’ doesn’t say anything about there being a new directory. Now create a new file in the ‘new’ directory and call it ‘index.html’ and add the exact same contents you did in the first ‘index.html’ file you created. If you run ‘git status’, Git will tell you that there are untracked files under the new directory:

# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use “git rm –cached …” to unstage)
#
# new file: index.html
#
# Untracked files:
# (use “git add …” to include in what will be committed)
#
# new/

So now we’ll add new/index.html so Git can track it:

git add new/index.html

If you run ‘git status’, you’ll see this:

# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use “git rm –cached …” to unstage)
#
# new file: index.html
# new file: new/index.html
#

Now let’s run ‘find .git/objects’:

.git/objects
.git/objects/e4
.git/objects/e4/6f9d05b91b7ea6825a94d2a5f0b6f04f409d4e
.git/objects/info
.git/objects/pack

Nothing seems to have changed. Now let’s run the command ‘git ls-files -s’:

100644 e46f9d05b91b7ea6825a94d2a5f0b6f04f409d4e 0 index.html
100644 e46f9d05b91b7ea6825a94d2a5f0b6f04f409d4e 0 new/index.html

Wait a minute! Both of those files have the exact same SHA1 hash! But they’re in different folders! How’s that possible? This is because Git tracks the contents of the file. You may now be thinking, well both files have the same name, maybe these values are the same because the file names are the same. Let’s create a new folder ‘retry’. Now we’ll call this file ‘public.html’ and pass the exact same contents as the other files:

echo “My First File” > public.html

Add this file to Git so that it can be tracked.

git add retry/public.html

And now list the files Git is tracking:

100644 e46f9d05b91b7ea6825a94d2a5f0b6f04f409d4e 0 index.html
100644 e46f9d05b91b7ea6825a94d2a5f0b6f04f409d4e 0 new/index.html
100644 e46f9d05b91b7ea6825a94d2a5f0b6f04f409d4e 0 retry/public.html

The SHA1 hashes are still all identical! Ok, now you should be
convinced that Git tracks the contents of the files. So does that mean
that Git doesn’t track the pathnames of files? No, Git uses a different
object to do that. It’s called the tree object. Whenever you use the
Git add or rm command, Git updates the index. The index is found in
.git/index. When Git updates the index, it doesn’t create the tree
objects right away. The Git add and rm commands update the index with
the new pathname and contents of the file. If you want Git to create
the tree objects, you can issue the ‘git write-tree’ command. This is
a low-level command, and in practice you won’t have to do this. Instead,
using ‘git commit’ will take care of creating these tree objects.

We have simply added files from our working directory to the index, but
we have not yet added these staged files to the repository. When
you issue the ‘git commit’ command, Git will take the virtual tree objects
in the index and create real tree objects that it will store in the
.git/objects directory.

Now that we have three files in our stage, we will go ahead and commit
these changes to our repository. To do this we will issue the ‘git commit’
command. Git will then open your default editor. What Git wants you to do
is to write a short message describing what you have committed, basically
what changes have you made in this incremental step now being recorded
to the repository. You may not want to get very detailed. I would recommend writing a one line overview of what this commit involved. Then you can separate that line with an empty line followed by a more detailed explanation of what you did if you like. Once you have finished, you can close the editor and you should see the changes Git has recorded.

[master (root-commit) 9ad35aa] My First Commit
3 files changed, 3 insertions(+), 0 deletions(-)
create mode 100644 index.html
create mode 100644 new/index.html
create mode 100644 retry/public.html

If you run the ‘git status’ command, you see:

# On branch master
nothing to commit (working directory clean)

This means the working directory, the index, and the repository are all in
agreement. All three are in sync. Now run the command ‘find .git/objects’:

.git/objects
.git/objects/13
.git/objects/13/a6860ac22bfb70e28db48be830127bd21c58aa
.git/objects/43
.git/objects/43/a062c5dda49e2e95ad8824e0611de31b383ce1
.git/objects/96
.git/objects/96/eaacc865733e873198c6a381bb17617b1872f1
.git/objects/9a
.git/objects/9a/d35aa68a0fd2ca186fe366dbe94bf53f683204
.git/objects/e4
.git/objects/e4/6f9d05b91b7ea6825a94d2a5f0b6f04f409d4e
.git/objects/info
.git/objects/pack

Type the following command ‘git cat-file -p type_your_sha1_hash_value’. The SHA1 hash ‘e46f9d05b91b7ea6825a94d2a5f0b6f04f409d4e’ corresponds to the
contents of the files ‘index.html’, ‘new/index.html’, and ‘retry/public.html’
The other objects are tree and commit objects.

The first one ’13a6860ac22bfb70e28db48be830127bd21c58aa’ corresponds to the tree object that points to the file index.html under the ‘new’ folder.

The second one ’43a062c5dda49e2e95ad8824e0611de31b383ce1′
corresponds to the tree object that points to the file public.html under the ‘retry’ folder.

The third object ’96eaacc865733e873198c6a381bb17617b1872f1′ points to three objects: index.html, the ‘new’ directory, and the ‘retry’ directory. This is the output:

100644 blob e46f9d05b91b7ea6825a94d2a5f0b6f04f409d4e index.html
040000 tree 13a6860ac22bfb70e28db48be830127bd21c58aa new
040000 tree 43a062c5dda49e2e95ad8824e0611de31b383ce1 retry

Notice that this object contains three data unlike the other objects. You can also see that it contains objects we’ve already seen.

The last object is a commit object. When you run ‘git cat-file -p 9ad35aa68a0fd2ca186fe366dbe94bf53f683204′, you see the text below:

tree 96eaacc865733e873198c6a381bb17617b1872f1
author Daniel Dyba 1276451901 -0700
committer Daniel Dyba 1276451901 -0700

My First Commit

Notice how the tree object information is contained in this commit object. Using this object, you can build a visual diagram that looks like this:

Now, to use Git at the beginner level, you want to follow the process of creating files, adding these files to the index using the ‘git add’ command, and finally committing your changes using the ‘git commit’ command to synchronize the working directory, index, and repository.

Articles

Ruby script to connect to MySQL database

In mysql, ruby on March 3, 2010 by dyba Tagged: ,

In this screencast, I’ll be writing a Ruby script to connect to a MySQL database. I’m using Ruby version 1.8.7 and the mysql gem version 2.8.1. To see this video with optimum quality, view it in HD.

Here’s the code. Save this to a file called mysql-01.rb. Find the correct directory and using the Terminal on a Mac OS X, type ruby mysql-01.rb.

require 'mysql'
begin
  db = Mysql.real_connect("localhost", "test", "testpass", "test")
  puts "Server version: " + db.get_server_info
rescue Mysql::Error => e
  puts "Error code: #{e.errno}"
  puts "Error message: #{e.error}"
  puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate")
ensure
  db.close if db
end

If you get any errors while trying to do this, check to make sure that you have turned on your MySQL server. Also if you have not set rubygems to be the value of your RUBYOPT variable in the environment variables on your machine, you’ll get errors when you try to run the command ‘ruby mysql-01.rb’ in the Terminal window.

Follow

Get every new post delivered to your Inbox.