Removendo referências em cascata no Rails
by Bruno Milare on February 4, 2011
O problema:
Recentement me deparei com um problema que pode ser considerado bem sutil.
Eu tinha três tabelas e cada uma tinha relacionamento 1 para n com outra, algo parecido com o MER abaixo.

Relacionamentos
Eu estava tratando a remoção em cascata das dependências utilizando :delete_all, e quando removia a tabela principal, somente o primeiro nível de referência era removido, deixando a última tabela intacta, fui atrás de saber o porque disso.
Descobri que o :delete_all age direto na tabela, portanto, assim que um registro é destruído suas dependências são destruídas direto no banco e a aplicação Rails nem se dá conta de que algo foi removido, então, quando a tabela intermediária é removida, a aplicação não sabe que tem que remover a próxima dependência e então pára por aí.
Para resolver isso utilizei o :destroy para remoção em cascata, esse método instancia o objeto a ser removido e então os callbacks são chamados, assim a aplicação é notificada da remoção e chama a próxima remoção de dependências, obviamente esse método é mais lento, vamos verificar isso na parte de performance.
Read the rest of this entry »
Exibindo consultas do banco no console do Rails
by Bruno Milare on February 3, 2011
Muitas vezes você tem a necessidade de verificar as queries que o Active Record está realizando no banco, então, para facilitar a vida existe um maneira de exibir todas as queries no console, enquanto você realiza os comandos.
Existem duas maneiras de fazer a mesma coisa:
Pelo irbrc:
Nesse caso vamos alterar o arquivo ˜/.irbrc e adicionar as seguintes linhas:
logger = Logger.new(STDOUT)
ActiveRecord::Base.logger = logger
ActiveResource::Base.logger = logger
end
Pronto, você visualizará as queries no momento de execução:
Product Load (0.3ms) SELECT `products`.* FROM `products` LIMIT 1
Pela aplicação Rails:
Adicione ao arquivo config/environment.rb o seguinte trecho de código:
ActiveRecord::Base.logger = Logger.new(stream)
ActiveRecord::Base.clear_active_connections!
end
Feito isso, quando for utilizar o console, basta redirecionar a saída do log para a saída padrão (STDOUT)
Vocês podem verificar que desta maneira é possível redirecionar o log para onde você quiser, como o exemplo abaixo:
=> #<StringIO:0x00000104896908>
ruby-1.9.2-rc1 > log_to buffer
ruby-1.9.2-rc1 > Product.first
ruby-1.9.2-rc1 > buffer.string
=> " \e[1m\e[35mProduct Load (0.2ms)\e[0m SELECT `products`.* FROM `products` LIMIT 1\n"
Acho que é isso,
fica aí a dica.
[]‘s
Bruno.
Ruby: Shallow Copy vs Deep Copy
by Bruno Milare on February 2, 2011
Neste post vou discutir sobre como é feita a cópia de objetos em Ruby.
Os métodos para duplicar um objeto são: dup, clone e =. Em Ruby todos esses métodos utilizam shallow copy. Lembrando que a única diferença entre dup e clone é que dup não copia o estado do objeto original. Agora vamos discutir como funciona cada um desses métodos de duplicação.
Shallow:
Este método cria realmente um novo objeto na memória, porém todas as referências do objeto original são mantidas. Assim se você você alterar alguma referência do objeto original acreditando estar mantendo os valores da cópia, você está enganado, pois as mesmas serão alteradas também.
Por exemplo, imaginem uma lista ligada de três nós, se fizermos uma cópia do segundo nó essa cópia vai continuar apontando para o mesmo terceiro nó que o nó original, assim, se alterarmos o terceiro nó estaremos alterando tanto para o segundo nó original quanto para sua cópia.
Deep:
Fazendo uma deep copy, o objeto em questão é duplicado e todas as suas referências também, assim a cópia se torna totalmente independente do objeto original. Voltando ao exemplo anterior, se tivermos uma lista ligada com três nós e copiarmos o segundo nó, além de criar uma nova instância com a cópia do segundo nó, vai ser criado uma nova instância do terceiro nó que ele tem como próximo.
Configurando o Bundler com o Sinatra
by Márcio Gasparotto on February 1, 2011
Esses dias comecei um novo projeto usando o Sinatra e queria configurar o bundler, foi algo bem simples mas se alguém precisar, fica a dica.
Passo 1: Crie o arquivo Gemfile na raiz do projeto.
$ touch Gemfile
Passo 2: Adicione as suas configurações/gems no Gemfile, no meu caso ficou assim.
gem "sinatra"
gem "dm-sqlite-adapter"
gem "datamapper"
group :test do
gem "rspec"
gem "rack-test"
end
Passo 3: No arquivo config.ru (tambem na raiz do projeto) setei as seguintes configurações
require 'bundler'
require 'sinatra'
require 'sinatra/base'
set :app_name, 'Nome da sua App'
set :author_name, 'Marcio Gasparotto'
set :author_email, 'email@gmail.com'
Bundler.require
require File.join(File.dirname(__FILE__), 'lib', 'sua_app.rb')
run Sinatra::Application
Ai pra rodar sua aplicação basta executar o comando:
$ rackup
This is it!
Rails e Javascript: Escrevendo seu próprio javascript.
by Márcio Gasparotto on December 9, 2009
O integração padrão entre Ruby on Rails e Javascript sempre foi muito boa, as possibilidades com rjs, métodos que respondem javascript, json, etc. ajudam muito.
Mas o que vou falar hoje é sobre como escrever seu próprio javascript, sem depender dos helpers do rails. Na minha opinião, embora a integração existente ajude muito, quando queremos ir pouco mais fundo, ou em um projeto muito grande que exija mais do que simples chamadas ajax eu prefiro criar meu próprio javascript, isso pelo simples fato de que faço do jeito que eu quero, organizo minha biblioteca de arquivos js da forma que melhor se adapta ao projeto e tenho total controle sobre o que estou fazendo, não fico “preso” ao jeito de fazer “imposto” pelo rails.
Só um aparte neste ponto, NÃO estou dizendo que rjs é ruim pelo contrário ele ajuda muito em muitas coisas.
Bem, dito isso vamos por a mão na massa! Em primeiro lugar aviso que usarei o jquery ao inves do prototype, não vou entrar em detalhes de como configurar o jquery no rails pra isso você pode usar o jrails (eu uso).
O cenário que escolhi para esse post foi algo bem básico, só para exemplificar mesmo, imagine o seguinte: Um cadastro de produtos, esses produtos tem uma categoria e uma subcategoria, então quando eu escolher uma categoria em um select quero que o select de subcategorias seja carregado dinamicamente:
o meu controller eu adiciono o seguinte metodo:
1 2 linha = params[:linha] || 0 3 @sublinhas = Sublinha.sublinha_by_linha(linha).collect {|c| [c.description, c.codesublinha] } 4 render :layout => false 5 end
Ai na view do metodo:
1 2 SubLinha 3 4 nenhuma sublinha foi encontrada. 5 6 8 9
Por fim no meu formulário, na pagina de cadastro de produto:
1 2 3 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 47 48 49 50 51 52
Vejam que para o exemplo eu estou usando o formtastic, por isso o formulário um pouco diferente do convencional.
Lembre sempre de setar o método no routes.rb também
map.resources :products, :collection => { :ajax_load_sublinhas => :get }
Vejam que temos muita liberdade para fazer a coisa do nosso jeito, esse foi só um exemplo bem simples de selects dinâmicos, mas o leque de coisas que podemos fazer é o quanto a nossa imaginação permitir.
Qualquer dúvida é só comentar.
This is it!