Thursday, July 28, 2011

#change

Do you now about change?

In Rails 3.1 ActiveRecord::Migration we can define only one method

change

It`s 'reversible' migrations. You just implement 'up' version and Migration system generate for you methods to create revers migration.

For example:

class CreateWagons < ActiveRecord::Migration
  def change
    create_table :wagons do |t|
      t.integer :number
      t.integer :mileage
      t.datetime :build_date
    end
  end
end

When you run migration 'up' it create a new table, if 'down' - drop dable. But you must be careful using this magick, because some methods can`t be resolved and you get ActiveRecord::IrreversibleMigration

Rails known how to revert this commands:

add_column
add_index
add_timestamp
create_table
remove_timestamps
rename_column
rename_index
rename_table

There for you can create 'change' migration. Try to run it 'up' and 'down', and if you migration raised, you just implement 'down' version.

I think it`s one more beautiful issues that presents to us Rails platform.

Friday, April 29, 2011

sticker

This sticker i must put on my display :) command to create TAGS file

$ cd rails_root_path
$ ctags -e -a --Ruby-kinds=-f -o TAGS -R .

Friday, April 22, 2011

Inside rails.

You must be very careful when create "before_*" callbacks in Rails.

I found one interesting feature (of course it is not bug :D ) ActiveRecord raise with error RecordNotSaved if you have "before_*" callback that return "false". For example:

class User < ActiveRecord::Base
  before_save :set_short_link

  private
  def set_short_link
    short_link = name.to_url if name.changed?
  end
end

You can`t save instance of this class if you don`t change "name" because method "set_short_link" return false (see /activerecord/lib/active_record/base.rb, line 2568)

Right version will be:

class User < ActiveRecord::Base
  before_save :set_short_link

  private
  def set_short_link
    short_link = name.to_url if name.changed?
    true
  end
end

Friday, November 19, 2010

All about ~/.emacs

As most of the time I work with Ruby and Ruby on Rails and Emacs is my favorite text editor I would like to devote my next post to the Emacs configuration.

Last week I have been customizing Emacs in order to simplify my work. Therefore, i would like to share my work with you.

Theme

I started with Emacs theme customization and used color-theme plugin, which can be found on Emacs color-theme plugin homepage or can be taken from Debian repository in emacs-goodies-el package. After the installation you have three options:

  1. Use one of the build-in themes (M-x color-theme-select);
  2. Create your own theme;
  3. Use mine :) (color theme)

For the options 2 and 3 you have to save the theme file into Emacs path directory and add the following line into your ~/.emacs file:

;; Theme
(load-file "~/.emacs.d/color-theme-butcher.el")
(color-theme-butcher)

(set-frame-font "-misc-fixed-medium-r-normal--15-*-75-75-c-90-koi8-r")
(tool-bar-mode)
(menu-bar-mode)
(scroll-bar-mode)

Also, as you have noticed, I set the custom font using set-frame-font (the font was chosen in xfontsel), disabled: toolbar, menubar and scrollbar.

Rinari

Afterwards, I chose Rinari from a large list of Emacs Rails plugins. Rinari homepage.

Rinari installation:

$ git clone git://github.com/eschulte/rinari.git
$ cd rinari
$ git submodule init
$ git submodule update

The base Rinari directory is placed into Emacs path directory and the following code is added to ~/.emacs

;; Rinari
(add-to-list 'load-path "~/.emacs.d/rinari/")
(require 'rinari)
(add-hook 'ruby-mode-hook
          (lambda ()
            (defadvice ruby-mode-set-encoding
              (around ruby-mode-set-encoding-disable activate) nil)))

The last hook for ruby-mode deactivates Emacs coding tags, automatically created by Emacs coding-system (that can be very uncomfortable while working with files that have Cyrillic symbols).

Ruby Electric

Unfortunately, Rinari does not include ruby-electric (helper for automatic brackets closure or any other language construction). To add ruby-electric copy ruby-electric.el to Emacs path directory and configure it into ~/.emacs

;; Ruby-electric
(require 'ruby-electric)
(add-hook 'ruby-mode-hook 'ruby-electric-mode)

MultiMajorModes

Generally, Emacs uses only one major editing mode, for example, ruby-mode in *.rb files. However, if we want to edit files that contain ruby and HTML we will have to either switch the modes every time or we can install MuMaMo (MultiMajorModes). MuMaMo automatically highlights the code and switches the major modes. Most often MuMaMo is used in *.html.erb files to edit ruby and HTML. MuMaMo is based on nXhtml. You can download the latest version of nXhtml (MuMaMo included) here.

Unzip the archive and copy it into Emacs path directory. Add to ~/.emacs the following:

;; MuMaMo-Mode for rhtml files
(add-to-list 'load-path "~/.emacs.d/nxhtml/util/")
(require 'mumamo-fun)
(setq mumamo-chunk-coloring 5)
(add-to-list 'auto-mode-alist '("\\.rhtml\\'" . eruby-html-mumamo))
(add-to-list 'auto-mode-alist '("\\.html\\.erb\\'" . eruby-html-mumamo))

As I don`t like colored hunks, I set the variable MuMaMo-chunk-coloring being equal 5. This means that the coloring will turn on only for the fifth level, however, usually we see only three levels maximum.

Interactively Do Things

