Não sei dizer se isto é um bug ou não, mas na minha opinião isto representa um problema. Veja o código abaixo, onde tento alterar a conta de um usuário usando sua foreign key em um projeto Rails 2.1 ou anterior:
end
user = User.first
# => #<User id: 1, login: "admin", account_id: 1>
user.account
# => #<Account id: 1, name: "My Account">
user.account_id = 2
# => 2
user.account
# => #<Account id: 1, name: "My Account">
Note que estou alterando a conta do usuário, mas a associação não foi atualizada. Mesmo depois de salvar o objeto user, se ele não for recarregado, a associação continuará mostrando a conta errada.
No Rails 2.2 este problema foi corrigido, veja:
end
comment = Comment.first
# => #<Comment id: 1>
>> comment.post
# => #<Post id: 1>
>> comment.post_id = 2
# => 2
>> comment.post
# => #<Post id: 2>
Veja que ao alterar o post por meio de sua foreign key, automaticamente a associação foi atualizada.
Todos os exemplos dados aqui funcionarão somente no Ruby on Rails 2.2 ou superior. Você pode encontrar mais detalhes sobre esta e outras novidades do Rails 2.2 no e-book “Ruby on Rails – O que há de novo?“.
e no segundo exemplo, caso o post numero 2 não existisse, ele retornaria nil?
Muito bom, eu já perdi um tempo com esse mesmo problema, e era no mínimo irritante.
Boa pergunta Thiago!
Se você informar um id que não existe ele funcionará como era no passado, sem atualizar a associação.
ola Carlos,
eu particularmente, gosto muito do activerecord, mas isse tipo de coisa me deixa muito triste pois mata completamente a POO, na minha opnião o atributo
post_id não deveria esta presente para escrita em comment, por que?
encapsulamento,o que gostariamos de fazer é trocar o objeto post não o “post_id”,bem de qualquer forma excelente dica e desculpa pelo “purismo OO”.
O problema Bruno é que imagine uma atualização em campos de ids muitas vezes é necessária. Com quando selecionamos um item em uma drop_down_list e depois precisamos atualizar o registro.
beleza carlos,
se o item selecionado, puder ser recuperado como comentario no controller,
então uma abordagem seria:
item_selecionado.change_post(new_post) # codigo do change_post em Comment... def change_post(other_post) @post_id = other_post.id save! enddado que itemselecionado aqui é um comment e new_post foi recuperado de algum lugar ( banco, parametros etc) a vantagem disso é que fica claro sua intenção de mudar o “dono” do objeto além de manter o encapsulamento.
quero deixar claro que isso é apenas uma maneira mais OO apenas,até porque certo e errado em alguns casos são bem subjetivos, sempre depende da situação e do problema em questão.
grande abraço
Bruno
Concordo Bruno.