Sonntag, 28. April 2013

Lambda is not a Proc

I guess you already know about Procs. The lambda in Ruby is also a closure. Therefore, it encapsulates logic which can be executed at the time it is encountered. It even an be put into a particular context by passing it to a function. So far nothing new.
That's why I start with explaining the lambda and later compare with the Proc.
A simple lambda:
my_lambda = lambda { puts "A lambda" }
my_lambda.call
returns:
A lambda
Sure, you can pass a parameter:
my_lambda = lambda { |param| puts "Parameter: #{param}" }
my_lambda.call(1)
returns:
Parameter: 1
And yeah you can also pass more than one parameter like:
my_lambda = lambda { |p1, p2| puts "Parameters: #{p1}, #{p2}" }
my_lambda.call(1, 2)
returns:
Parameters: 1, 2
You also can pass the lambda to a method for some reasons:
def my_function(block)
  puts "before lambda"
  block.call
  puts "after lambda"
end
my_lambda = lambda { puts "inside lambda" }
my_function my_lambda
returns:
before lambda
inside lambda
after lambda
Though there are not many reasons for passing logic to an object method without using data of that object. You would more often want to "send logic" to an object for dynamically using its data. Then you pass a parameter like:
def my_function(block)
  number = 0
  block.call(number)
end
my_lambda = lambda { |p| puts "inside lambda: #{p += 1}" }
my_function my_lambda
returns:
inside lambda: 1
At this point I note an essential property of closures. They automatically carry with them the bindings from the code location where they were created.
 
word = "Foo"
def redefine_word(block)
  word = "Bar"
  puts word
  block.call
end
redefine_word(lambda { puts word })
You really have to take care of the scope, when you send a block to a function. Consider the output:
Bar
Foo

The difference between lambda and Proc

There is another exciting detail I want to put the finger on. Control keywords like return, raise, break, redo, retry do NOT have any impact on the further execution. And that's an important difference to Procs. A lambda example:
 
def my_method
  puts "before lambda"
  my_lambda = lambda do
    puts "inside lambda"
    return
  end
  my_lambda.call
  puts "after lambda"
end
my_method
returns:
before lambda
inside lambda
after lambda
And now the same snippet with a Proc:
 
def my_method
  puts "before Proc"
  my_proc = Proc.new do
    puts "inside Proc"
    return
  end
  my_proc.call
  puts "after Proc"
end
my_method
returns:
before Proc
inside Proc
Boom! The "return" inside the Proc prevents executing all following logic (line 8 of "my_method"). Good to know, isn't it? Another important difference concerns the parameters of the block. Lambdas are strict:
my_lambda = lambda { |p1, p2| puts "Parameters: #{p1}, #{p2}" }
my_lambda.call("One")
ends up in an exception:
wrong number of arguments (1 for 2) (ArgumentError)
But a Proc is liberal:
my_proc = proc { |p1, p2| puts "Parameters: #{p1} and #{p2}" }
my_proc.call("One")
returns:
Parameters: One and
Keep the differences in mind, when you choose a Proc or a lambda for closuring.

Supported by Ruby 1.9.3

Mittwoch, 20. Februar 2013

The quick Proc

In the previous post Yield your block in Ruby I described how to code a block and its short cut "yield". You may have noticed that another kind of closure, the Proc. The goal behind is the same as the already explained block. But you will get into the situation to save a block for later dynamic use. I used a Proc the first time in my very first Ruby On Rails project.
That's why I also explain the Proc in a Rails example now.
Let's assume a model Machine:
class Machine
  attr_accessor :in_progress
  attr_accessible :name
  validates :name, :presence => true, :unless => Proc.new { |machine| machine.in_progress.blank? } 
end
having the accessor methods generated through "attr_accessor". Furthermore there is the model attribute "name" for the machine name. I want the machine validate its name for presence only in the case of the machine was already started.
That's why there is the third call "validates". And it is only called, when the :unless key contains a false. Since the validation call is dynamic, there is a Proc assigned. It executes its code not before the validation call and can return true or false depending on the value of the instance variable @in_progress.
I agree, the logic of the Proc also could be put into an instance method, say "in_progress?" (as it would be generated by Rails, if it was a model attribute).
But why should I? I only need the logic once and this way it is more readable, because it is located next to the key.
So when do I use a Proc?
I do, when some logic should be called dynamically and not be put into a method for some reasons.

