VOOZH about

URL: https://rubychallenger.blogspot.com/search/label/ruby

⇱ The Ruby Challenger: ruby


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)

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:

http = Net::HTTP.new('server.com', 443)
http.use_ssl = true
      response = http.send_request('GET', path, parameters, headers)


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).

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.

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.

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!"


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:

  • 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. ;-)

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

!#/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:

#!/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:

# apt-get install libsqlite3-dev

In 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:

# apt-get install ruby1.8-dev

In 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.
That was not properly documented; the official documentation lean us to guess it would return false when the file is not found, and that's not the case.

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.

#!/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 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 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 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:

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:
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
Subscribe to: Posts (Atom)