Blog

LISTAR TODOS OS POSTS - Assine os feeds dos posts e comentários

Coisas aleatórias acontecendo no Rails 2.x

Publicado/atualizado em 24/01/2008 10:14

Não, não tem nada errado no Rails 2.x não, mas se vocês usavam código do tipo:

>> Produto.find(:all).instance_eval{ self[rand()*self.size] }
=> #<Produto id: 7, nome: "Caneta", valor: 3.10>

para selecionar um elemento aleatório do resultado, agora é só fazer isso:

>> Produto.find(:all).rand
=> #<Produto id: 2, nome: "Lapiseira", valor: 10.50>

O pequeno detalhe é que o primeiro código vai dar pau pois ele vai retornar, no exemplo, um objeto do tipo Produto, que não tem um método *. Foi o que aconteceu em um projeto aqui. :-)

Permalink: http://eustaquiorangel.com/posts/507

salvar no del.icio.ussalvar no diggsalvar no rec6 Veja o que estão dizendo sobre isso.

Comente

Linhas em branco viram saltos de linha. Se você quiser mostrar algum código, por favor use o pastebin e informe a URL.

*

*

Responda: Qual a sigla de File Transfer Protocol?  
Clique aqui se não souber essa resposta!

* campos obrigatórios

Comentários

1 - ArthurGeek disse em 28/01/2008 12:20

TaQ, tem algum motivo especial em precisar carregar *todos* os produtos para selecionar apenas um produto em especial?

Não seria melhor usar um find(:first) e um rand do banco de dados, em SQL?


2 - TaQ disse em 28/01/2008 12:36

Arthur,

Nesse caso, são poucos registros e ... algumas consultas, então não consome tantos recursos.

Lógico que com uma carga mais pesada, seria melhor pegar um randômico direto do banco e usar o :first como você falou, mas o que eu quis expor foi que agora se alguém tentar usar um rand() em algum ponto e der de cara com alguma mensagem de erro, é por causa da implementação do dito cujo no ActiveSupport. No caso de precisar usar o rand() "normal" em algum desses pontos, deve-se explicitar como Kernel.rand().


3 - TaQ disse em 28/01/2008 12:54

Complementando um pouco, *se os registros não tem nenhum id pulado*, ou seja, se você não apagou nenhum na sequência, dá para fazer direto:

Produto.find(:first,:conditions=>["id=?",rand(Produto.count)])

ou mesmo, no caso do MySQL, nesse caso pulando o primeiro SELECT que ele usa para o count mostrado acima mas talvez perdendo um pouco a portabilidade (já que, por exemplo, no Oracle teria que usar um treco doido chamado dbms_random.value e usar subqueries para limitar o resultado), daria para fazer assim:

Produto.find_by_sql("select * from produtos order by rand() limit 1")


Anterior Próximo Últimos Índice