Serializando e deserializando no Ruby com Marshal(dump e load)

As serialização de objetos nos dias de hoje é essencial. Precisamos serializar hashes no banco, serializar JSON para saídas e entradas de chamadas Ajax e uma pá de necessidades que não seriam possíveis sem serializarmos objetos.

Recapitulando rapidamente, serializar um objeto é transformar sua estrutura (ou estado) que está em memória num formato adequado para transmissão e/ou armazenamento, para que ele possa ser transformado novamente, num segundo momento, em um objeto na memória, com o processo que chamamos de deserialização. Mais rapidamente ainda e de forma grosseira (e espero que didática): é como pegarmos um objeto (uma variavel, array, hash…), transforma-la em texto (serialização) e depois transformar novamente em um objeto da memória (deserialização).

O processo se serialização/deserialização também é conhecido como marshalling/unmarshalling e deflating/inflating respectivamente.

Modulo Marshal

O Ruby conta com um módulo específico para serializar/deserializar chamado Marshal. Esse módulo já vem incluido no Ruby. ;)

Ele tem basicamente dois métodos:

  • Marshal.dump para serializar um objeto
  • Marshal.load para deserializar um objeto

Um exemplo básico de como isso funciona:

1
2
3
hash = {nome: "Léo Hackin"}
hash_serializado = Marshal.dump(hash) # {: nomeI"Léo Hackin:ET
hash_deserializado = Marshal.load(hash_serializado) # {:nome=>"Léo Hackin"}

Em nosso exemplo, temos uma variável chamada hash com um hash dentro (jura?!) que serializamos com o método Marshal.dump e depois deserializamos com o método Marshal.load. A variável hash_deserializado agora é um clone idêntico, em valores e tipo, ao hash original. Prova disso é que se executarmos uma comparação de tipo e valor entre eles, o resultado é verdadeiro.

1
hash.eql?(hash_deserializado) # retorna TRUE pois os valores e o tipo do objeto são exatamente iguais

Fácil né? É fácil mesmo e sem pegadinhas. :) Quer dizer, exceto algumas.

Objetos complexos com métodos, associações e por ai vai

O Marshal.dump não consegue fazer o dump de objetos que contenham binding, procedures, métodos de instância e objetos singleton. Se tentar fazer algo assim, uma exceção TypeError é lançada.

A serialização de uma instancia de um modelo ActiveRecord com associações serializa/deserializa normalmente. Mas, logicamente, esse objeto não poderá ser usado em outro ambiente que não seja o seu por motivos óbvios: ao ser deserializado, o objetivo virá com o tipo/modelo original e caso você não o tenha no seu ambiente, vai dar pau. Ex.: você serializa um objeto ActiveRecord de um modelo chamado Livro e tenta deserializa-lo em outro ambiente qualquer. :P

Versão do módulo Marshal

O Marshal.load funcionará apenas para objetos serializados com uma versão igual ou menor à do modulo que está tentando carregar.

Ou seja, se você está com a versão 4.8 do módulo Marshal, você conseguirá fazer o load apenas quando o objeto for serializado por essa versão ou menor (4.7, 4.6 …). Por sorte (ou azar) o módulo tem um versionamento diferente do Ruby. Para fazer a checagem da versão serializada, veja os dois primeiros bytes da serialização, como abaixo:

1
2
3
4
5
str = Marshal.dump("thing")

str[0].ord #=> 4

str[1].ord #=> 8

Nesse caso a versão é a 4.8.

Problemas de encoding

Em alguns casos você irá serializar objetos que podem conter valores com encodings diferentes do padrão UTF-8, como ASCII-8BIT. Ao invés de interagir por todo o hash ou objeto corrigindo os encodings, você pode forçar a conversão diretamente pelo método dump.

1
2
3
str = Marshal.dump(hash_com_caracteres_ASCII).force_encoding("UTF-8")

str = Marshal.dump(outro_hash_com_caracateres).force_encoding("ISO-8859-1").encode("UTF-8")

Serializando para um arquivo texto

Se você deseja serializar seu objeto para um arquivo texto, tenha cuidado na forma como você vai escrever esse conteúdo. Por algum motivo estranho, algumas vezes em que você joga o conteúdo serializado em um arquivo com o método write do módulo File, isso pode dar pau na hora de deserializar o conteúdo.

Para evitar o problema, escreva o dump no arquivo destino como abaixo.

1
2
3
File.open("arquivo.txt",'w') do |f|
Marshal.dump(objeto, f)
end

Para fazer a deserialização do objeto armazenado no arquivo.

1
2
3
objeto = File.open("arquivo.txt") do |file|
Marshal.load(file)
end

E é isso. Simbora.

Ref.:

  • http://www.ruby-doc.org/core-1.9.3/Marshal.html
  • http://en.wikipedia.org/wiki/Marshalling_(computer_science)
  • http://stackoverflow.com/questions/14990323/marshal-dump-format-error0xa

Ruby on Rails: referências de leitura

Aloha,

Antes de tudo gostaria de deixar aqui a surpresa (e alegria) em ver meu post sobre a migração de PHP para o Ruby on Rails depois de 5 meses na capa do iMasters. Muito bacana ver as pessoas discutindo com argumentos e tudo mais sobre Python/Django e PHP. Valew aê a todos.

