Showing posts with label ruby. Show all posts
Showing posts with label ruby. Show all posts
Friday, December 27, 2019
Troubleshooting Ruby 2.7 compiler errors
So Ruby 2.7 was released at Xmas'19 and I got some errors when compiling it in Linux Mint 19.1. Some libraries were not configured. The errors ocurred at the linking phase of make. Five libraries got errors, and I'll walk across their solutions:
- openssl:
sudo apt install libssl-dev - gdbm:
sudo apt install libgdbm-dev - dbm:
sudo apt install libqdbm-dev - readline:
sudo apt install libedit-dev - zlib:
sudo apt install libz-dev
cd /lib/x86_64-linux-gnu/
sudo ln -s libz.so.1 liblibz.so
Enjoy!
Monday, May 13, 2019
Detecting key press in Ruby
To check whether a key is pressed in linux (non-blocking, non-waiting).
def keypressed
system('stty raw -echo') # => Raw mode, no echo
char = (STDIN.read_nonblock(1).chr rescue nil)
system('stty -raw echo') # => Reset terminal mode
char
end
Inspired on https://stackoverflow.com/a/22659929.
Saturday, October 27, 2018
Net::HTTP error sending GET request with parameters
If you're getting trouble with Net::HTTP#send_request when sending a GET request with parameters, one possible cause is that parameters must be part of path as a query string, and not as data (3rd parameter of #send_request).
For example (assuming that parameters is not empty), instead of
http = Net::HTTP.new('server.com')
http.send_request('GET', path, parameters, headers)
try:
http = Net::HTTP.new('server.com')
http.send_request('GET', path + '?' + parameters, '', headers)
For example (assuming that parameters is not empty), instead of
http = Net::HTTP.new('server.com')
http.send_request('GET', path, parameters, headers)
try:
http = Net::HTTP.new('server.com')
http.send_request('GET', path + '?' + parameters, '', headers)
Net::HTTP error 400 (bad request) with HTTPS
Hello, friends!
Yesterday I got stuck when trying to connect to an HTTPS site using Net::HTTP:
http = Net::HTTP.new('server.com', 443)
response = http.send_request('GET', path, parameters, headers)
I was getting error 400 in response.code.
What is not well documented is that when accessing a server via HTTPS protocol it's not enough to set port to 443. You must also set use_ssl to true:
Yesterday I got stuck when trying to connect to an HTTPS site using Net::HTTP:
http = Net::HTTP.new('server.com', 443)
response = http.send_request('GET', path, parameters, headers)
I was getting error 400 in response.code.
What is not well documented is that when accessing a server via HTTPS protocol it's not enough to set port to 443. You must also set use_ssl to true:
http = Net::HTTP.new('server.com', 443)
http.use_ssl = true
response = http.send_request('GET', path, parameters, headers)
I found that by seeing code at http://www.rubyinside.com/nethttp-cheat-sheet-2940.html.
http.use_ssl = true
response = http.send_request('GET', path, parameters, headers)
I found that by seeing code at http://www.rubyinside.com/nethttp-cheat-sheet-2940.html.
Wednesday, August 31, 2016
How to install mysql2 gem on Ubuntu
If you are having trouble to install the mysql2 gem, try the following:
# apt-get install build-essential ruby-dev libmysqlclient-dev
Sunday, July 24, 2016
Slides: Introduction to Ruby
I'm here today to share a presentation that I've made to a group of Software Development students.
Click here to see the presentation.
I'm sorry for a piece of code that was not translated (variable names in portuguese), but I think that you can get the idea (comparing how PHP is spelling and how Ruby is expressive).
Click here to see the presentation.
I'm sorry for a piece of code that was not translated (variable names in portuguese), but I think that you can get the idea (comparing how PHP is spelling and how Ruby is expressive).
Monday, April 21, 2014
Installing Ruby 2.1.1 in Ubuntu 14.04
The apt-get way don't install the latest stable Ruby (2.1.1), even on Ubuntu 14.04. Instead, I got 1.9.3 that way. RVM can be easy, but to work with Apache I'd need a system-wide installation independent of the RVM environment. So I've decided to install Ruby from source. I had problems around readline, but after seeing this hint, the solution that worked for me is:
./configure --with-readline-dir=/usr/lib/x86_64-linux-gnu/libreadline.so
make
make install
on the directory of the unpacked source of Ruby 2.1.1, as root. I suspect there is a more elegant solution out there, but this is enough for me at this time.
./configure --with-readline-dir=/usr/lib/x86_64-linux-gnu/libreadline.so
make
make install
on the directory of the unpacked source of Ruby 2.1.1, as root. I suspect there is a more elegant solution out there, but this is enough for me at this time.
Friday, January 18, 2013
Some undocumented differences between 1.8 and 1.9
Here I bring some differences among Ruby versions 1.8.7, 1.9.1 and 1.9.2 which I didn't found in other sites, maybe because they represent very rare use cases (or maybe because I didn't search enough). For these cases, version 1.9.3 behaves as 1.9.2. I was faced with them when trying to make Namebox compatible with Ruby 1.8.7 and 1.9.1, but after weeks of work I concluded that it doesn't worth.
The method names for instance_methods will be String in 1.8.7 and Symbol since 1.9.1.
Since instance_method(method_name)don't care whether method_name is Symbol or String, this seems to be a innocuous difference, but if you code has something like Klass.instance_methods.include?("f") it will break when changing versions. This is also valid for methods and singleton_methods.
The superclass of the singleton class (also known as eigenclass) of a class X is the singleton class of the superclass of X. This follows the natural way of class methods lookup (not counting the extended modules). However, this works only since 1.9.1. In Ruby 1.8.7, the superclass of the singleton class of any class is the singleton class of the class Class:
For instance methods, you can bind an unbound method to an object since that object is an instance of the method's class or subclass. For class methods, you can bind an unbound method to a subclass of the method's class (or to the class itself). This works since 1.9.2. Earlier versions raises TypeError if you try to bind a class method to a subclass:
In Ruby 1.8.7, if you bind an instance method of a module to an object (of a class which includes that module), and if that method has super, it will raise NoMethodError instead of looking for the super method. It will flow normally if that method is invoked without bind.
Methods names' type
The method names for instance_methods will be String in 1.8.7 and Symbol since 1.9.1.
Since instance_method(method_name)don't care whether method_name is Symbol or String, this seems to be a innocuous difference, but if you code has something like Klass.instance_methods.include?("f") it will break when changing versions. This is also valid for methods and singleton_methods.
class A; def f; end; end
p A.instance_method(:f) #=> #<Method:A#f>
p A.instance_method('f') #=> #<Method:A#f>
p A.instance_methods(false)
#=> Ruby 1.8.7: ["f"]
#=> Ruby 1.9.1: [:f]
The superclass of the singleton class of a class
The superclass of the singleton class (also known as eigenclass) of a class X is the singleton class of the superclass of X. This follows the natural way of class methods lookup (not counting the extended modules). However, this works only since 1.9.1. In Ruby 1.8.7, the superclass of the singleton class of any class is the singleton class of the class Class:
class A; end class B < A; end # singleton class of B SB = class << B; self; end p SB #=> #<Class:B> p SB.superclass #=> Ruby 1.8.7: #<Class:Class> #=> Ruby 1.9.1: #<Class:A>
Binding class methods to a subclass
For instance methods, you can bind an unbound method to an object since that object is an instance of the method's class or subclass. For class methods, you can bind an unbound method to a subclass of the method's class (or to the class itself). This works since 1.9.2. Earlier versions raises TypeError if you try to bind a class method to a subclass:
class A
def self.f
"self is #{self}"
end
end
class B < A; end
p A.method(:f).unbind.bind(B).call
#=> Ruby until 1.9.1: TypeError
#=> Ruby since 1.9.2: "self is B"
super from a module method after binding
In Ruby 1.8.7, if you bind an instance method of a module to an object (of a class which includes that module), and if that method has super, it will raise NoMethodError instead of looking for the super method. It will flow normally if that method is invoked without bind.
class A def f "Hello" end end module M def f super + " world!" end end class B < A include M end b = B.new p b.f #=> "Hello world!" p M.instance_method(:f).bind(b).call #=> Ruby 1.8.7: NoMethodError #=> Ruby 1.9.1: "Hello world!"
Labels:
binding,
classes,
metaprogramming,
method lookup,
methods,
ruby,
singleton classes,
versions
Thursday, December 13, 2012
Refinements in Ruby: an ingenuous implementation
UPDATE: I've worked on Namebox, an improved way to protect methods from changes, inspired on this implementation of Refinements.
I'm back to programming after some months of pause. The last thing I've heard about Ruby before pausing was Refinements. And I fell in love with it.
I found that idea so smart that I couldn't continue programming without it. I couldn't wait for Ruby 2.0. I had to implement it on my own.
Ruby 1.8.7 give us enough tools for designing a lexically scoped activation of refinements. I could use using with set_trace_func to detect the end of blocks (scopes), but I preferred to use enable and disable, because:
My solution is so simple that I called it "an ingenuous implementation". It has many differences from the original proposal, as I will discuss later, but it brings which I consider the most important feature to me: the refinements are limited to physical ranges within the text file. There's no outside consequences. Anyone can use my refined libraries with no (unpleasant) surprises. And the unrefined methods are not affected (if you're thinking about performance impact).
Here there are some examples:
Differences from the original proposal:
I think this solution is good enough for me, and I guess it won't have the evil side of refinements which was very well discussed in this post (and I agree).
I'm open to discuss about errors, consequences and improvements to my code; feel free. ;-)
I'm back to programming after some months of pause. The last thing I've heard about Ruby before pausing was Refinements. And I fell in love with it.
I found that idea so smart that I couldn't continue programming without it. I couldn't wait for Ruby 2.0. I had to implement it on my own.
Ruby 1.8.7 give us enough tools for designing a lexically scoped activation of refinements. I could use using with set_trace_func to detect the end of blocks (scopes), but I preferred to use enable and disable, because:
- it's simpler to implement;
- it's explicit and easy to read;
- the programmer has the freedom to enable and disable the refinements whenever he/she considers it necessary.
My solution is so simple that I called it "an ingenuous implementation". It has many differences from the original proposal, as I will discuss later, but it brings which I consider the most important feature to me: the refinements are limited to physical ranges within the text file. There's no outside consequences. Anyone can use my refined libraries with no (unpleasant) surprises. And the unrefined methods are not affected (if you're thinking about performance impact).
# Refinements for Ruby: an ingenuous implementation # # (c) 2012 Sony Fermino dos Santos # http://rubychallenger.blogspot.com/2012/12/refinements-in-ruby-ingenuous.html # # License: Public Domain # This software is released "AS IS", without any warranty. # The author is not responsible for the consequences of use of this software.
#
# This code is not intended to look professional,
# provided that it does what it is supposed to do.
#
# This software was little tested on Ruby 1.8.7 and 1.9.3, with success.
# However, no heavy tests were made, e.g. threads, continuation, benchmarks, etc.
#
# The intended use is in the straightforward flux of execution.
#
# Instead of using +using+ as in the original proposal, here we use
# Module#enable and Module#disable. They're lexically scoped by the
# file:line of where they're called from.
#
# E.g.: Let StrUtils be a module which refine the String class.
# module StrUtils
# refine String do
# def foo
# #...
# end
# end
# end
#
# Using it in the code snippets:
#
# StrUtils.enable
# "abc".foo #=> works (foo is "visible")
# def bar; puts "abc".foo; end #=> bar is defined where foo is "visible"
# StrUtils.disable
# "abc".foo #=> doesn't work (foo is "invisible")
# bar #=> works, as bar was defined where foo is "visible"
# def baz; puts "abc".foo; end
# baz #=> doesn't work.
#
# You can enable and disable a module at any time, since you:
# * enable and disable in this order, in the file AND in the execution flow;
# * disable all modules that you enabled in the same file;
# * don't reenable (or redisable) an already enabled (or disabled) module.
#
# See refine_test.rb for more examples.
# Refinements is to avoid monkey patches, but
# we need some minimal patching to implement it.
class Module
# Opens an enabled range for this module's refinements
def enable
info = ranges_info
# there should be no open range
raise "Module #{self} was already enabled in #{info[:file]}:#{info[:last]}" if info[:open]
# range in progress
info[:ranges] << info[:line]
end
# Close a previously opened enabled range
def disable
info = ranges_info
# there must be an open range in progress
raise "Module #{self} was not enabled in #{info[:file]} before line #{info[:line]}" unless info[:open]
# beginning of range must be before end
r_beg = info[:last]
r_end = info[:line]
raise "#{self}.disable in #{info[:file]}:#{r_end} must be after #{self}.enable (line #{r_beg})" unless r_end >= r_beg
r = Range.new(r_beg, r_end)
# replace the single initial line with the range, making sure it's unique
info[:ranges].pop
info[:ranges] << r unless info[:ranges].include? r
end
# Check whether a refined method is called from an enabled range
def enabled?
info = ranges_info
info[:ranges].each do |r|
case r
when Range
return true if r.include?(info[:line])
when Integer
return true if info[:line] >= r
end
end
false
end
private
# Stores enabled line ranges of caller files for this module
def enabled_ranges
@enabled_ranges ||= {}
end
# Get the caller info in a structured way (hash)
def caller_info
# ignore internal calls (using skip would differ from 1.8.7 to 1.9.3)
c = caller.find { |s| !s.start_with?(__FILE__, '(eval)') } and
m = c.match(/^([^:]+):(\d+)(:in `(.*)')?$/) and
{:file => m[1], :line => m[2].to_i, :method => m[4]} or {}
end
# Get line ranges info for the caller file
def ranges_info
ci = caller_info
ranges = enabled_ranges[ci[:file]] ||= []
ci[:ranges] = ranges
# check whether there is an opened range in progress for the caller file
last = ranges[-1]
if last.is_a? Integer
ci[:last] = last
ci[:open] = true
end
ci
end
# Here the original methods will be replaced with one which checks
# whether the method is called from an enabled or disabled region,
# and then decide which method to call.
def refine klass, &blk
modname = to_s
mdl = Module.new &blk
klass.class_eval do
# Rename the klass's original (affected) methods
mdl.instance_methods.each do |m|
if method_defined? m
alias_method "_#{m}_changed_by_#{modname}", m
remove_method m
end
end
# Include the refined methods
include mdl
end
# Rename the refined methods and replace them with
# a method which will check what method to call.
mdl.instance_methods.each do |m|
klass.class_eval <<-STR
alias_method :_#{modname}_#{m}, :#{m}
def #{m}(*args, &b)
if #{modname}.enabled?
_#{modname}_#{m}(*args, &b)
else
begin
_#{m}_changed_by_#{modname}(*args, &b)
rescue NoMethodError
raise NoMethodError.new("Undefined method `#{m}' for #{klass}")
end
end
end
STR
end
end
end
Here there are some examples:
#!/usr/bin/ruby require "./refine" class A def a 'a' end def b a + 'b' end end module A2 refine A do def a a + '2' # A#a, since here A2 is disabled end A2.enable # You must make A2 explicit here def d a + 'd' # A2#a, since here A2 is enabled end A2.disable end refine String do def length length + 1 # Original String#length, since A2 is disabled here end end end a = A.new str = 'abc' puts a.a # a puts a.b # ab puts str.length # 3 A2.enable class A def c a + 'c' # a2c, as A2 is enabled end end puts '' puts a.a # a2 puts a.b # ab (b was not refined nor defined where A2 is enabled) puts a.c # a2c puts a.d # a2d puts str.length A2.disable puts '' puts a.a # a puts a.b # ab puts a.c # a2c (it was defined where A2 is enabled) # puts a.d # NoMethodError, since A2 is disabled puts str.length # In-method enabling test def x(y) A2.enable puts y.a # a2 A2.disable end x(a) # a2 x(a) # enabling multiple times at same line with no error # Lazy enabling test def e A2.enable end def z(y) puts y.a # defined between enable and disable, but affected only after running e() and d() end def d A2.disable end z(a) # a e # now, activating the range for refinements d z(a) # a2 def e2 A2.enable end e2 # running before d(), but... d # error, as you are enabing *after* the disable (physically in the text file)
Differences from the original proposal:
- enable and disable instead of using;
- calls to refined methods only works if it's within the enabled range in the file; so subclasses won't be affected unless their code is in an enabled range;
- super doesn't work for calling the original methods, but you can call it by its name from an un-enabled range; or by calling the renamed methods (see the code for refine).
I think this solution is good enough for me, and I guess it won't have the evil side of refinements which was very well discussed in this post (and I agree).
I'm open to discuss about errors, consequences and improvements to my code; feel free. ;-)
Labels:
metaprogramming,
refinements,
ruby,
scope
Saturday, July 14, 2012
RVM + Apache + CGI Scripts
Hello!
I've configured a new server on Ubuntu 12.04 and I started to use RVM, an excellent version manager which permits to have multiple versions of Ruby installed on a single server (and many versions of the gems - see gemsets), and it makes easy to switch among them.
I've installed RVM under my user (as myself, not as root with sudo) by following the Ryan Bigg's guide, with no previous system-wide installed Ruby. So, I didn't have any Ruby under /usr/bin. My first task then was to replace the shebang line of all my CGI scripts, from
to
(The second line is needed to define the encoding of the string literals in my code, for Ruby 1.9.)
However my scripts didn't run under Apache. In the terminal I could run them (by typing ./index.cgi, for example), but not over a browser. A relevant note: in both the user is the same, i.e., the Apache user is the same as the one logged on terminal. Through php tests, I've checked the RVM enviroment was not loaded under Apache. (If anyone can solve that, please let me know.)
I saw this tip for running CGI scripts with RVM, which suggests to put the complete path of specific version of Ruby in the shebang line. That can be useful if you have scripts which run on different versions of Ruby. But that solution doesn't work for me, because my scripts must run on different machines, with different users, different ruby versions and different paths.
The solution which works for me is to put a symlink of the desired Ruby version under /usr/bin:
(Notes: sony is my username and I chose 1.8.7 because by now my scripts aren't 1.9-compliant yet.)
Therefore I didn't need to have changed the shebang lines. :) But I guess that will be useful in the future.
I've configured a new server on Ubuntu 12.04 and I started to use RVM, an excellent version manager which permits to have multiple versions of Ruby installed on a single server (and many versions of the gems - see gemsets), and it makes easy to switch among them.
I've installed RVM under my user (as myself, not as root with sudo) by following the Ryan Bigg's guide, with no previous system-wide installed Ruby. So, I didn't have any Ruby under /usr/bin. My first task then was to replace the shebang line of all my CGI scripts, from
!#/usr/bin/ruby
to
!#/usr/bin/env ruby # encoding: utf-8
(The second line is needed to define the encoding of the string literals in my code, for Ruby 1.9.)
However my scripts didn't run under Apache. In the terminal I could run them (by typing ./index.cgi, for example), but not over a browser. A relevant note: in both the user is the same, i.e., the Apache user is the same as the one logged on terminal. Through php tests, I've checked the RVM enviroment was not loaded under Apache. (If anyone can solve that, please let me know.)
I saw this tip for running CGI scripts with RVM, which suggests to put the complete path of specific version of Ruby in the shebang line. That can be useful if you have scripts which run on different versions of Ruby. But that solution doesn't work for me, because my scripts must run on different machines, with different users, different ruby versions and different paths.
The solution which works for me is to put a symlink of the desired Ruby version under /usr/bin:
sudo ln -s /home/sony/.rvm/rubies/ruby-1.8.7-p370/bin/ruby /usr/bin/ruby
(Notes: sony is my username and I chose 1.8.7 because by now my scripts aren't 1.9-compliant yet.)
Therefore I didn't need to have changed the shebang lines. :) But I guess that will be useful in the future.
Tuesday, March 13, 2012
Capitalized methods names
You can define methods with capitalized names:
At call time, to avoid Ruby to interpret them as constants, you must make clear that you are using them as functions, by using parenthesis or parameters:
Sequel uses this feature to define methods named String, Integer, etc. for creating/altering tables.
#!/usr/bin/ruby def Foo puts 'foo' end def Bar x puts x end
At call time, to avoid Ruby to interpret them as constants, you must make clear that you are using them as functions, by using parenthesis or parameters:
Foo() #=> 'foo' Bar 3 #=> 3 Foo #=> Error: not initialized constant
Sequel uses this feature to define methods named String, Integer, etc. for creating/altering tables.
Tuesday, March 6, 2012
How to install sqlite3-ruby gem on linux
If you are having trouble to install the sqlite3-ruby gem, try the following:
In systems with apt-get:
In systems with yum:
In systems with apt-get:
# apt-get install libsqlite3-devIn systems with yum:
# yum install sqlite-devel
How to install bson_ext gem on linux
MongoDB requires the bson_ext gem to increase performance. However, it's common to be not ready to install it.
In ubuntu (10.04 32bit) I had to run:
In systems with yum I had to run:
Finally in both systems I could run, with no errors:
In ubuntu (10.04 32bit) I had to run:
# apt-get install ruby1.8-devIn systems with yum I had to run:
# yum install gcc
# yum install make
# yum install ruby-devel
Finally in both systems I could run, with no errors:
# gem install bson_ext
A little bit on require behavior
require filename will:- return true when it finds filename;
- return false when it already loaded filename;
- raise LoadError when it doesn't find filename.
Monday, February 27, 2012
Changing aliased method does not alter the original one
Changing aliased method does not alter the original one, and vice-versa.
So, if you need to alter some method that you know it's aliased, you may stay unworried: you won't affect the other aliased methods, and you can use them if you need the original behavior.
See my tests and the results below.
So, if you need to alter some method that you know it's aliased, you may stay unworried: you won't affect the other aliased methods, and you can use them if you need the original behavior.
See my tests and the results below.
#!/usr/bin/ruby
class A
def original_method
puts "original content"
end
alias aliased_method original_method
alias_method :alias_methoded_method, :original_method
end
class B < A
def original_method
puts "modified content"
end
end
class C < A
def aliased_method
puts "modified content"
end
end
class D < A
def alias_methoded_method
puts "modified content"
end
end
[A, B, C, D].each do |klass|
puts "#{klass}:"
obj = klass.new
[:original_method, :aliased_method, :alias_methoded_method].each do |meth|
print "#{meth}: "
obj.send meth
end
puts
end
The results:
A: original_method: original content aliased_method: original content alias_methoded_method: original content B: original_method: modified content aliased_method: original content alias_methoded_method: original content C: original_method: original content aliased_method: modified content alias_methoded_method: original content D: original_method: original content aliased_method: original content alias_methoded_method: modified content
Saturday, July 30, 2011
Caller binding
One of most useful feature not present in Ruby is to get the binding of the caller of current method, to do something with its local variables.
There is an implementation in the Extensions gem, but it must be the last method call in the method, and we must use the binding within a block.
There is another implementation here, but it depends on tracing along all the code execution, compromising the performance.
However, in this answer in StackOverflow, Taisuke Yamada implemented an version of
There is an implementation in the Extensions gem, but it must be the last method call in the method, and we must use the binding within a block.
There is another implementation here, but it depends on tracing along all the code execution, compromising the performance.
However, in this answer in StackOverflow, Taisuke Yamada implemented an version of
ppp.rb (what is it?) which inspired me to implement my own version of a caller_binding method. Enjoy!#!/usr/bin/ruby
#
# (c) Sony Fermino dos Santos, 2011
# License: Public domain
# Implementation: 2011-07-30
#
# Published at:
# http://rubychallenger.blogspot.com/2011/07/caller-binding.html
#
# Inspired on:
# http://stackoverflow.com/questions/1356749/can-you-eval-code-in-the-context-of-a-caller-in-ruby/6109886#6109886
#
# How to use:
# return unless bnd = caller_binding
# After that line, bnd will contain the binding of caller
require 'continuation' if RUBY_VERSION >= '1.9.0'
def caller_binding
cc = nil # must be present to work within lambda
count = 0 # counter of returns
set_trace_func lambda { |event, file, lineno, id, binding, klass|
# First return gets to the caller of this method
# (which already know its own binding).
# Second return gets to the caller of the caller.
# That's we want!
if count == 2
set_trace_func nil
# Will return the binding to the callcc below.
cc.call binding
elsif event == "return"
count += 1
end
}
# First time it'll set the cc and return nil to the caller.
# So it's important to the caller to return again
# if it gets nil, then we get the second return.
# Second time it'll return the binding.
return callcc { |cont| cc = cont }
end
# Example of use:
def var_dump *vars
return unless bnd = caller_binding
vars.each do |s|
value = eval s.to_s, bnd
puts "#{s} = #{value.inspect}"
end
end
def test
a = 1
s = "hello"
var_dump :s, :a
end
test
Friday, July 29, 2011
How to return from inside eval
I have a code which I need to use within eval. Sometimes I need to get out from the middle of eval code, but how?
In PHP I can use the
I tried with
After many tries and a question in StackOverflow, I found a solution which fits best into my problem:
This way the intuitive
You can find alternative ways at StackOverflow.
In PHP I can use the
return keyword, but it doesn't work on Ruby:# expected to see 1, 2 and 5; not 3 nor 4; and no errors eval "puts 1; puts 2; return; puts 3; puts 4" # => Error: unexpected return puts 5
I tried with
return, end, exit, break, and I couldn't get success. exit doesn't raise errors, but then I don't get the 5.After many tries and a question in StackOverflow, I found a solution which fits best into my problem:
lambda do eval "puts 1; puts 2; return; puts 3; puts 4" end.call puts 5
This way the intuitive
return keyword can be used inside eval to get out from it successfully.You can find alternative ways at StackOverflow.
Monday, April 11, 2011
Ways to map hashes
In Ruby, Hashes haven't the
However, sometimes we need to do something with the keys or the elements of a Hash. Here I show some ways to do that:
1. Through each_key or each_pair (first natural options, from reference):
2. Through merge (inspired here):
3. Here a way to modify the keys (from here):
4. A way to work with hashes sorted by keys (which I published here):
map or map! method; it's for Arrays.However, sometimes we need to do something with the keys or the elements of a Hash. Here I show some ways to do that:
1. Through each_key or each_pair (first natural options, from reference):
hash.each_key { |k| hash[k] = some_fun(hash[k]) }
hash.each { |k, v| hash[k] = some_fun(v) }
hash.each_pair { |k, v| hash[k] = some_fun(v) }
2. Through merge (inspired here):
hash.merge(hash) { |k, ov| sume_fun(ov) }
3. Here a way to modify the keys (from here):
Hash[*hash.map{|key,value| [key.upcase, value]}.flatten]
4. A way to work with hashes sorted by keys (which I published here):
hash.keys.sort.each { |k| puts k + " => " + hash[k] + "
\n" }
Tuesday, April 5, 2011
How to run Ruby CGI scripts in Windows 7 with XAMPP
I use Ubuntu to develop my apps, but sometimes I need to run scripts in windows.
In a computer with Windows 7, I've installed Ruby and XAMPP. It runs PHP script very well, but when I tried to run a Ruby CGI script, I got the error:
It's due to the "shebang" first line of the script:
In my local installation, ruby is in:
That's not much different from the linux path. I solved the problem by creating a symbolic link usr pointing to ruby at root directory. To do that, run cmd as Administrator and type:
That was enough to run my scripts. :)
In a computer with Windows 7, I've installed Ruby and XAMPP. It runs PHP script very well, but when I tried to run a Ruby CGI script, I got the error:
Couldn't create child process: 720002
It's due to the "shebang" first line of the script:
#!/usr/bin/ruby
In my local installation, ruby is in:
C:\ruby\bin\ruby.exe
That's not much different from the linux path. I solved the problem by creating a symbolic link usr pointing to ruby at root directory. To do that, run cmd as Administrator and type:
c: cd \ mklink /D usr ruby
That was enough to run my scripts. :)
Sunday, April 3, 2011
Two ways to write an "increment" method
1. As I did in another post:
2. Inspired here:
inc = lambda do |x|
eval "#{x} += 1"
end
a = 5
inc[:a]
puts a #=> 6
2. Inspired here:
def inc(&blk)
eval "#{yield} += 1", blk
end
x = 5
inc {:x}
puts x #=> 6
Labels:
increment,
metaprogramming,
ruby,
ways
Subscribe to:
Posts (Atom)
