Archive for June, 2009

My Ruby on Rails dev environment

My dev environment for Ruby is currently this:

Set up:
1. Windows Vista. I’m probably the only developer who likes Vista, but actually it behaved without problems for me from the start.
2. Ruby 1.8 + Rails 2.3.2.
3. sqlite3 – More than enough for the development purposes

IDE:
1. cmd window 1 – Web Server (ruby script/server). Usually runs in the background, but sometimes useful to see the database queries, no need to open the log.
2. cmd window 2 – Rails project directory. There I can quickly run Rails command-line commands, edit some text files, etc.
3. cmd window 3 – sqlite3.exe (dbconsole) for quick check ups on the data
4. Google Chrome browser – much faster than IE and the ever-bloated Mozilla.
5. E-texteditor. A “clone” of Mac’s favorite textmate. My version is a bit buggy and crashes if you try to write macros, plus I am not using bundles at all, but it still is the most pleasant way to write RoR code (an alternative was Aptana Studio, but when it crashed without any notice I decided against using it).

June 29, 2009 at 10:27 pm 8 comments

Learning to read Ruby on Rails code – a cheatsheet for absolute beginners

Ok, I wish somebody made this post when I was just learning Ruby on Rails, so enjoy πŸ˜‰ This is version 1.0, so if you find any errors or want an extension, let me know:

1. @variable – @ sign is an indicator of an instance variable. Actually it’s incorrect, as Ruby does not have variables, it has only Classes and their instances. So for example assigning like this: @some_string = “some text” makes @some_string an instance of a String class. And it makes it possible to access methods for this class. So you can use @some_string.length to get a length of a string. There’s also the @@variable, which is a class-level variable (accessible by anywhere within the class), also quite rare.

2. No “;” needed. You do not need to explicitly finish each line with a semi-colon, unless you want to write multiple operators on a single line, like this: a = 5; puts a; puts a+5;

You can also use “\” for continuation of a line. There is a related notation that you might see which is:

something = longname + anotherlongname \
+ z

“\” is used to indicate to Ruby that the line continues, if the continuation is ambiguous, like in the example above.

3. = and ==. Just as in PHP, the first is for assignment, the second is testing equality.

4. “some text #{@variable} and some more text” – use this to insert variables or actually any(!) ruby expression, eg. #{2*@variable} or #{@variable.capitalize} will work too. The parsing happens only for “quotes”, not the ‘quotes’. Also, if you are simply referring to a variable you can omit the curly brackets, so just use ” some text #@variable and more text”

5. $variable – a Global variable, same meaning as in PHP. Rarely seen in the Ruby on Rails world.

6. something.blank? – a “?” is just a part of the method “blank?” name. What makes it useful is that you can understand that this method returns a boolean.

7. something.do! – Again, just a part of the method but indicates that this is a more dangerous version of a normal method. A standard example – @array.sort – will return a new sorted array, whereas @array.sort! will resort the existing @array, modifying it.

8. variable – a local variable is without any variable indicator. Actually, this is probably the most confusing notation for novices as variables (really objects or instances) and method calls can look the same.

9. Constant – constant is any name capitalized (!). Constants in Ruby can actually be changed, but you will get a warning.

10. something.method – easy to guess, what comes after the dot is a method call. Method call can omit the brackets, so when usually you would write something.method(), in Ruby you don’t have to. Also Ruby is very flexible in the use of brackets even if you pass parameters to it, so…

11. link_to “Artist”, artists_path – So link_to is a method and brackets are omitted. You could just as well write link_to(“Artist”, artists_path). Bracket omission is very common in Ruby on Rails. For example belongs_to :person is the equivalent to belongs_to(:person), but you would rarely see the latter notation.

12. curly brackets { } – these are most of the time an indicator of a block, but will also be used for hashes (more on them later). More on blocks here.

13. @array[0] or array[0] or string[0], etc. – This is similar to PHP, so you should not have a problem with that, this is a notation to access the elements of the array.

14. 1..10 – this is a range from 1 to 10. And this 1…10 is the same range, but excluding 10.

15. {1=>”one”, 2=>”two”} – this is a hash definition.

