Coisas aleatórias acontecendo no Rails 2.x
Publicado em Developer
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. :-)
Comentários
Comentários fechados.
Artigos anteriores
- Pull requests em modo raiz - sex, 22 de dezembro de 2023, 09:57:09 -0300
- Qual a idade do seu repositório? - ter, 27 de dezembro de 2022, 12:50:35 -0300
- Utilizando ctags em projetos Rails mais recentes - qui, 24 de junho de 2021, 08:23:43 -0300
- Fazendo o seu projeto brotar - seg, 15 de julho de 2019, 08:57:05 -0300
- Learn Functional Programming with Elixir - sex, 02 de março de 2018, 18:47:13 -0300
- Ambiente mínimo - Driver Driven Development - qua, 23 de agosto de 2017, 15:15:03 -0300
- Ambiente mínimo - repositórios de código - dom, 16 de abril de 2017, 13:02:14 -0300
- Ambiente mínimo - terminal e navegador - dom, 02 de abril de 2017, 21:43:29 -0300
- Utilizando muitas gems no seu projeto? - sáb, 29 de outubro de 2016, 11:57:55 -0200
- Desenvolvedores e inteligência artificial - seg, 11 de julho de 2016, 09:09:38 -0300
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")
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().
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?