Test for blank elements with Culerity-Cucumber

When you need to test for blank elements on Culerity, it is better to parse the html. Using Celerity helper methods such as $browser.button will return a Culerity::RemoteObjectProxy object. It does not tell you if it found an element or not. It is a limitation of Culerity. To work around it try this: You can use the above code in the step definitions.

How to shoot yourself in the foot using a functional programming language

While preparing for a presentation on Scala, I added some jokes on the functional languages. Here's the original version and the new editions Erlang You create a dozen clones of youself, pass the gun to one another in turn to shoot at each other's foot Python You have to align your foot 10 steps below the gun for it to work Ruby You pull the trigger to find popcorns popping out of the gun. Someone somewhere has just made all guns shoot popcorns. Haskell Close your eyes and picture a gun in your mind. Think about the foot being shot. Open your eyes. You found your foot shot. No sound. No smell. No one else even noticed. Scala You pull the trigger and you got shot. You stab your foot with the gun and you got shot.

Using Cucumber to test Paperclip file attachments

I was using thoughtbot's paperclip to attach files. I realised that paperclip only provide shoulda macros for test::unit. No cucumber macros? In the end, I got to write it. Its very simple. The feature is shown here: Define your steps: As celerity does not have an attach_file method, I got to write my own. You could see it's not hard at all. Remember to define the browser variable. Last, we have some hooks to clean up the test upload files. Remember to place an @upload tag in your scenario.

Email_Spec Integrated with Action_Mailer_Cache_Delivery

For people using the action mailer cache delivery plugin, you can now add the email_spec plugin. The email_spec plugin provides many wonderful helpers to test your emails. Both plugins are now integrated. To use them you need to install both my forks of the plugins: Install them as plugins following the same instructions from the README. Don't forget to change the git url!

Persistent Cookie Authentication Gem Documentation

Media_httpliangzannet_cemld

What are persistent cookies? What are persistent cookies used for?

A persistent cookie is no different from other cookies. What is different is that it is used to identify users. With identification, it enables a website to remember you on subsequent visits, speeding up or enhancing your experience of services or functions offered. For example, a website may offer its contents in different languages. On your first visit, you may choose to have the content delivered in French and the site may record that preference in a persistent cookie set on your browser. When you revisit that site it will use the cookie to ensure that the content is delivered in French.

Why do I need it?

The biggest advantage is we can skip the registration step. We use persistent cookies to identify users. Users can be anonymous first time visitors or registered users. When we're able to identify them(especially anonymous users), we can keep data like what items the user has placed on her cart. For e-commerce sites, you may not want to force the first time anonymous users to register when they try to place items in the cart. Some may be turned off and go away. By using persistent cookies to identify them, we can save which items they want without making them go through the registration process. You can make them register when its time to make payment.

How do I use them?

To use persistent cookies effectively, we're segregating the web site into 3 levels of access.
  • Public - anyone can go in. Examples would include your index page and FAQ
  • Protected - cookie authenticated.
  • Private - user must log in.
In your controllers, place a before_filter to identify which actions is private/protected
before_filter :cookie_required, :only => [:some_actions]
before_filter :login_required, :only => [:some_actions]
Use :cookie_required for protected actions, and :login_required for private areas.

How do I identify the users?

If you have seen through the code, there're actually 3 models controlling the authentication system: identity, login_cookies and users.
  • Identity - the unique identifier used to identify users. All users only have one identity, be it anonymous or registered users.
  • Login_cookie - the cookies used for identifying the users.
  • User - for identifying registered users.
One unique identity can have many Cookies, but only one User. So when you want to link to the user, use the Identity model instead. For example, you want to create a relationship where a user has many books:
class Identity 
Whenever your controllers need to link to the user, do it through the identity instead.

@identity.user
What if the user's browser did not enable cookies?
Good question. If that happens, we will treat the protected region as private automatically. There's no need for you to handle it. The code is created to degrade gracefully.
Implementation of persistent cookie authentication
The implementation is as suggested by Barry Jaspan and Charles Miller. In fact, Drupal's Persistent Login Module follows this set of implementation.
Special cases
There's a special case you need to take note. For example, an anonymous user comes to your site, and place a few items on the cart. And then she registers as a new user. Will the data in her shopping cart be lost?  The gem will ensure that her cookie entry and her newly registered user entry will be transferred to the same identity. But as I do not know how your website will be implemented, I did not implement the merging of the data from her cart. You'll need to add your code to transfer the data to her new identity. An example of the implementation is here. You'll need to modify the merge_identity function from user_controller.rb  From app/controllers/user_controller.rb

def mergeIdentity(anonymousCookieValue, knownIdentityID)
if anonymousCookieValue == nil || knownIdentityID == nil
return false
end

return false if !LoginCookie.isAnonymous(anonymousCookieValue)
loginValue = LoginCookie.getCookieLogin(anonymousCookieValue)

#getting the both anonymous user's identity and the known identity
anonymousCookie = LoginCookie.find(:first, :conditions => ["login = ?", loginValue])
anonymousIdentity = anonymousCookie.identity
knownIdentity = Identity.find(knownIdentityID)
return false if anonymousIdentity == nil || knownIdentity == nil