16. :some_symbol – Ok, one of the more confusing things, a symbol is used pretty heavily in Rails. Think of it as a name without a value. You might ask why not use “some_value” instead of :some_value. As I understood, it all goes in the treatment of “some_value” by Ruby – it takes more memory to store this instead of a symbol and has more overhead, as “some_value” is also an instance of a String (don’t believe me? test it – “some value”.class), and you can write things like “some_value”.length. Another thing you will get used to is that :some_value is a good indicator of a parameter.

17. # – This is for comments. Simple enough. The multiline comments do not exist in Ruby, so the best way is to use a “false” block, like this: if false do … some code you want to comment out.. end

18. @variable = “something” if @othervariable.blank? – This is actually quite easy to read, it’s called “if modifier”. It’s the same as saying if @othervariable.blank? then @variable = “something” end. So, the modifier saves you typing 7 characters and looks more natural language-like. The modifier can be used only for simple one-line operators, but it’s very common in Ruby on Rails. You can use the same logic for the unless or while operators, which is the opposite of if in that case.

19. def methodname..end – this is the definition of a method. Again, simple enough. def self.methodname..end is a definition of a singleton method (a method that cannot be called on an instance, only on the class itself).

20. method.each or @variable.each – a very common iterator that usually comes with a block. For example, if you want to go through each item in an array and display it, you will write something like this: @some_array.each { |item| puts item }

21. class Artist < ActiveRecord::Base
This is a class definition for Artist. “<" means that it's a subclass of ActiveRecord::Base. "::" means that Base is a class within the ActiveRecord module.

22. SomeClass::CONSTANT – Class can define a constant and you will access it that way.

23. <% ruby code here %> – same as <? php code ?> – allows to use inline ruby in the templates.

24. <%= ruby code here %> – same as <?= php code ?> – uses inline ruby and outputs the result in the browser. You can also comment out inline ruby like this: <%#= ruby code here %>. Finally, you might also see this: <%= … -%>, it just removes unnecessary white space from the inline ruby, so that the output HTML is prettier.

25. =~ – this is a Ruby operator for pattern matching. It’s not available for most variable types, but can be used for strings.

26. @array << “here is another item for you” – this is how you can append to many types of variables, including strings and arrays.

27. x==1 ? y:z – conditionals. If x == 1 then y else z

28. %w[this is a test] # Same as: [‘this’, ‘is’, ‘a’, ‘test’] – This example is lifted from the great Ruby Programming Language book. A quick way to create an array out of a space delimited string. There is also a %W which will create an array with “items” instead of %w ‘items’. (See above for the difference in “string” and ‘string’).

29. Implicit method return. Justin adds:

A method automatically returns whatever the last value is, eg.

def multiplyTwo x
x * 2
end

the result of β€˜x * 2β€² is returned from the method, you don’t have to explicitly use the return keyword

30. True / false definitions. Nil and false return false, while everything else returns true. So 0, 1, “” will all return true, for example.

31. variable ||= “hello”. This operator is very often used, basically what it means – assign “hello” to variable if it’s not defined / nil and do nothing if it’s not nil. Good way to initialize variables.

32. User.name rescue nil. This notation is used to get around the NoMethod Ruby error. If name is not defined, the exception is rescued and nil is returned. This is now somewhat deprecated, as you can use try (comes with Rails 2.3.2) or andand methods (here’s the info).

33. something.each(&:some_method). This can be seen in the Rails code and is a short notation for a simple block like this:

# The same as people.collect { |p| p.name }
  people.collect(&:name)

June 28, 2009 at 11:24 am 11 comments

Split a string in two (or three)

@lat, @lng, @zoom = @location.split(',')

This simple line will take the string @location, split it based on the comma into three strings. If location is “a,b”, then @zoom will be empty.

You will need to validate your user’s input of course, but it’s one of the ways how Ruby makes some basic tasks easy.

June 27, 2009 at 10:07 am Leave a comment

Google Maps API in Rails (YM4R-GM) – Part II: Usage

Environment: Rails 2.3.2, Windows Vista, SQLite3 development on a local box

Using the YM4R is pretty simple. Here’s what you need to do:

