Existe alguma maneira de substituir o valor de id de um modelo na criação? Algo como:
Post.create(:id => 10, :title => 'Test')
seria ideal, mas obviamente não funcionará.
ruby-on-rails
activerecord
Codebeef
fonte
fonte
Respostas:
id é apenas attr_protected, é por isso que você não pode usar atribuição em massa para defini-lo. No entanto, ao configurá-lo manualmente, ele simplesmente funciona:
Não tenho certeza de qual foi a motivação original, mas faço isso ao converter modelos ActiveHash para ActiveRecord. ActiveHash permite que você use a mesma semântica belongs_to no ActiveRecord, mas ao invés de ter uma migração e criar uma tabela, e incorrer na sobrecarga do banco de dados em cada chamada, você apenas armazena seus dados em arquivos yml. As chaves estrangeiras no banco de dados fazem referência aos ids na memória no yml.
ActiveHash é ótimo para listas de opções e pequenas tabelas que mudam com pouca frequência e apenas mudam pelos desenvolvedores. Portanto, ao passar de ActiveHash para ActiveRecord, é mais fácil apenas manter todas as referências de chave estrangeira iguais.
fonte
ActiveRecord::VERSION::STRING == "3.2.11"
aqui (com o adaptador sqlite3) e o acima funciona para mim.Experimentar
isso deve dar a você o que você está procurando.
fonte
Você também pode usar algo assim:
Embora conforme declarado nos documentos , isso contornará a segurança de atribuição em massa.
fonte
Para Rails 4:
Outras respostas do Rails 4 não funcionaram para mim. Muitos deles pareceram mudar durante a verificação usando o Console do Rails, mas quando verifiquei os valores no banco de dados MySQL, eles permaneceram inalterados. Outras respostas só funcionaram algumas vezes.
Para MySQL, pelo menos, atribuir um
id
número de id abaixo do auto incremento não funciona a menos que você useupdate_column
. Por exemplo,Se você mudar
create
para usarnew
+save
, ainda terá esse problema. Alterar manualmente oid
semelhantep.id = 10
também produz esse problema.Em geral, eu usaria
update_column
para alterar o,id
mesmo que custe uma consulta de banco de dados extra porque funcionará o tempo todo. Este é um erro que pode não aparecer em seu ambiente de desenvolvimento, mas pode corromper silenciosamente seu banco de dados de produção enquanto diz que está funcionando.fonte
Post.new.update(id: 10, title: 'Test')
Na verdade, acontece que fazer o seguinte funciona:
fonte
validate: false
, ao invés de simplesmentefalse
. No entanto, você ainda se depara com o problema do atributo protegido - há uma maneira separada de contornar o que descrevi em minha resposta.Como Jeff aponta, id se comporta como se fosse attr_protected. Para evitar isso, você precisa substituir a lista de atributos protegidos padrão. Tenha cuidado ao fazer isso em qualquer lugar onde as informações do atributo possam vir de fora. O campo id é protegido por padrão por um motivo.
(Testado com ActiveRecord 2.3.5)
fonte
podemos substituir attribute_protected_by_default
fonte
Isso não me parece o tipo de coisa que você normalmente gostaria de fazer, mas funciona muito bem se você precisar preencher uma tabela com um conjunto fixo de ids (por exemplo, ao criar padrões usando uma tarefa rake) e você deseja substituir o incremento automático (de modo que cada vez que você executar a tarefa, a tabela seja preenchida com os mesmos IDs):
fonte
Coloque esta função create_with_id no topo de seu seed.rb e então use-a para fazer sua criação de objeto onde ids explícitos são desejados.
e usar assim
ao invés de usar
Foo.create({id:1,name:"My Foo",prop:"My other property"})
fonte
Este caso é um problema semelhante que foi necessário substituir o
id
por um tipo de data personalizada:E depois :
Callbacks funcionam bem.
Boa sorte!.
fonte
id
registro de data e hora baseado em Unix. Eu fiz isso por dentrobefore_create
. Funciona bem.Para Rails 3, a maneira mais simples de fazer isso é usar
new
com owithout_protection
refinamento e entãosave
:Para os dados iniciais, pode fazer sentido ignorar a validação, que você pode fazer assim:
Na verdade, adicionamos um método auxiliar a ActiveRecord :: Base que é declarado imediatamente antes de executar os arquivos de semente:
E agora:
Para Rails 4, você deve usar StrongParams em vez de atributos protegidos. Nesse caso, você simplesmente poderá atribuir e salvar sem passar nenhum sinalizador para
new
:fonte
{}
como a resposta de Samuel acima (Rails3).id
ainda tem 10.id
foi passado como 10 - então é exatamente o que deveria ser. Se não era isso que você esperava, pode esclarecer com um exemplo?No Rails 4.2.1 com Postgresql 9.5.3,
Post.create(:id => 10, :title => 'Test')
funciona desde que ainda não exista uma linha com id = 10.fonte
você pode inserir id por sql:
fonte