#transferring the cookies
anonymousIdentity.login_cookies.each { |cookie|
cookie.identity_id = knownIdentity.id
cookie.save
}

#transferring the cards
anonymousIdentity.cards.each { |card|
card.identity_id = knownIdentity.id
card.save
}

#finally send the identity to its grave
anonymousIdentity.destroy

return true

end
This is about all you will need to know to implement the persistent cookie authentication system effectively. Any bugs or unclear points, feel free to contact me.

Persistent Cookie Authentication Generator

Media_httpliangzannet_bqgjj

This is a Rails gem that I wrote, or rather extracted from the codebase from hushyhushy.com. OK, what is PersistentCookie Authentication Generator? This gem is a code generator.  This generator creates an authentication system with persistent cookie management. Feature include
  • a model which uses SHA1 encryption and salted hashes for passwords
  • a controller with signup, login, welcome and logoff actions
  • gmail smtp server integration
  • account creation that requires account verification via email
  • supports forgotten and changed passwords
  • a mixin which lets you easily add advanced authentication features to your abstract base controller
  • extensive unit and functional test cases to make sure nothing breaks.
  • token based authentication
  • persistent cookie management that allows anonymous users to be authenticated via cookies
Actually the code is heavily modified from another well known gem: salted hash login generator To put it simply, it is

persistent_cookie_authentication = salted_hash_login - localization + persistent_cookie_management

The code is written with an emphasis on simplicity. No effort is made from me to write clever or DRY(don't repeat yourself) code. The intention is to dumb it down so that people using it could understand it. As Joel says, abstraction is bad.

Media_httpliangzannet_cdozo

Here's the installation instructions: To install, run this line on the shell
gem install persistent_cookie_authentication_generator
From the directory of your Rails app, run this from the shell
ruby script/generate persistent_cookie_authentication
Change your config/database.yml settings. Then update your database by running
rake db:migrate
From app/controllers/application.rb, add this within application.rb
include UserSystem
Example application.rb From config/environment.rb, add this at the end of the file
require 'environments/user_environment'
require 'smtp_tls'
Example environment.rb From config/environments/, add this to the end of both development.rb and production.rb
ActionMailer::Base.smtp_settings = {:address => "smtp.gmail.com",
:port => "587",
:domain => "localhost.localdomain",
:authentication => :plain,
:user_name => "yourgmailusername",
:password => "yourgmailpassword"
}
Example development.rb From config/initializers/inflections.rb, modify your inflections.rb to look like this
Inflector.inflections do |inflect|#   inflect.plural /^(ox)$/i, '1en'
#   inflect.singular /^(ox)en/i, '1'
#   inflect.irregular 'person', 'people'
#   inflect.uncountable %w( fish sheep )
inflect.irregular 'LoginCookie', 'LoginCookies'
end
To test, run this from your shell
rake db:test:clone
rake test
From config/user_environment.rb, change the name of your Rails app to your liking That's it. Another post will cover how to use persistent login cookies. Bug reports please contact me directly at my email address. *Update: Here's the slides I've presented at the Singapore Ruby Meeting

InvalidAuthenticityToken and Session Expiry

This is something that I've discovered as I was building hushyhushy. After I upgraded to Rails 2, I began using authenticity tokens. So far so good. But in the course of testing the app, I would encounter the infamous 'InvalidAuthenticityToken Error'. That's weird! It usually happened in the middle of testing the app, and after some time too. It means that my authentication token was working fine, but somehow or rather it just failed in mid air. Then I realised the reason after some investigation. The reason is that my session expired. The session id changed. The authentication token is tied to the session id. So it became invalid. I did set my sessions to expire. I hope this helps for those who encountered the same problems as me. The obvious solutions that I can think of is:
  • prevent the session from expiring
  • lengthen the session expiration time
  • reset the authentication token
Here's how you would set the session expiration time in config/environment.rb
ActionController::Base.session_options[:session_expires] = 10.minutes.from_now
The best solution is to reset the authentication token. I tried doing that with form_authentication_token(), but I wasn't too successful. I'll try again and update this post if I am successful.

Postman Rails Plugin

Media_httpliangzannet_bnrbm

This plugin is calculates the shipping rate for a given location and weight. It is useful for cases where the postal service in your country doesn't provide APIs for calculating shipping rates. This is actually extracted code from my website hushyhushy.com. I needed some sort of a calculator for shipping rates. But there isn't any. Those available are meant for USPS, Fedex, UPS, you know the Big & Expensive mail carriers. Not suitable for poor folks like me. They have nice APIs which makes writing your own calculator code superfluous. The code is ridiculously simple. I even find it embarrassing. Well, why code when you have the database doing all the heavy lifting for you? Here's the project URL: rails-postman This is my first Rails plugin. So if you find any bugs, please yell at me! Do forgive me after that. Hahaha... Anyway, there's another plugin coming from the hushyhushy code. That one is more complicated. But definitely more useful.