Embora o Ruby 1.9 já tenha sido liberado há algum tempo, infelizmente ele ainda é inacessível para muitos de nós, já que muitos projetos foram iniciados em versões mais antigas do Rails, quando ele ainda era incompatível com esta nova versão do Ruby. E mesmo aqueles que estão utilizando as versões mais recentes do Rails, também precisam tomar certos cuidados já que nem todos os plugins e gems já foram preparados e testados para serem executados nesta versão do Ruby.
Já faz um tempo que o core team do Rails vêm aceitando patches que implementam certos recursos presentes apenas no Ruby 1.9, permitindo que mesmo projetos rodando sob as versões 1.8.x também possam se beneficiar destas novas funcionalidades. Uma dessas novidades que recentemente foi incluída na versão de desenvolvimento do Rails (Edge Rails) e que estará presente no próximo release, foi o novo sistema de interpolação de Strings do Ruby 1.9.
Atualmente utilizamos muito o conhecido #{} para realizar esta atividade, como demonstrado no exemplo abaixo.
firstname = "Carlos"
familyname = "Brando"
puts "#{firstname} #{familyname}"
# => "Carlos Brando"
No Ruby 1.9, além da forma exibida acima, também podemos utilizar %{} para informar os valores a serem interpolados através de um objeto do tipo Hash. Seguindo a seguinte sintaxe:
person = {:firstname => "Carlos", :familyname => "Brando"}
puts "%{firstname} %{familyname}" % person
# => "Carlos Brando"
Se você gosta de viver no limite e utiliza a versão de desenvolvimento do Rails em seus projetos, então já pode começar a utilizar este novo recurso, mesmo que ainda nem tenha o Ruby 1.9 instalado em seu computador. Mas, se você é um pouco mais conservador e não gosta de arriscar (o que pode evitar alguns problemas com bugs), você tem duas opções: esperar pelo Rails 2.3.3 (ou quem sabe o 3.0, não sei qual será o próximo) ou implantar você mesmo esta funcionalidade no seu projeto Rails atual.
Se você optou pela segunda opção, basta criar um arquivo qualquer no diretório lib do seu projeto e incluir o seguinte código nele:
if RUBY_VERSION < '1.9'
=begin
string.rb - Extension for String.
Copyright (C) 2005-2009 Masao Mutoh
You may redistribute it and/or modify it under the same
license terms as Ruby.
=end
# This feature is included in Ruby 1.9 or later but not occur TypeError.
#
# String#% method which accepts named arguments. Particularly useful if the
# string is to be used by a translator because named arguments mean more
# than %s/%d style.
class String
unless instance_methods.find {|m| m.to_s == 'bytesize'}
# For older ruby (such as ruby-1.8.5)
alias :bytesize :size
end
alias :_old_format_m :% # :nodoc:
PERCENT_MATCH_RE = Regexp.union(
/%%/,
/%\{(\w+)\}/,
/%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/
)
# call-seq:
# %(arg)
# %(hash)
#
# Format - Uses str as a format specification, and returns the result of applying it to arg.
# If the format specification contains more than one substitution, then arg must be
# an Array containing the values to be substituted. See Kernel::sprintf for details of the
# format string. This is the default behavior of the String class.
# * arg: an Array or other class except Hash.
# * Returns: formatted String
# Example:
# "%s, %s" % ["Masao", "Mutoh"]
#
# Also you can use a Hash as the "named argument". This is recommended way so translators
# can understand the meanings of the msgids easily.
# * hash: {:key1 => value1, :key2 => value2, ... }
# * Returns: formatted String
# Example:
# For strings.
# "%{firstname}, %{familyname}" % {:firstname => "Masao", :familyname => "Mutoh"}
#
# With field type to specify format such as d(decimal), f(float),...
# "%<age>d, %<weight>.1f" % {:age => 10, :weight => 43.4}
def %(args)
if args.kind_of?(Hash)
ret = dup
ret.gsub!(PERCENT_MATCH_RE) {|match|
if match == '%%'
'%'
elsif $1
key = $1.to_sym
args.has_key?(key) ? args[key] : match
elsif $2
key = $2.to_sym
args.has_key?(key) ? sprintf("%#{$3}", args[key]) : match
end
}
ret
else
ret = gsub(/%([{<])/, '%%\1')
begin
ret._old_format_m(args)
rescue ArgumentError => e
if $DEBUG
$stderr.puts " The string:#{ret}"
$stderr.puts " args:#{args.inspect}"
puts e.backtrace
else
raise ArgumentError, e.message
end
end
end
end
end
end
Não esqueça de carregar o arquivo utilizando o método require antes de utiliza-lo. É recomendado que você faça isto em algum arquivo do diretório initializers (talvez seja bom criar um arquivo apenas para esta finalidade). Também recomendo estudar o código acima para entender o que está acontecendo antes de simplesmente sair usando.
Ah, e você também pode definir tipos numéricos assim:
"%<age>d, %<weight>.1f" % {:age => 10, :weight => 43.4}
# => "10, 43.4"
Para mais informações sobre as novidades do Rails, siga-me no Twitter: @carlosbrando.
Achei legal essa nova funcionalidade, uma dúvida que tenho é em relação a velocidade, com ruby 1.9 a máquina virtual ganhou velocidade ?
@Jhonathas Matos
Eu ainda não testei para dizer com certeza, mas existem alguns testes feitos por outros programadores que revelam uma boa melhora na performance.
Perfeito, irei esperar a compatibilidate com as gems e vou testar.
Obrigado.
@Jhonathas, eu tenho alguns algoritmos para a minha tese que consomem três vezes menos memória e são aproximadamente duas vezes mais rápidos usando o Ruby 1.9 comparado com o Ruby 1.8.6. É um uso específico, mas me ajudou muito (ter que esperar 2 dias invés de 4 para o algorimto acabar me deixa muito feliz! :D).
@Carlos, vale lembrar que o I18n do Rails já foi modificado para aceitar #{} e hashes como interpolação (ou seja, compatível com o Ruby 1.9). É muito mais rápido do que {{}} no Ruby 1.8, que depende do String#gsub.
Abraços!
O que mais me desanima quando o assunto é ruby on rails é ver que todos os blogs que falam de ruby on rails são feitos em php.
Paulo, o WordPress é o melhor sistema para blogs existente e não vejo problema nenhum em ele ser feito em PHP.
Eu estou interessado na ferramenta e não na linguagem neste quesito.
p.s.: E também não tenho nada contra PHP… se fosse tão ruim não teria tanta gente usando.