To speed up file management in you working directory you can use IDO helper (Interactively Do Things), which is a part of Rinari package. If you dislike it you can disable it any time.

;; Interactively Do Things
(require 'ido)
(ido-mode t)

Git in Emacs

As I use git a lot I included git-emacs (link) in Emacs as well:

;; git-emacs
(add-to-list 'load-path "~/.emacs.d/git-emacs/")
(require 'git-emacs)
(require 'git-status)
(setq git-state-modeline-decoration 'git-state-decoration-large-dot)
(global-set-key (kbd "C-x M-g") 'git-status)

In the last line I bound git-status function to C-x M-g combination.

Autocompletion.

Autocomplete plugin can be downloaded here. Unpack the plugin, copy to Emacs path and configure it:

;; Autocomplete
(add-to-list 'load-path "~/.emacs.d/")
(require 'auto-complete-config)
(add-to-list 'ac-dictionary-directories "/home/butcher/.emacs.d//ac-dict")
(ac-config-default)

Rsense

As autocomplete has a short completion list. I used Rsense to extend autocomplete functionality. Further on I will tell how to install and configure Rsense in Debian (more detailed information for other OS you can find in Rsense installation guide).

So, having downloaded and unpacked the archive copy it into /opt directory and add local variable RSENSE_HOME that will keep the path to Rsense root directory. Afterwards, check whether bin/rsense can be executed and then create config file from Rsense configuration script.

$ wget http://cx4a.org/pub/rsense/rsense-0.3.zip
$ unzip rsence-0.3
$ cp -av rsense-0.3 /opt

What comes to the local variable RSENSE_HOME, add to ~/.bashrc the following line using your favorite editor:

export RSENSE_HOME=/opt/rsense-0.3/

Save the file, close the editor and open new console tab to re-read the configuration file.

$ echo $RSENSE_HOME
/opt/rsense-0.3/
$ cd $RSENSE_HOME
$ chmod +x bin/rsense
$ bin/rsense version
RSense 0.3
$ ruby etc/config.rb > ~/.rsense
$ cat ~/.rsense
home = /opt/rsense-0.3
load-path = /usr/local/lib/site_ruby/1.8:/usr/local/lib/site_ruby/1.8/i486-linux:/usr/local/lib/site_ruby/1.8/i386-linux:/usr/local/lib/site_ruby:/usr/lib/ruby/vendor_ruby/1.8:/usr/lib/ruby/vendor_ruby/1.8/i486-linux:/usr/lib/ruby/vendor_ruby:/usr/lib/ruby/1.8:/usr/lib/ruby/1.8/i486-linux:/usr/lib/ruby/1.8/i386-linux:.
gem-path = /home/butcher/.gem/ruby/1.8:/var/lib/gems/1.8

That is all about Rsense installation.

Autocomplete with Rsense

To configure Emacs for Rsense and automplete + Rsense work:

;; Rsense
(setq rsense-home "/opt/rsense-0.3")
(add-to-list 'load-path (concat rsense-home "/etc"))
(require 'rsense)

;; Rsense + Autocomplete
(add-hook 'ruby-mode-hook
          (lambda ()
            (add-to-list 'ac-sources 'ac-source-rsense-method)
            (add-to-list 'ac-sources 'ac-source-rsense-constant)))

That`s all folks! :) You can borrow my final version of ~/.emacs file here

Have a nice coding on Ruby on Rails with Emacs!

Thursday, October 28, 2010

Ruby Deal-breaker

Recently I have come across a very interesting thing while working with Ruby arrays. My goal was to convert the array into a SQL query. For example, converting the array [[1,2,3],[4,5,6,],[7,8,9,]] into the string "(1,2,3),(4,5,6),(7,8,9)". If one has any basic knowledge about iterators, it won’t be a difficulty at all.

Example below:
irb(main):001:0> array = [[1,2,3], [4,5,6], [7,8,9]]
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
irb(main):002:0> sql_values = array.map{|a| "(" + a.join(", ") + ")" }.join(", ")
=> "(1, 2, 3), (4, 5, 6), (7, 8, 9)"

`map` returns new array which we join using "," string.
Also, you can put the data into SQL query manually. For example, adding any random integer values to our data:

irb(main):003:0> sql_values = array.map{|a| "(" + (a << rand(100)).join(", ") + ")" }.join(", ")
=> "(1, 2, 3, 98), (4, 5, 6, 24), (7, 8, 9, 77)"

However, pay attention! Of course, `map` does return the new array, but you, probably, think that the `a << rand (100)` adds the new value to the output array only. You are wrong! The thing is that when you work with `a` inside the `map` iterator, you work with the basic array, as by default, the variables are passed by link in Ruby. Therefore, when the new data is added in the existing array, you will get the following:

irb(main):004:0> array
=> [[1, 2, 3, 98], [4, 5, 6, 24], [7, 8, 9, 77]]

To create a new instance you must use the operation like ‘+’

irb(main):005:0> sql_values = array.map{|a| "(" + (a + [rand(100)]).join(", ") + ")" }.join(", ")
=> "(1, 2, 3, 98, 93), (4, 5, 6, 24, 92), (7, 8, 9, 77, 10)"
irb(main):006:0> array
=> [[1, 2, 3, 98], [4, 5, 6, 24], [7, 8, 9, 77]]

Thus, don’t forget that variables in ruby are passed by link and when you work with ruby iterators you work with the basic data.