1 – In your controller you need to add the following lines:

@map = GMap.new("map_div")
@map.control_init(:large_map =&gt; true,:map_type =&gt; true)
@map.set_map_type_init(GMapType::G_HYBRID_MAP)
@map.center_zoom_init([22,38],4)
@map.overlay_init(GMarker.new([22,38],:title =&gt; "Title", :info_window =&gt; "This description<br/> can have <b>HTML</b> in it!"))

@map.center_zoom_init([22,38],4) – first parameter is latitude, second is longitude (it usually comes with a decimal point and can be negative, eg. -12.3456), third is the zoom level (0 – world view, 19 – highest possible).

@map.overlay_init is how you set up the markers. You can change a marker icon if you want, you can also put html (including links) in the :info_window. Info window is what you see when you click on the marker.

@map.set_map_type_init(GMapType::G_HYBRID_MAP) By default you can view the map in the NORMAL mode. If you want to run in HYBRID, you need to add this line.

2 – Now you need to modify your layout to load the needed Javascript libraries. The layout is in views/layouts directory. Open the one for your controller and add this line just below your generic javascript loading line:

<%= GMap.header %>

3 – In your action view add the following 2 lines to render the map:

  <%= @map.to_html %>
  <%= @map.div(:width => 600, :height => 400) %>

A note on @map.to_html – some tutorials would suggest you add it to your layout, I think it’s not the correct way, because layout exists for the whole controller and you will usually want to define the @map only in particular actions (like show). So in all other cases you will get a mistake of an undefined variable.

That’s it. If you need additional instruction, you can get a lot from reading the extended tutorial on its Git page.

June 27, 2009 at 10:01 am Leave a comment

Google Maps API in Rails (YM4R-GM) – Part I: Installing the beast

Environment: Rails 2.3.2, Windows Vista, SQLite3 development on a local box

So, you want to be able to use Google maps in your mashup project. In order to do that, there is a nice plug-in YM4R that supports Google Maps and Yahoo APIs and is quite easy to use once you get through the hurdle of installing (if you are on a Windows system). So I split this post into 2 parts – one is the installation, the other – usage of the plugin itself.

Installation

Installation in theory seems to be quite easy, you just need to install a gem and then install a plugin that uses this gem (update: looks like ym4r-gm doesn’t require the gem anymore, so try installing the Git plugin without the gem first – see below).

Here are the instructions:

gem install ym4r
ruby script/plugin install svn://rubyforge.org/var/svn/ym4r/Plugins/GM/trunk/ym4r_gm

SVN

However, if you are one of the unlucky ones with a Windows development environment, most probably you do not have an SVN client installed. A bad thing about this is that the plugin install command above does not show any error messages, so you can run the program with -x switch or just check the vendor/plugins subdirectory of your project – it should have the directory ym4r_gm in it. If it doesn’t, you need to install an SVN client. Installing an SVN client is a minor pain (I chose a command-line version that is 3mb, but you can’t just download, you need to register to get the file), and after installing it actually gave me an error that looked like this: “svn: error resolving case of” and the local path to the plugin. Googling this error leads to a lot of posts from other clueless newbies, and as I really had no experience with SVN, it looked like in order to solve this problem I needed to read a book on SVN first. One option that I used was to download the GUI client TortoiseSVN and copy the repository to a local disk.

Github

Thankfully, there is an easier way. The YM4R-GM is actually copied to Github, which allows you to download the package without the client. And it’s actually a newer version of the plugin. So, here is the Github page for YM4R-GM.

A Windows client for Git can be downloaded here.

After you download a client (I’ve installed this one, but check for the latest version), you can run Git installations, and actually it does so without problems. If you get a path not found problem, you will need to close and reopen your cmd window, because new Windows PATH setting is not visible to an “old” window.

Here is the line:

ruby script/plugin install git://github.com/ewildgoose/ym4r_gm.git

Manual install

Ok, you can stop right here ;). But just in case you will come into any problems or will find a project which is on SVN only, you can download the files manually and put them in vendor/plugins/[name-of-plugin] directory. For most of the plugins that’s enough, but YM4R-GM also installs files into other directories, so you should (1) copy its javascript files into public/javascripts and (2) file in the root of the plugin called gmaps_api_key.yml.sample needs to be copied to config directory with the name gmaps_api_key.yml.

