Posts com o tag ‘linguagens de programação’
7abr2010
Muita gente acha (assim como eu achava há um tempo atrás) que não é possível utilizar debug (ou “depurar”, ou “debugar”) uma aplicação Ruby on Rails. Acredito que isso se deve ao fato de Ruby ser uma linguagem interpretada, diferente de outras linguagens que requerem compilação.

Existe uma forma muito simples de se “debugar” em Rails. Primeiro vamos instalar a gem ruby-debug.
$ sudo gem install ruby-debug
Agora vamos criar uma aplicação Rails de exemplo para utilizar o debug.
$ rails prodis-debug
$ cd prodis-debug
$ rails script/generate scaffold MyModel my_text:string my_value:float
$ rake db:migrate
E ao invés de subir a aplicação com script/server, iniciamos a aplicação em modo debug:
$ rdebug script/server
/Users/Prodis/Blog/code/prodis-debug/script/server:2
require File.expand_path('../../config/boot', __FILE__)
(rdb:1)
Esse é o momento de adicionarmos o(s) breakpoint(s) desejados, informando o arquivo e a linha do mesmo. Vamos colocar um breakpoint na ação create de MyModelsController:
(rdb:1) break app/controllers/my_models_controller.rb:43
Breakpoint 1 file /Users/Prodis/Blog/code/prodis-debug/app/controllers/my_models_controller.rb, line 43
E usamos o comando cont para prosseguir com o carregamento da aplicação no servidor.
(rdb:1) cont
=> Booting Mongrel
=> Rails 2.3.5 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
No browser, através do endereço http://localhost:3000/my_models/new, vamos criar um novo registro de MyModel.