Chegaram alguns e-mails do pessoal me pedindo referências de leitura, links, livros e algumas perguntando qual linguagem estudar: tentei ajudar com base no que vejo hoje como desenvolvedor e também como empresário no mercado de desenvolvimento de software. :)

Então, vai uma lista de coisas que li/leio sobre Ruby (linguagem) e Ruby on Rails (framework) e todo seu entorno. Só pra lembrar: estes foram livros que li e não um compendium de todas as leituras bacanas sobre Rails que existem: existem tanto livros bons que ainda não li quando disposição pra encher meu Kindle com eles. AHEuAe uHA E :)

Livros

Praticamente todos os livros que li são da série The Pragmatic Programmers: é uma editora muito bacana e com vários nomes de peso. O bacana é que os livros em versão digital tem valores bem atrativos e quando sai qualquer update, eles mandam um aviso para que você baixe as versões mais novas. :)

  • Agile Web Development with Rails (4rd Edition) é um ótimo livro para se começar com Rails. A linguagem é bem prática e ele explora a construção de uma aplicação de loja virtual de cabo a rabo, com testes e tudo. :) Existe a versão traduzida dele no Brasil chamada “Desenvolvimento Web Ágil com Rails“. A diferença é que essa quarta edição é com o Rails 3 já. ;)
  • Programming Ruby 1.9: The Pragmatic Programmer’s Guide é um livro muito muito bom sobre a linguagem Ruby. Não o li todo mas serve como uma ótima referencia à programação Ruby que tem várias particularidades não apenas interessantes mas essenciais para quem quer extrair o máximo da linguagem e extensibilidade do Rails.
  • Repensando a Web com Rails, do Fábio Akita, foi meu primeiro livro de Rails. Recomendo a todos não apenas porque é de um brazuca mas provavelmente um dos caras que correram atrás pela comunidade. Ele está numa versão antiga do Rails mas vale pela didática.
  • The RSpec Book, um livro obrigatório para quem quer (ou já trabalha) usando BDD como framework de testes e design de aplicações. Decidimos usar o RSpec ao invés da framework de testes que vem no Rails devido à melhor abordagem didática do BDD (precisavamos treinar um time em testes) e poder de descrição de problemas e design que ela traz para gente. Como o próprio autor diz, este é um livro para TODOS os programadores. Vale demais a pena.
  • Learn to Program é um livro extramamente introdutório sobre programação usando Ruby: isto ajuda e muito quem quer dar uma passada de olho no básico da linguagem. O livro da Pragmatic Programmers está em sua segunda edição (e mais completa) mas a primeira (e ainda muito boa) está em português neste link. :)
  • Ruby: Investigando a Linguagem, de Ivan Mecenas, é um livro bem introdutório mas ao mesmo tempo elucidativo. É um livro bem rapido de ler e que dá uma boa visão do que a linguagem pode fazer.

Sites

Muitos dos sites que leio são de referência da linguagem mas também com uma gama de coisas que ajudam e muito no dia-a-dia.

  • Rails Guides (http://guides.rubyonrails.org/) são os guias oficiais do Rails 3 (e também da 2.3). Leitura diária e obrigatória para conhecer o funcionamento da framework. Peca um pouco em detalhar mais algumas coisas e mostrar coisas que saem das conversões do Rails. :P
  • http://rubyonrails.org/ que é o site oficial do Rails: instalação, tutoriais, documentação e um monte de coisa. A versão brazuca dele está em http://www.rubyonrails.pro.br/.
  • http://www.ruby-doc.org/ documentação do Ruby :)
  • http://www.rubyonrails.pro.br/planeta/ é um agregador de blogs de vários figuras conhecidas do mundo Ruby on Rails. Vale adicionar o rss. :D
  • http://railscasts.com/ é site com toneladas de screencasts sobre Rails. Melhor do que quebrar a cabeça lendo é ver o cara quebrando a cabeça por você as vezes. Enjoy!
  • http://asciicasts.com/ tem o mesmo conteúdo que o railscasts mas … EM TEXTO!  Perfeito para quem quer ler e pesquisar por alguns termos, ver se existe um cast relativo a isso e ler código.
  • http://railsforzombies.org/ pode parecer brincadeira, mas é uma forma interessante de iniciar os estudos em Rails. Veja os vídeos, faça os exercícios … isso tudo com zumbis. :)
  • http://rubygems.org/ é o diretório oficial de gems do Ruby. As gems são como pacotes para o Ruby. Existe solução para quase tudo lá. se não existir o que você procura, contribua: faça a a sua gem e submeta ela. A comunidade agradece.

Listas de discussão, blogs, empresas e outras coisas mais

Pra fechar, alguns blogs que acompanho que falam não apenas de Rails mas de várias coisas que considero importantes para quem quer saber sobre agilidade, desenvolvimento e afins.

Enfim … tem MUITO mais coisas além disso, mas acho que já é um bocado de informação pra dar uma sacada. :)

Espero que ajude em algo. Bons estudos.