However, you can also just as easily go into the plugin directory and run ruby install.rb

Google MAP API key

Final thing you need to do is to get an API key from Google. Here is the link. You need to get a link for each url that you use. If you only use the development environment now, put the URL of the site as http://127.0.0.1. Copy the API key that you receive and put it in the development section of the gmaps_api_key.yml you created earlier.

Well, that’s it. It took longer than usual, but it was worth it πŸ˜‰

June 27, 2009 at 9:42 am 5 comments

Michael Jackson RIP

Wow, so Michael Jackson died. How did I miss that? Yes, he was a little freaky, but still a pop idol. RIP.

PS – Businessweek is talking about how death of Jackson means good business to Amazon & other retailers. Cruel world, eh.

June 27, 2009 at 12:39 am Leave a comment

Acts_as_versioned delete a specific version

Environment: Rails 2.3.2, Windows Vista, SQLite3 development on a local box

By default acts_as_versioned has a method to delete up to :limit of versions called clear_old_versions. If you need to delete a specific version, the following does not work: @artist.versions.delete(id) because a String is passed instead of a Versioned class.

But you can specify your own method, which is a very easy modification of the clear_old_versions:

def clear_old_version(version)
     self.class.versioned_class.delete_all ["#{self.class.version_column} = ? and #{self.class.versioned_foreign_key} = ?", version, id]
end

And now you can call this method like this: @artist.clear_old_version(params[:version_id])

artist_controller.rb:

def deleteversion
   @artist = Artist.find(params[:artist_id])
   @artist.clear_old_version(params[:version_id])
   redirect_to :action => 'show', :id => @artist
end

June 26, 2009 at 11:56 pm Leave a comment

Post ruby or html, css, sql sourcecode in your wordpress.com blog

To correctly post Ruby (or HTML, CSS, SQL, etc.) source code you should use the following tags, and not the useless <code> tag. This way you don’t need to escape the HTML tags, the code will be highlighted and numbered.

I found out about this just now, so posting it for anyone who might get into the same trouble.

[sourcecode language=’ruby’]
5.times do
something
end
[/sourcecode]

This will show up like this:

5.times do
 something
end

I do not see any way to add a shortcut to this on the “Edit/Create Post”, so it’s not as comfortable as it could be, but still much better than using an external converter.

You can use one of the following params for the language attribute:
bash
cpp
csharp
css
delphi
html
java
jscript
php
python
ruby
shell
sql
vb
xml

More info here

June 26, 2009 at 6:54 pm 5 comments

Acts_as_versioned tutorial

Environment: Rails 2.3.2, Windows Vista, SQLite3 development on a local box

You might want to create a wiki-like functionality on your web site that is able to save all changes to your objects and adds an ability to retrieve them. So, for example you have pages for Artists that anybody can change in wiki-fashion but you also want to save the history of such changes and revert to a specific version as needed.

Good thing is that there is a very neat plugin called “acts_as_versioned” that you can install and gain access to versions of your objects straight away. Bad thing is that most of the tutorials and documentation is outdated (the official RDoc was last updated in 2005).

So, if you are trying to follow some tutorials or recipes you might get an error:

NoMethodError: undefined method `find_version'
or 
NoMethodError: undefined method `find_versions'

So use this tutorial to get through this.

1 – First, download the latest version of the plugin acts_as_versioned from here. Do not use the script/install command, as it downloads the old version that does not work any more with Rails 2.2 or 2.3. You can manually install the plugins by copying the files in the directory to a subdirectory “acts_as_versioned” in the path vendor/plugins. Don’t forget to restart the script/server, otherwise RoR does not see your new plugin.

While there, you can also generate the up to date documentation by running:

rake doc:plugins:acts_as_versioned

This will place the documentation for the plugin in the doc/plugin subdirectory of your project.

2 – In the model for which you want version support add the following line somewhere closer to the top:

acts_as_versioned

If you want to add it for a model “Artists”, then you should edit app/models/artist.rb

