We are using Tarantula as an additional form of testing within our last project, Tarantula is called during a cruise control task to ensure that the application works also with realistic data (taken from the production database during the night).
The main problem we found in this approach was how to stop the crawler before it finish to load all the possible links collected during the session. This was critical for us ‘cause the web application currently handles thousands of elements and we could not wait hours.
So we chose to patch Tarantula in order to:
let the spider follow links in a random order
stop the spider after a configurable period of time (eg: 10 min)
Here’s the crawler.rb you’ll need to put under ‘lib/relevance/tarantula/’ in order to obtain this effect, then you can change two instance_variables: test_max_time_links and test_max_time_forms in order to choose how many minutes the spider will spend on these elements.
In the next days we’ll fork the Tarantula projects in order to better share this new behavior.
If you still have some of your rails applications in Rails 2.1, here is how to start migrating to Rails 2.3 and take advantage of the new features….
Firstly, create a branch of your application
svn checkout path_of_application
Delete your current rails folder from vendor/rails from your branched application (if you had frozen rails into your app before)
Install the Rails 2.3.2 framework and then freeze it into your application with these two commands:
create a sample rails 2.3 application, then copy all the missing the config/initializers/ files from the test application to your branched application such as the session_store.rb, then copy the secret key from the environment.rb file into this file. This is to keep the environment.rb file small, braking parts into the config/initializers/ files
Remember to change your Rails version in your environment.rb file to Rails 2.3.2
rename your application.rb file to application_controller.rb or run
rails:update:application_controller
formatted urls
formatted_ * are no longer supported in the route helper due to using too much memory:
formatted_users_path(:format => 'xml') changed to users_path(:format => 'xml')
Internationalization
If you have used the globalization gem, it will no longer be compatible in Rails 2.3. Rails has now built in I18n Internationalization. (read more about internationalization)
The old way:
The new way:
In the config/locales/en.yml file we have the following:
The text is retrieved from these files, as well as if you have other languages such as italian, just create an it.yml file and replace the text with the translated text.
Hope this will help when you migrate to Rails 2.3….
Euroko’s 2009 is over and in these few lines I’ll try to summarize two days full of sessions,
laughs and Ruby. Everything started with Matz’s opening speech which focuses on ‘Things we got’ explaining why Ruby’s got all the features a good language need (starting from the name), what are the next steps in the core development and why we don’t need to rush in the future.
During the day I found two very interesting speeches: one from Javier Ramirez that told us about Gosu, an enjoyable and pretty powerful gaming framework suitable for Ruby which can also be combined with Chipmunk (a physics engine) in order to obtain
awesome effects and collisions.
The day ends up (at least for me ‘cause I know some guys went partying somewhere) with a very
nice stand up dinner made with delicious catalan ‘Jamon y Queso’ .
Sunday comes with an exceptional list of talks that impressed me much, starting from Adhearsion:
a framework crafted to help people deploy applications that need to interact with Asterisk servers. The presentation was really cool and comprised a live coding demo which showed us how to write simple voice-enabled applications (with menus and digit recognition). After a short coffee break we met Adam Blum and Rhodes, a framework that let you create mobile applications for almost
any existing smartphone using Ruby as coding language and HTML for creating views.
Then it was the turn of Pablo Formoso Estrada; his talk focused on Archaeopteryx which make the whole conference dance and
clap their hands at the rhythm of a Ruby-driven runtime midi generator at which Pablo made adjustment
just like a dj does with disks. Aslak Hellesøy then performed a good presentation explaining us what is Cucumber (a tool that helps creating semantic and readable tests written in human language) and showing us its latest features.
The last cool speech of the day was helded by Tomasz Stachewicz and focused on RuDy , a tool that lets you create
Ruby extensions in D. The whole presentation was made to look like Antonietti’s much discussed
‘Perfoming like a Pr0n star’ but with ‘rock’ instead of ‘porn’, the result was very hilarious and it’s definitively worth a look.
And.. that’s it! Hope you enjoyed this summary and… see you next year in Krakovia!
Within the project we’re developing we found ourselves pretty attracted from the features offered by Selenium so we started to use its beautiful IDE to create behavioral tests that try to ensure our quality requirements.
But soon we discovered that manually aggregating and running these tests often lead to problems: first of all you don’t really have the same data on your developer instance each time you run Selenium so it happens that a particular business object is no more present or has been already, let’s say, processed and that means failure.
So we decide to move all the test we created to our CruiseControl.rb instance. To do that we followed these steps:
Create a Selenium startup script by following this good post from Mohammed Morsi;
Save your Selenium IDE tests as Unit Test File (File > Export Test Case As.. > Ruby) and copy them under your application tests/unit directory;
Put this piece of code within your ‘custom_cc.rake’ file
begin
puts "="*10 + "SELENIUM TESTS" + "="*10
Kernel.system "ruby","script/server","-d","-e","development","-p","3000"
CruiseControl::invoke_rake_task 'test:units'
rescue => e
@test_errors << e
end
Kernel.system "killall","ruby"
end
Hi, It’s been a while since my last post, I apologize but I have been really busy with coding and testing (Cucumber is awesome!) for a quite important project. Within these days I came across this interesting trick that lets me discover how to return a ready-for-find options hash from a named_scope and also from an association.
So, let’s take this (simple) named scope for example:
named_scope :name, lambda do |query|
firstname, lastname = query.split(" ")
{:conditions=>{:firstname =>firstname, :lastname => lastname}}
end
By calling the method ‘proxy_options’ after the scope you’ll be able to retrieve the generated options Hash:
As I mentioned last week, I am busy doing an upgrade of WhoDo.es from Rails 1.2.2 to Rails 2.3 and it is slowly sowly coming together, still have to do a lot of modifications for internationalization.
In my search for any help, I came across a very good step-by-step guide from Peter Marklund that might help someone if they might have a similar quest!
Hope it might be useful for someone else. Please follow the link here
I am currently working on Migrating WhoDo.es from Rails 1.2.2 to Rails 2.3.
My first steps were to migrate from Rails 1.2.2 to Rails 2.0 and no real big issues were faced, I only had to make sure that the gems that we were using were compatible with Rails 2.0.
Some of the following configurations had to be done:
Updated environments.rb with RAILS_GEM_VERSION = ‘2.0.2’
run rake rails:update:configs to update your config/boot.rb file from your current rails install.
In my config/environment/development.rb commenting out the following :
Introduction to ObjectiveResource, the open source framework that connects the iPhone to the Ruby on Rails application
ObjectiveResource is a library that is written in Objective-C by YFactorial the purpose is to facilitate the integration between Ruby on Rails applications and programs for the iPhone.
As declared from the developers, the project starts from the idea to carry the potential of the module ActiveResource of Rails onto the iPhone .
The library supplies a system that is able to serialize the objects from and to web services RESTful standard of Rails (through XML o JSON) and makes the complexity requested transparent to invoke such as services from any programming language used on the iPhone.
Even if the library was recently released and is still under continues development, it is evident that the effort done by the developers in search of covering the functionality of ActiveResource and in the supply of an interface utilized along side fully conforms to the subsystem of Cocoa used as the management of the persistence of data, better known as Core Data as complete as possible in the world.
On the website dedicated to ObjectiveResource an introductive guide is available, quite useful just to give you an idea. It is also possible to download a project example that explains how simple and quick it is to use.
ObjectiveResource adds some methods to the class NSObject through the category NSObject(ObjectiveResource), in such a way that each instance of the Objective-C class can act from remote resource.
The name of the class and the name of the property must coincide with those from the remote resources of the Rails application. Given that the id is a reserved word in Objective-C, the property id of a Rails resource is mapped in Objective-C on a property, which name is composed from name of the class followed by suffix Id (like this for the class Dog such a property will be dogId)
The following code shows a Dog class that maps the correspondent Rails resource:
@interface Dog : NSObject {
NSString *name;
NSString *dogId;
}
@property (non-atomic , retain) NSString *name;
// map the property "id" of Rails
@property (non-atomic , retain) NSString *dogId;
@end
To use the library it is necessary for us to put certain parameters in the ObjectiveResourceConfig class:
//Set the Rails website. The last slash is mandatory.
[ObjectiveResourceConfig setSite:@"http://localhost:3000/"];
//Set the username and password requested to connect to the Rails site
[ObjectiveResourceConfig setUser:@"remoteResourceUserName"];
[ObjectiveResourceConfig setPassword:@"remoteResourcePassword"];
//Set the protocol to use for remote communication(XML o JSON)
[ObjectiveResourceConfig setResponseType:XmlResponse];//il default
[ObjectiveResourceConfig setResponseType:JSONResponse];
Other than ObjectiveResource, connected resources are also supported.
For example to find all the dogs that belongs to one person, you only need to add the following method for the Dog class:
+ (NSArray *)findAllForPersonWithId:(NSString *)personId {
//using the generation method of the URL of ObjectiveResource to
//construct the path nested.
//http://localhost:3000/persons/:person_id/dogs.xml
NSString *dogPersonPath = [NSString stringWithFormat:@"%@%@/%@/%@%@",
[self getRemoteSite],
[Person getRemoteCollectionName],
personId,
[self getRemoteCollectionName],
[self getRemoteProtocolExtension]];
Response *res = [Connection get:dogPersonPath withUser:[[self class] getUser]
andPassword:[[self class] getPassword]];
return [self allFromXMLData:res.body];
}
The non CRUD custom actions are also supported.
This is how you implement a method pet in the class Dog, that points to the URLhttp://localhost:3000/dogs/1/pet.xml:
- (void) pet {
//Construct the path to the custom action pet
NSString *petPath = [NSString stringWithFormat:@"%@%@/%@/pet%@",
[Dog getRemoteSite],
[Dog getRemoteCollectionName],
dogId,
[Dog getRemoteProtocolExtension]];
//Send the request
Response *res = [Connection get:petPath withUser:[[self class] getUser]
andPassword:[[self class] getPassword]];
//Modify the property with the values restored from the server
[self setProperties:[[Dog fromXMLData:res.body] properties];
}
@interface Dog : NSObject {
NSString *name;
NSString *dogId;
}
@property (nonatomic , retain) NSString *name;
@property (nonatomic , retain) NSString *dogId;
@end
#import "ObjectiveResourceConfig.h"
[ObjectiveResourceConfig setSite:@"http://localhost:3000"];
NSArray *dogs = [Dog findAllRemote];
To complete this example, the developers have made a short screencast available on vimeo and have announced that the next tutorial published is on Pragmatic Programmers:.
Although some applications already exist that uses ObjectiveResource, as they indicate on the project website, the library still has enough margins for improvement.
An idea could be to implement an automatic system generation of class files, that maps the resources of the Rails application.
You can create a script in Ruby that is able to reduce the property such as classes navigating the website, or better, using the Rails API directly.
The opinion of ObjectiveResource can only be positive: good idea, good projecting and careful implementation. Welcoming instruments that facilitate integration between the world of web and mobile devices such as iPhone.
The opportunity that this library offers are interesting and many. Think of a possible example to simply develop functional applications for the iPhone, that makes it possible directly in real-time on the terminal of the user an altogether well-defined and limited to updated data (for example earnings of the quotations, on the variation of prices, on the unsold goods, ...) without having to develop the mobile version of the whole application.
At the end of this library it allows you to quickly develop with Ruby on Rails to the flexibility of the utilization of the iPhone: agility to the nth power!
Today I come up to Scrubyt, an excellent piece of code developed by Peter Szinek, Glenn Gillen and a bunch of other collaborators. What this software do is essentially fetch and operate on XML/HTML pages, here’s an example taken from the official website:
require 'rubygems'
require 'scrubyt'
ebay_data = Scrubyt::Extractor.define do
fetch 'http://www.ebay.com/'
fill_textfield 'satitle', 'ipod'
submit
record "//table[@class='nol']" do
name "//td[@class='details']/div/a"
end
end
puts ebay_data.to_xml
In this ten lines of code (including the two ‘require’ on top of the page) we fetch ‘ebay.com’ website, then we fill a textfield with the id ‘satitle’ with the text ‘ipod’ and we press the submit button. Next we create a container (named ‘record’) for each table with class ‘nol’ of the returning page (the page containing the results from our ‘ipod’ search) and we fill this container with a ‘name’ variable containing the text within an ‘A’ element incapsulated inside a td with class ‘details’.
If we print the result as xml (as we do in the last line) this will be the output (truncated):
<root>
<record>
<name>USB 2.0 Sync Data Cable for iPhone 3G iPod Mini NanoPOWER SELLER-30 DAYS MONEY BACK GUARANTEE-FAST SHIPPING$1.99Free shipping22d&#160;5h&#160;50m</name>
</record>
<record>
<name>EnlargePIONEER 5.8" GPS NEW AVIC-F90BT DVD MP3 IPOD AVICF90BT!!! HAS THE NEW 2.0 UPDATE INSTALLED !!!!! 2.0 UPDATE$637.00Free shipping9d&#160;5h&#160;35m</name>
</record>
<record>
...
In conclusion, this is a very nice and handy toy that can help us during deployment and test.
If we consider the business world, since the Blackberry was released in 2002, it broadened the use of IT in the business world. Receiving e-mail on your smartphone and being able to be updated in real-time was a useful tool for everyone.
But then came along the iPhone….
The iPhone changed the whole game of the smartphone. Not only is it an interesting little device that allows you to be updated with your e-mail, organize your appointments, manage what you need to do but so many more applications are being developed that have reached the top of the top 25 list of apps to have. Like the new Google voice search application
that enables you to search a website using your voice, but I have tried it and maybe it didn’t like my voice…
iPhone applications have created another dimension in the development of web applications, not only to develop web 2.0 applications in Ruby on Rails but for our applications to be successful and competing within the current market, we need to develop iPhone web applications that are synchronized with our web applications. A simple to-do list application is much more useful if you can view it on your iPhone and manage it from there too.
But then I ask myself…
is it better to develop iPhone web applications or native applications?
Some advantages of web applications :
web based therefore can be cross -browsered
it can be used with other smartphones and not only for the iPhone
While installing Globalize I stumbled upon the plug in’s table structure. If we look at the ‘tr_key’ field inside the table ‘globalize_translations’ we may notice that this field type is ‘VARCHAR (255)’ (obviously only under mysql but I think this
is the database chosen by the majority of rails developers).
Hey, but isn’t this column the one holding the strings to be translated?
The answer is (ASAIK) yes, in fact if we look inside file ‘view_translation.rb’ (inside the plug in’s models’ folder) we spot this piece of code:
def self.pick(key, language, idx, namespace = nil)
conditions = 'tr_key = ? AND language_id = ? AND pluralization_index = ?'
namespace_condition = namespace ? ' AND namespace = ?' : ' AND namespace IS NULL'
conditions << namespace_condition
find(:first, :conditions => [conditions,*[key, language.id, idx, namespace].compact])
end
Wow, the ‘tr_key’ is used also to store and (as shown here) retrieve translations from the db; but what happens if the string I’m trying to translate exceed the 255 chars limit?. Simple, the string get saved on the database truncated at its 255th character, then when the plug in try to search for this string obviously it didn’t find anything (‘cause it’s looking for the whole string, not its first 255 chars); the result? A string longer than 255 chars never get translated plus it creates a duplicate row each time is called its ‘t’ method.
The fix I coded is pretty easy:
def self.pick(key, language, idx, namespace = nil)
conditions = 'tr_key = ? AND language_id = ? AND pluralization_index = ?'
namespace_condition = namespace ? ' AND namespace = ?' : ' AND namespace IS NULL'
conditions << namespace_condition
find(:first, :conditions => [conditions,*[key[0...256], language.id, idx, namespace].compact])
end
In this way you just need to be aware of long string with the first 255 chars in common; but this is quite rare, so you can easily ignore it.
With the release of Googles browser Chrome, as Web Developers I think we could take a few pointers that I am sure we all know about but sometimes we need to be reminded.
Technology
Google wanted to introduce a browser that had multiprocess architecture. Other browsers, if one of the tabs crash the whole browser crashes. In our web applications we need to take advantage of new technology like Rails 2.2 and develop applications that are innovative making use of technology to develop new concepts and ways of solving a problem.
We need to identify critical factors of the applications and understand how we will solve them, using existing plugins, gems or developing our own solution to solve the problem.
Keeping it simple and use only the technology that is needed. Redundant use of gems, plugins or scripts will slow down or application let alone the time spent to implement them.
Who is to blame?
As google puts it “Placing blame were blame belongs”.
Why did a web application fail? I think there are many factors that could lead to a project failing, one of the important factors is that not enough planning and brainstorming has been done before starting a project. We jump right into the code without understanding the concept and setting or goals on what we want to achieve.
Not having the technology available at the time. For example, with Rails, what is introduced in Rails 2.2 did not exist in previous versions of Rails.
Eliminate factors of a project that didn’t work before and develop a strategy on what can be done to improve them and how.
Testing
Testing is crucial as in the long run, it will save time and money. Doing continuous testing on a project will enable you to see come across errors sooner, being able to correct them immediately, saving time and cost from the start of development.
Develop a test analysis, identifying various testing paths that we need to do to test the application and be obedient to implement these test strategies.
Useful tools
Use useful tools at our disposal. Google used V8 or we could use WebKit. These tools help us develop faster and discover errors quicker. So much time is spent on testing, with the use of useful tools, we can develop applications faster, leaving more time for perfecting.
References for this article was taken from Google chrome
We come up with this solution after a couple of failing attempt to find a way to emulate a redirect_to method without actually create a 302 HTTP message which need to be sent to the user and then back to the application.
By using this internal_redirect_to function you will be able to get the same results as a normal redirect_to without send anything to the user, only keep in mind to explicit invoke the return after this function.
def internal_redirect_to (options={})
params.merge!(options)
(c = ActionController.const_get(Inflector.classify("#{params[:controller]}_controller")).new).process(request,response)
c.instance_variables.each{|v| self.instance_variable_set(v,c.instance_variable_get(v))}
end
Note: this function must be placed inside the calling controller.
Then you can simply invoke this function by typing:
MasterController < ApplicationController
def index
internal_redirect_to :controller=>'another', :action=>'an_action'
return
end
end
By mixing some good posts (this, this and also this) we were able to create a :cruise task that:
Check ruby, yaml and erb code syntax;
Run all rspec tests;
Check for code quality.
To use this task simply download ‘custom_cc.rake’ inside your app/lib/tasks folder. The next time CruiseControl.rb builds your application this task will be executed instead the standard one.
A note:
Don’t try to include the roodi gem inside your application; that was one of our first mistakes we did as Roodi requires facets and this gem seems to break things up inside Rails. That’s why we decided to call this quality checker using the Kernel.exec method.