Supported by Ruby 1.9.3, RubyOnRails 3.1

Montag, 11. Februar 2013

Yield your block in Ruby

In Ruby there are some topics which are not often discussed and even some developer not really know about. One of them are closures.
The Ruby closures are called blocks, Procs and lambdas. They enclose logic, which can be invoked outside of its immediate scope.
Every Ruby developer already used a block when running the well known Array#collect! or Hash#select!. An easy to understand (and 100% true) example:
languages = ["Ruby", "Python", "Javascript"]
languages.collect! do |language|
  "#{language} is awesome!"
end
The introduction so far. But how does the Proc behind (e.g. Array#collect!) work, how to do something similar and when to use it?
To illustrate the functionality of such closure I start with the Proc itself:
class Array
  def power!(&block)
    self.each_with_index do |number, index|
      self[index] = number * number
      block.call(self[index])
    end
  end
end
I re-opened the Array class and added the power! method. I sticked to Ruby conventions and put a bang at the end (if you don't know why, read about the bang convention). The method itself expects a block (or rather enclosed logic) to be passed. That is why there is an ampersand before the block parameter. Inside it only iterates over its items, squares each and calls the block on the result. Quick & simple.
The Proc is called:
numbers = [1, 2, 3, 4]
numbers.power! do |number|
  puts number
end
and prints:
1
4
9
16
 => [1, 4, 9, 16]
Well. Simple but pretty static. The call of "puts" is injected into the scope of the method "power!" by putting it into the block. Let's enhance the same example and rename the method:
class Array
  def iterate!(&block)
    self.each_with_index do |number, index|
      self[index] = block.call(number)
    end
  end
end
The method "iterate!" is pretty comparable to the stuff Array#collect! does. It iterates over each item and stores the result of the called block. In a conclusion "iterate!" offers much more dynamics. We also could square:
numbers = [1, 2, 3, 4]
numbers.iterate! do |number|
  number * number
end
There is a keyword known for calling the block. Its name is "yield". Using it you don't pass a "&block" to the method. The Array#iterate! would look like:
class Array
  def iterate!
    self.each_with_index do |number, index|
      self[index] = yield(number)
    end
  end
end
Finally I want to point out that you also can pass as much as parameters as you need to your closure. An example with two parameters would be:
class Array
  def iterate_with_index!(&block)
    self.each_with_index do |number, index|
      self[index] = block.call(number, index)
    end
  end
end
and calling it:
numbers = [1, 2, 3, 4]
numbers.iterate_with_index! do |number, index|
  puts index
end
returns:
0
1
2
3
 => [nil, nil, nil, nil]
I use blocks to keep my code DRY and to achieve more readability. And there will be a point you can't ignore them.

Supported by Ruby 1.9.3

Mittwoch, 23. Januar 2013

Ruby On Rails calling SAP

Some years ago I had to tap several RFC of SAP. Believe me, communicating with SAP is no fun (in fact SAP is the acronym for Shitty Awful Pain or more seriously Slow Account Program), but without the RFC connector of Piers Harding it would have been impossible. Since SAP is a so called monopolist in the ERP layer, you might have to deal with it and know how to do.
First step is to download the current sapnwrfc of Piers:
user$ curl -o sapnwrfc-0.26.tar.gz http://www.piersharding.com/download/ruby/sapnwrfc/sapnwrfc-0.26.tar.gz
untar it:
user$ tar -xzf sapnwrfc-0.26.tar.gz
build a gem:
user$ gem build sapnwrfc.linux.gemspec
and install the generated gem. The name depends on the version and architecture of your machine. For example:
user$ gem install sapnwrfc-0.26-x86_64-darwin-11.gem
Check, if it is working in your irb:
require 'sapnwrfc' 
Preparations finished.
The basic requisite is an existing RFC module you want to interact with and to know the specific connection parameters. Put them into a configuration file (config/sap.yml):
ashost: your.sap_host.com
sysnr: "00"
client: "510"
user: your_user
passwd: your_pass
lang: EN
trace: 1
Furthermore you have to know the SAP RFC you want to call. In my case it is the fictive RFC "zEquipments". I create a model (models/equipment.rb) as the calling Ruby endpoint:
require 'sapnwrfc'
SAPNW::Base.config_location = "#{Rails.root}/config/sap.yml"
SAPNW::Base.load_config

class Equipment
private
  def self.connect(&block)
    rfc_connection = SAPNW::Base.rfc_connect
    discovered_connection = rfc_connection.discover("CRHD")
    rfc = discovered_connection.new_function_call
    block.call rfc
    rfc_connection.close
  end

public
  def self.find_all_by_site site
    equipments = []
    self.connect do |rfc|
      rfc.EQUIPMENT_PARAMS {
        "WERKS" => site.to_s
      }
      rfc.invoke
      rfc.RETURN.each do |equipment|
        equipments << equipment["ARBPL"].strip
      end
    end
    equipments.uniq!
  end

  def self.find_by_objid objid    
    name = nil
    self.connect do |rfc|
      rfc.EQUIPMENT_PARAMS {
        "ARBPL" => objid.to_s
      }
      rfc.invoke
      name = rfc.RETURN.first["ARBPL"].to_s.strip
    end
    name
  end
end
The first line is self-explanatory. The two following lines load the SAP configuration initially. I first coded a separate private class method for connecting to the SAP system, because I use the logic for connecting twice. The first public class finder method "find_all_by_site" expects the name of the site where the equipments are located in. It connects to the RFC and passes the site parameter. The result collects the names of the found equipments and removes all duplicates (you never know with SAP).
Please note the implemented block for connection. I'll cover the use of closures in the post "Yield Your Block in Ruby".
The second public class finder method searches for a certain equipment having a specific OBJID (the unique identifier for every equipment in SAP) and returns its name.
Conclusion: 2 finder methods calling the same SAP RFC with different parameters returning a collection of equipment names or a certain equipment name.

Supported by Ruby 1.9.3, RubyOnRails 3.1 and SapNwRfc 0.26

Freitag, 28. Dezember 2012

Save time per Rails controller query

Ruby On Rails is sooo elaborated. It ships with a lot of optimizations included, like query caching, page caching and so forth. But this is about optimizing a continuous polled controller. Let's assume getting the current state of some machines. Therefore I use a simple cyclic remote link as I described in an earlier post or in CoffeeScript. It queries the controller once per 10 seconds.
The database migrations:
class CreateMachines < ActiveRecord::Migration
  def change
    create_table :machines do |t|
      t.string :name
      t.integer :state_id
      t.timestamps
    end
  end
end
class CreateStates < ActiveRecord::Migration
  def change
    create_table :states do |t|
      t.string :name
    end
  end
end
The models/machine.rb:
class Machine < ActiveRecord::Base
  belongs_to :state
  validates_presence_of :state_id
end
And the models/state.rb:
class State < ActiveRecord::Base
  has_many :machines
end
The controllers/machines_controller.rb:
class MachinesController < ApplicationController
  def index
    respond_to do |format|
      format.html {
        @machines = Machine.includes(:state).order("machines.name ASC")
      }
      format.js {
        @machines = Machine.where("machines.updated_at >= :updated_at",
            { :updated_at => session[:last_status_request] }).includes(:state)
      }
    end
    session[:last_status_request] = Time.now
  end
end
If a simple GET request was received by the MachinesController, it returns all machines including their state and sets the request timestamp in the session initially. They are displayed in the views/machines/index.html.erb:
<ul>
  <% machines.each do |machine| %>
    <li>
      <%= machine.name %>: <span id="<%= dom_id(machine) %>_state"><%= machine.state.name %></span>
    </li>
  <% end %>
</ul>
<%= link_to 'Refresh', machines_path, :remote => true, :class => 'auto_remote' %>
The XMLHTTPRequest triggered by the remote link reaches the format.js part of the MachinesController. Please notice that only those machines are queried, who have been updated since the last status request timestamp. So a lot less machines and their state are queried, instantiated and sent back to the client.
The result is processed in the index.js.erb:
<% @machines.each do |machine| %>
  state = $('#<%= dom_id(machine) %>_state');
  state.text("<%= machine.state.name %>");
<% end %>
This post was more about the conception how to save processing time than an optimized-to-the-bones tutorial. For example you better should render a 304 Not Modified, if no state was updated since the last polling request.
Supported by Ruby on Rails 3.2.8

Dienstag, 25. Dezember 2012

The AOP in Ruby

Needless to say Ruby stands for readable codes, prototyping mixins and other paradigms. In this post I present the paradigma of aspect oriented programming in Ruby (short AOP). What is it good for?
Say you included a cool gem, but it contains one feature, you have to enhance to fulfill your requirement. You have got two options:
  1. copy the code of the feature and overwrite the method with the enriched logic
  2. AOP
The drawback with the first option is the copy & overwrite part. Overwriting means your application will never benefit from bugfixes and enhancements of the original code.
That's why you better go with the aspect oriented paradigma, recycling the original code and injecting new logic.
Fortunately Ruby as a great metaprogramming language offers an easy exposure to AOP. Easy as follows.
module ActsAsExample
  def feature
    @feature ||= "The original"
    @feature + " feature is oh-some."
  end
end
The ActsAsExample module contains the feature method. Including it into the Example class:
class Example
  include ActsAsExample
end
Using the included feature:
Example.new.feature
returns The original feature is oh-some., as expected. Let's add a new aspect to the Example class:
class Example
  include ActsAsExample
  alias_method :original_feature, :feature

  def feature
    @feature = "My new cool fancy"
    original_feature
  end
end
The use of the same feature method:
Example.new.feature
now returns My new cool fancy feature is oh-some.. The feature method behaves different compared to the original code though the original code was used.
A bugfix of the ActsAsExample module to:
module ActsAsExample
  def feature
    @feature ||= "The original"
    " feature is awesome."
  end
end
will break through to the Example class and again calling the feature:
Example.new.feature
returns the bugfixed My new cool fancy feature is awesome. and please note that no change was made in the copy method of the Example class.
Clean!
Maybe my example is not the best, but I hope it illustrates how easy AOP in Ruby is.
Additionally I point to the Ruby Aquarium framework.
Supported by Ruby 1.9.3

Donnerstag, 20. Dezember 2012

VI: best Ruby IDE since 1976

First I have to admit that you caught me in a lie.
The very best editor for developing software is not the VI but its conduction, the great VIM (Vi IMproved). It's not "cool" like TextMate and Apple hipsters might give a sniff at VIM, but it's available on every professional OS (Windows is none!)
From time to time you also have to debug some logic on a remote server, possibly even on a production server. Then your best choice is tunneling via SSH and debugging in your terminal by using VIM.
The mentioned method of operation is not only for Rubyists. It's the way to go for everyone working on remote machines. Even those Java island guys have to turn their back on NetBeans/ IntelliJ/ Eclipse in some situations.
Other good points are VIM's portable configuration, the high level of customizability and extensibility and not to forget its powerful and skilled community.
Well, none says VIM is intuitive. There is a learning curve when you first start using it, and it does require a bit of a commitment. But you will be rewarded for the rest of your coding life time.
If VIM is not already installed on your Debian based system (like Ubuntu), just do:
user$ sudo apt-get install vim vim-common
or in Fedora:
user$ sudo yum install vim-common vim-enhanced vim-minimal
As a next step maybe you will want to edit your vimrc:
user$ vi ~/.vimrc
There you can configure a lot and it will be part of your VIM life style. It could look like this:
set nocompatible " make VIM useable by switching off the compatibility to grandpa VI
 
set diffexpr=MyDiff() " overwrite the default diff function of VIM
function MyDiff()
  let opt = ''
  if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif
  if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif
  silent execute '!C:\Vim\vim61\diff -a ' . opt . v:fname_in . ' ' . v:fname_new . ' > ' . v:fname_out
endfunction
 
set history=500 " keep 500 lines of command line history
set tabstop=4 " set the tab Stops to 4 white spaces
set shiftwidth=4 " set the indention to 4 white spaces. along with tabstop=4 it implies an indention with 1 tab
set noexpandtab " do not replace Tabs with white space while editing
 
set nobackup " do not write Backup Files while saving

set showmatch " jump to the opening bracket briefly, if a closing bracket is typed

set cindent " cindent is a quite intelligent indention

set fo=croq " continues the comments in the next line

set foldmethod=marker " tagged lines with {{{ and }}} can be hidden with zc or opened with zo
set mousehide " hides mouse pointer while typing

set background=dark " set the background dark

syntax on " enable syntax highlightening
filetype on
filetype indent on
filetype plugin on
Of course there are a lot more options. Surf the web for it.
I won't go into details how to use the VIM. It is well documented in VIM. Just type :help. Moreover there are many tutorials out there. I suggest the official VIMdoc and the great screencast at peep code.com. For getting further tips visit the VIM Runpaint