3 – Now you need to create a table which will store the older versions of your objects. This is done by running the following command:

Artist.create_versioned_table

You can put it in a db migration task or you can run it in a script/console. The best way is to add it to migrations and you can use the following migration (by running rake db:migrate)

  class AddVersions < ActiveRecord::Migration
    def self.up
      # create_versioned_table takes the same options hash
      # that create_table does
      Post.create_versioned_table
    end

    def self.down
      Post.drop_versioned_table
    end
  end
&#91;/sourcecode&#93;

4 - Now try out how it works - the objects should be saved and shown just as before, but at the same time a copy of your object should be saved into artist_versions table. To check it, you can use sqlite3 console by either running script/dbconsole or if it gives you an error (as it does for me running on vista), then you can run sqlite3 development.sqlite3 in the db subdirectory of your project

In sqlite3 check the following:
&#91;sourcecode language='sql'&#93;
.tables versions
&#91;/sourcecode&#93;
This will show you all the tables with "versions" in the name. There should be your "artist_versions" table. Check that the object is saved correctly there by running:
&#91;sourcecode language='sql'&#93;
select * from artist_versions;
&#91;/sourcecode&#93;

5 - Now add version functionality to your controller / view:

<strong>To show the list of versions:</strong>

In artist_controller.rb show method you can add the following:


@artistversion = @artist.versions.find(:all)

This will populate @artistversion with the array of versions of the current object @artist. And that’s the new syntax that replaces the old find_versions / find_version that might give you trouble.

And in the view you should add something like that:

	<b>Edits history:</b><br/>
	<% @artistversion.reverse.each do |version| %>
  Version <%= version.version %> Updated: <%= version.updated_at %>
  <%= link_to '(restore)', :action => 'restore', 
                   :version_id => version.version, 
                   :artist_id => @artist.id %><br/>
<% end %>

Version variable has access to all the attributes of the object and also to the attribute “version” that you can use. You can just as easily show who was the editor of the version if you store that information by using version.user_id, etc. Also, as artistversion is just an array, it is nice if you reverse the order, so that the latest version is shown first.

Finally, add the method restore to your controller:

def restore
   @artist = Artist.find(params[:artist_id])
   @artist.revert_to! params[:version_id]
   redirect_to :action => 'show', :id => @artist
end  

revert_to! method restores the object to a given version and saves it.

You might need to also update the routes.rb if you are using default RESTful map if you get a “unknown method” error:

Your route might look something like this:

map.resources :artists, :collection => {:restore => :get}

Additional settings

Another cool feature is to trigger the saving of a version only if particular fields are changed. It’s easy to set up:

acts_as_versioned :if_changed => [:name, :description, :user_id]

You can also use if option, that allows you to save a version only if method called returns true. Here is the extract from documentation:

if – symbol of method to check before saving a new version. If this method returns false, a new version is not saved. For finer control, pass either a Proc or modify Model#version_condition_met?

acts_as_versioned :if => Proc.new { |auction| !auction.expired? }

Limitations

So, acts_as_versioned lets you create a history of changes to your model. What it does not do is save any related changes that are not exactly a part of the main class table, for example if you have tags or pictures stored in the separate classes/tables.

Also, if you delete the main object, all the object versions are automatically deleted. This means that you would lose the whole object and all of it’s versions – very open to abuse, etc. In order to circumvent this behavior you can use another plugin – acts_as_paranoid, instructions are provided in this blog.

Finally, if you decide to change the main object (add table columns), the versions table is not updated automatically, you will need to add new columns to it yourself.

June 26, 2009 at 5:55 pm 6 comments

Transactions

Runy on Rails has a cool support for database transactions. Basically, if you need to save 2 objects as a result of a particular action, you need to make sure that the 2nd is saved only if the first is saved successfully:

balance.transaction do
    balance.save!
    account.save!
end

More information here.

June 26, 2009 at 1:12 pm Leave a comment

Older Posts


Starting to learn Rails?

Kindle

Get Kindle - the best e-book reader, that I personally use, and the only one that you can read on the beach - very useful: Kindle Wireless Reading Device (6" Display, Global Wireless, Latest Generation)