Quando clicarmos no botão “Create”, a aplicação irá parar no breakpoint que colocamos na linha 43 de MyModelsController.
Breakpoint 1 at /Users/Prodis/Blog/code/prodis-debug/app/controllers/my_models_controller.rb:43
/Users/Prodis/Blog/code/prodis-debug/app/controllers/my_models_controller.rb:43
@my_model = MyModel.new(params[:my_model])
(rdb:6)
A partir daqui podemos investigar o código e ter acesso as suas variáveis. Por exemplo, exibindo os valores da variável params:
(rdb:6) p params
{"my_model"=>{"my_text"=>"I am some text", "my_value"=>"50.00"},
"commit"=>"Create", "authenticity_token"=>"qN9mUhJelZD0V/P2CB1fhBkQrIxFvvk+NRkY5m6EFWg=",
"action"=>"create", "controller"=>"my_models"}
Mas a maneira mais fácil de inspecionar variáveis é pelo irb, que irá se manter no contexto atual onde a aplicação está parada.
(rdb:6) irb
irb(#):001:0> params
=> {"my_model"=>{"my_text"=>"I am some text", "my_value"=>"50.00"},
"commit"=>"Create", "authenticity_token"=>"qN9mUhJelZD0V/P2CB1fhBkQrIxFvvk+NRkY5m6EFWg=",
"action"=>"create", "controller"=>"my_models"}
irb(#):002:0>
Saindo do irb (com o comando exit), nós voltamos para o ambiente de debug. Há uma série de comandos úteis para se utilizar. Um deles é o list, que exibe o trecho de código onde a aplicação está parada e indicando sua linha exata através de uma seta:
(rdb:6) list
[38, 47] in /Users/Prodis/Blog/code/prodis-debug/app/controllers/my_models_controller.rb
38 end
39
40 # POST /my_models
41 # POST /my_models.xml
42 def create
=> 43 @my_model = MyModel.new(params[:my_model])
44
45 respond_to do |format|
46 if @my_model.save
47 flash[:notice] = 'MyModel was successfully created.'
(rdb:6)
Para avançar até a próxima linha, usamos o comando next:
(rdb:6) next
/Users/Prodis/Blog/code/prodis-debug/app/controllers/my_models_controller.rb:45
respond_to do |format|
(rdb:6)
Para listar todos os comandos disponíveis, basta entrarmos no help:
(rdb:6) help
ruby-debug help v0.10.3
Type 'help ' for help on a specific command
Available commands:
backtrace delete enable help next quit show trace
break disable eval info p reload source undisplay
catch display exit irb pp restart step up
condition down finish list ps save thread var
continue edit frame method putl set tmate where
(rdb:6)
Também podemos visualizar a ajuda de um comando específico:
(rdb:6) help next
n[ext][+-]?[ nnn] step over once or nnn times,
'+' forces to move to another line.
'-' is the opposite of '+' and disables the force_stepping setting.
(rdb:6)
E para continuar a execução da aplicação, usamos o comando continue (ou um dos seus álias c ou cont)
(rdb:6) continue
Processing MyModelsController#create (for 127.0.0.1 at 2010-03-20 12:20:54) [POST]
Parameters: {"my_model"=>{"my_text"=>"I am some text", "my_value"=>"50.00"},
"commit"=>"Create", "authenticity_token"=>"qN9mUhJelZD0V/P2CB1fhBkQrIxFvvk+NRkY5m6EFWg="}
MyModel Create (0.5ms) INSERT INTO "my_models" ("my_text", "created_at", "updated_at", "my_value")
VALUES('I am some text', '2010-03-20 15:45:19', '2010-03-20 15:45:19', 50.0)
Redirected to http://localhost:3000/my_models/4
Completed in 1464995ms (DB: 1) | 302 Found [http://localhost/my_models]
Existe também uma outra maneira de se “debugar” com a gem ruby-debug. Nós podemos colocar uma instrução debugger (que na verdade é um método) em qualquer lugar do código para marcar como breakpoint. O Railscast #54 Debugging with ruby-debug mostra os passos de como fazer isso.
Eu particularmente gosto de configurar os breakpoints direto no Terminal, evitando assim ter que colocar qualquer informação de debug no código.
Esse esquema de debug não se restringe somente à aplicações Rails. Você pode muito bem utilizá-lo com código Ruby diretamente. Por exemplo, o código abaixo é do arquivo some_class.rb:
#lib/some_class.rb
class SomeClass
def some_method
# do something here
end
def other_method
# do another thing here
end
end
É só utilizar o comando rdebug passando o nome do arquivo:
$ rdebug lib/some_class.rb
/Users/Prodis/Blog/code/prodis-debug/lib/some_class.rb:2
class SomeClass
(rdb:1)
Para informações mais detalhadas sobre a gem ruby-debug, veja a documentação completa.
Post original:
http://prodis.pro.br/2010/03/20/utilizando-debug-em-aplicacoes-rails
.
Link deste post
Tags: Debug, Desenvolvimento de Software, linguagens de programação, Prodis, rails, ruby, ruby on rails, rubyonrails
22mar2010

Nas últimas semanas, a equipe que eu trabalho estava desenvolvendo um web service onde havia a necessidade de renderizar o retorno de uma lógica de negócio em representações XML. Digo representações (no plural), pois para um retorno com sucesso a representação seria uma e para retorno com erro a representação seria outra.
Por exemplo, um retorno com sucesso:
<natural-person>
<name>Prodis</name>
<cpf>01234567890</cpf>
</natural-person>
E um retorno sem sucesso:
<error>
<description>CPF inválido.</description>
</error>
Como era um web service em REST, para sucesso retornamos o código de status HTTP “200 OK” e, dependendo do não sucesso da operação, o código de status HTTP da resposta poderia ser “400 Bad Request”, “404 Not Found” ou qualquer outro código 4xx ou 5xx que melhor se adequasse.
Mantendo um controller magro, a idéia era somente instanciar uma classe de negócio, chamar um método e renderizar o retorno. Algo como:
class NaturalPersonController < ActiveRecord::Controller
def index
business = SomeBusiness.new
natural_person = business.search_by_cpf params[:cpf]
# TODO: Renderizar pessoa física ou mensagem de erro
end
end
A partir daqui a equipe iniciou uma discussão sobre a melhor forma de se obter o(s) retorno(s) esperado(s). O controller precisava saber se a consulta havia sido feita com sucesso, para renderizar um objeto NaturalPerson retornando o código de status HTTP 200, ou se a consulta não tivesse sucesso, renderizar a mensagem de erro retornando um código de status HTTP 4xx adequado.
Como “bons programadores .NET e Java”, a primeira coisa que pensamos foi lançar uma exceção customizada caso a consulta não tivesse sucesso, capturar essa exceção no controller e, através das informações de descrição de erro e código de status HTTP contidas nessa exceção, renderizar o retorno adequado.
class NaturalPersonController < ActiveRecord::Controller
def index
business = SomeBusiness.new
begin
natural_person = business.search_by_cpf params[:cpf]
render natural_person, 200
rescue BusinessException => e
render e.error, e.status_code
end
end
end
A gente não tinha visto muito código Ruby utilizando begin rescue, então essa solução não nos pareceu muito “Ruby way”. Achamos melhor pedir a opinião de alguém com mais experiência em Ruby. Perguntamos ao Rafael Rosa, que nos disse que cada vez que lançamos uma exceção em Ruby “alguma coisa ruim acontece no servidor” e consequentemente a aplicação ficará mais lenta.
Ele indicou um post falando a respeito:
http://www.simonecarletti.com/blog/2010/01/how-slow-are-ruby-exceptions
Rafael Rosa nos sugeriu retornar um array de duas posições: uma com o código de status HTTP e outra com o objeto a ser renderizado.
class NaturalPersonController < ActiveRecord::Controller
def index
business = SomeBusiness.new
result = business.search_by_cpf params[:cpf]
render result[1], result[0]
end
end
Resolveu, mas o código não ficou muito intuitivo. A partir daí imaginamos algumas outras soluções.
Retornar um hash:
class NaturalPersonController < ActiveRecord::Controller
def index
business = SomeBusiness.new
result = business.search_by_cpf params[:cpf]
render result[:data], result[:status_code]
end
end
Criar uma classe de retorno:
class SomeBusinessResult
attr_accessor :status_code, :data
end
class NaturalPersonController < ActiveRecord::Controller
def index
business = SomeBusiness.new
result = business.search_by_cpf params[:cpf]
render result.data, result.status_code
end
end
Posteriormente, o Rafael Rosa também sugeriu essa última opção, mas criando uma Struct ao invés de uma classe.
Então eu sugeri o método search_by_cpf retornar dois valores. Todos da equipe me perguntaram: “Como assim retornar dois valores?”. Falei que em Ruby um método pode retornar vários valores, que vi isso no livro The Ruby Programming Language
.

O código do controller ficou bem mais intuitivo:
class NaturalPersonController < ActiveRecord::Controller
def index
business = SomeBusiness.new
status_code, data = business.search_by_cpf params[:cpf]
render data, status_code
end
end
O método search_by_cpf está retornando tanto o código de status HTTP quanto os dados para serem renderizados:
class SomeBusiness
def search_by_cpf(cpf)
# Lógica de negócio aqui
return 200, natural_person
end
end
Note que mesmo a linha 4 sendo a última linha de instrução do método, o retorno de mais de um valor obrigatoriamente precisa utilizar o comando return.
Quando há mais de um valor de retorno para um método, os valores são colocados implicitamente dentro de uma array e essa array fica sendo o único retorno do método.
O mesmo resultado seria obtido dessa forma:
class Business
def search_by_cpf(cpf)
# Lógica de negócio aqui
[200, natural_person]
end
end
Quem está consumindo um método que retorna mais de um valor, pode utilizar o recurso de atribuição paralela do Ruby para distribuir os valores de retorno em variáveis distintas, como é o caso no nosso controller:
class NaturalPersonController < ActiveRecord::Controller
def index
business = SomeBusiness.new
status_code, data = business.search_by_cpf params[:cpf]
render data, status_code
end
end
O dinamismo do Ruby lhe oferece várias opções para você encontrar soluções para o mesmo problema ou questão. Cabe a você decidir qual melhor abordagem para seu tipo de problema. O interessante é você conhecer essas opções para facilitar a sua decisão.
Post original:
http://prodis.pro.br/2010/02/20/metodos-que-retornam-mais-de-um-valor-em-ruby
.
Link deste post
Tags: Desenvolvimento de Software, Exception, linguagens de programação, Prodis, rails, REST, ruby, ruby on rails
18dez2009
Em um post anterior mostrei como serializar objetos em JSON utilizando .NET. Agora vamos fazer a mesma coisa com Ruby on Rails.
Vamos utilizar como exemplo uma classe de modelo chamada SomeFake:
class SomeFake < ActiveRecord::Base
end
Utilizando essa migration:
class CreateSomeFakes < ActiveRecord::Migration
def self.up
create_table :some_fakes do |t|
t.string :text
t.float :value
t.timestamps
end
end
def self.down
drop_table :some_fakes
end
end
No script/console vamos criar uma instância do modelo SomeFake com os seguintes dados:
>> fake = SomeFake.create :text => "I am a sample text.", :value => 150.85
=> #<SomeFake id: 1, text: "I am a sample text.", value: #<BigDecimal:18ac9f0,'0.15085E3',8(12)>,
created_at: "2009-12-13 19:43:28", updated_at: "2009-12-13 19:43:28">
Então queremos serializar a variável fake em JSON para obter o seguinte resultado:
{"id":1,"text":"I am a sample text.","value":150.85}
Para fazer isso, vamos chamar o método to_json na variável fake (estou usando o comando print para uma exibição melhor no console do JSON gerado):
>> print fake_json = fake.to_json
"{"some_fake": {"updated_at": "2009-12-13T19:43:28Z", "text": "I am a sample text.",
"id": 1, "value": 150.85, "created_at": "2009-12-13T19:43:28Z"}}"
O resultado que obtemos não é exatamente igual ao que estávamos querendo.
Primeiro, o nome do nosso modelo foi serializado como raiz do objeto em JSON. Isso aconteceu porque por padrão em uma aplicação Rails, a opção ActiveRecord::Base.include_root_in_json é configurada para true no arquivo config/initializers/new_rails_defaults.rb. Nós podemos alterar essa opção para false nesse arquivo, o que afeta a serialização em JSON de toda a aplicação, ou podemos alterá-lo no próprio script/console para nossos testes:
>> ActiveRecord::Base.include_root_in_json = false
=> false
Agora nosso objeto serializado fica assim:
>> print fake_json = fake.to_json
"{"updated_at": "2009-12-13T19:43:28Z", "text": "I am a sample text.", "id": 1,
"value": 150.85, "created_at": "2009-12-13T19:43:28Z"}"
A segunda diferença é que não queremos que os atributos de timestamps (created_at, updated_at) sejam serializados. Então vamos dizer para o método to_json não serializar esses atributos, utilizando a opção except:
>> print fake_json = fake.to_json(:except => [:created_at, :updated_at])
"{"text": "I am a sample text.", "id": 1, "value": 150.85}"
Para fazer o inverso, transformar dados em JSON para um objeto, criamos uma nova instância da classe SomeFake e chamamos o método from_json passando a variável fake_json como parâmetro:
>> other_fake = SomeFake.new
=> #<SomeFake id: nil, text: nil, value: nil, created_at: nil, updated_at: nil>
>> other_fake.from_json fake_json
=> #<SomeFake id: nil, text: "I am a sample text.", value: #<BigDecimal:1708a04,'0.15085E3',8(12)>,
created_at: nil, updated_at: nil>
Caso você precise serializar objetos em JSON sem os atributos timestamps com frequência, ao invés de sempre passar a opção except para o método to_json, podemos incluir um novo método na classe ActiveRecord::Base que faça a serialização sem esses atributos. Dessa forma, todos os nossos modelos terão essa funcionalidade.
Vamos chamar esse método de to_json_no_timestamps, o qual sua implementação é mostrada abaixo:
class ActiveRecord::Base
def to_json_no_timestamps(options = {})
timestamps_options = [:created_at, :updated_at]
if (options.has_key? :except)
if (options[:except].class == Array)
timestamps_options = options[:except] | timestamps_options
else
timestamps_options < < options[:except].to_sym unless options[:except].nil?
end
end
options[:except] = timestamps_options
to_json options
end
end
E então basta chamar nosso novo método em uma instância de qualquer modelo:
>> fake = SomeFake.first
=> #<SomeFake id: 1, text: "I am a sample text.", value: #<BigDecimal:1712798,'0.15085E3',8(12)>,
created_at: "2009-12-13 19:43:28", updated_at: "2009-12-13 19:43:28">
>> print fake_json = fake.to_json_no_timestamps
"{"text": "I am a sample text.", "id": 1, "value": 150.85}"
Post original:
http://prodis.pro.br/2009/12/13/serializacao-de-objetos-em-json-com-ruby-on-rails
.
Link deste post
Tags: ActiveRecord, JSON, linguagens de programação, Prodis, rails, ruby, ruby on rails, Serialização
15dez2009
Aqui na Locaweb utilizamos alguns projetos de Software Livre para auxiliar na criação de nossos produtos. Além de utilizarmos esses softwares, tentamos sempre que possível contribuir para a evolução dos projetos.

Pensando nisso, decidimos na última sexta-feira dedicar um dia inteiro de alguns desenvolvedores à contribuição ao Software Livre.
Desta vez, o projeto escolhido foi o Gitorious. O gitorious é um gerenciador de projetos git (uma versão livre do Github). Cerca de 12 desenvolvedores entraram em uma sala de reunião e seguiram uma série de tarefas pré-definidas em um backlog. Estas tarefas foram geradas a partir de problemas reais sentidos por clientes do gitorious (no caso os próprios desenvolvedores), além de sugestões de features que poderiam ser implementadas.

Alguns exemplos de histórias implementadas:
- Apresentar o conteúdo do arquivo README na página incial do projeto.
- Bug-Fix: Authorized_Keys deve ser gerado com permissão certa.
- Refatorações e melhoria na cobertura de testes
A empresa também patrocinou refrigerante e pizza para deixar o clima mais descontraído.

O resultado está publicado no próprio gitorious no branch do Fabio Hisamoto.
Link deste post
Tags: ferramentas, gitorious day, linguagens de programação, Linux, rails, ruby, ruby on rails
28out2009
Serializar e deserializar instâncias de objetos no formato JSON com .NET acaba sendo muito simples.
Vamos utilizar como exemplo a classe abaixo:
public class SomeFakeClass
{
public int ID { get; set; }
public string Text { get; set; }
public decimal Value { get; set; }
}
E criamos uma instância dela:
SomeFakeClass fake = new SomeFakeClass
{
ID = 123,
Text = "I am a sample text.",
Value = 150.85M
};
Então queremos serializar a variável fake em JSON para obter o seguinte resultado:
{"ID":123,"Text":"I am a sample text.","Value":150.85}
A classe DataContractJsonSerializer torna essa tarefa muito fácil. Basta escrever os dados serializados para um Stream usando o método WriteObject e depois recuperar uma string a partir desse Stream:
MemoryStream stream = new MemoryStream();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(SomeFakeClass));
serializer.WriteObject(stream, obj);
string json = return Encoding.Default.GetString(stream.ToArray());
Para fazer o inverso, transformar dados em JSON para um objeto, usamos o método ReadObject passando o Stream que possui os dados serializados:
string json = "{"ID":123,"Text":"I am a sample text.","Value":150.85}";
MemoryStream stream = new MemoryStream(json);
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(SomeFakeClass));
SomeFakeClass fake = (SomeFakeClass)serializer.ReadObject(stream);
Um detalhe importante é que a partir do .NET Framework 3.5 Service Pack 1 não há mais a necessidade de decorar a classe que queremos serializar com os atributos DataContract e DataMember, como o exemplo abaixo:
[DataContract]
public class SomeFakeClass
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Text { get; set; }
[DataMember]
public decimal Value { get; set; }
}
Isso somente se faz necessário se quisermos ter uma controle maior do que será serializado, como por exemplo, serializar uma propriedade com um nome diferente. Na classe abaixo, a propriedade Text é configurada para ser serializada com o nome Message:
[DataContract]
public class SomeFakeClass
{
[DataMember]
public int ID { get; set; }
[DataMember(Name = "Message")]
public string Text { get; set; }
[DataMember]
public decimal Value { get; set; }
}
Os dados serializados em JSON podem ser algo como:
{"ID":123,"Message":"I am a sample text.","Value":150.85}
Para usar a classe DataContractJsonSerializer, que está no namespace System.Runtime.Serialization.Json, é necessário adicionar referências para dois assemblies no seu projeto:
- System.Runtime.Serialization
- System.ServiceModel.Web
Agora que já sabemos como serializar e deserializar em JSON, podemos criar um utilitário que faz esse trabalho. O exemplo abaixo utiliza Extensions Methods combinados com Generics:
public static class JsonSerializerExtensions
{
public static string ToJson<T>(this T obj)
{
MemoryStream stream;
using (stream = new MemoryStream())
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
serializer.WriteObject(stream, obj);
}
return Encoding.Default.GetString(stream.ToArray());
}
public static T FromJson<T>(this string json)
{
T obj;
using (MemoryStream stream = new MemoryStream(Encoding.Default.GetBytes(json)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
obj = (T)serializer.ReadObject(stream);
}
return obj;
}
}
E um exemplo de sua utilização:
SomeFakeClass fake = new SomeFakeClass
{
ID = 123,
Text = "I am a sample text.",
Value = 150.85M
};
string fakeJson = fake.ToJson();
SomeFakeClass otherFake = fakeJson.FromJson<SomeFakeClass>();
.
O código-fonte desse utilitário você pode baixar aqui.
Post original:
http://prodis.pro.br/2009/10/23/serializacao-de-objetos-em-json-com-net
.
Link deste post
Tags: .NET, DataContract, JSON, linguagens de programação, Prodis, Serialização