Erro ao criar objetos associados em Rails
-
22-08-2019 - |
Pergunta
Eu tenho uma ação de criar que está a tentar criar uma avaliação e um programa de uma só vez:
def create
@rating = current_user.ratings.create(params[:rating])
@rating.create_programme(params[:programme])
redirect_to ratings_path
end
Neste código, a classificação pertence a um usuário e um programa e um usuário
has_many :ratings
has_many :programmes, :through => :ratings
e um programa
has_many :users, :through => :ratings
has_many :ratings
Quando eu chamar a ação acima na RatingsController criar, o Programa não está sendo salvo como sendo de propriedade do @rating por algum motivo. Então, se eu chamar, por exemplo:
rating.programme.channel
em uma classificação em um ponto de vista, ele me diz que o programa é um objeto nulo. No entanto, o programa foi salvo bem - é apenas a associação que não tenha sido salvo. Eu tenho certeza que é uma coisa muito básica aqui, mas eu não consigo entender. Alguém pode me apontar na direção certa?
graças, a
Solução
Em resposta à sua pergunta para ajudar a tornar o código mais limpo:
def create
@rating = Rating.new(params[:rating])
@rating.user = curent_user
@rating.programme = Programme.find_or_create_by_title(params[:programme])
@rating.save
redirect_to ratings_path
end
Primeiro de tudo você chamar find_or_create para um título e, em seguida, salvá-lo, mas o registro vai aleady ser criado lá para o salvamento não faz nada em tudo. Em segundo lugar, enquanto os proxies de associação são legais para criar facilmente objetos ralated, eles podem ficar muito peludo em um relacionamento mais comlex como você tem aqui e tornar o código mais difícil de ler.
Assim, em vez de usar os proxies de associação para criar registros, atribuição direta seria melhor. É mais fácil dizer em poucas palavras exatamente o que está acontecendo e onde a informação está vindo, e não precisa de uma chamada merge feia lá dentro. É um pouco mais, mas eu pensa que a sua muito mais fácil de entender à primeira vista.
Finalmente, você provavelmente não precisa @programme
como uma variável sozinha instância posição desde que você terá acesso fácil a esse objeto de @rating.programme
em seus pontos de vista. Na maioria dos casos, é melhor passar por alguns variável de instância quanto possível, especialmente quando os objetos têm uma relação direta facilmente acessível. Sua especialmente verdadeiro no caso becuase você não está prestando um modelo em tudo.
Outras dicas
Seu código parece certo. Tente isto. Imediatamente depois de bater esta criar a ação de ir para dentro de você script / console e ver o que está acontecendo. Tipo:
Rating.last
Ele deve retornar a classificação que acabou de ser criado. Procure user_id
e programme_id
na saída e ver se eles estão definidos. Se eles são, então, você tem um outro lugar bug. Talvez você não está olhando para a classificação que você pensa que é ou algo assim.
Bem, você está tentando criar o pai da criança (classificações pertence Programa, certo?). Eu não acho que funciona.
Programme.ratings.create iria funcionar.
Eu tenho o ok trabalhando ação criar com o seguinte. Apreciaria se alguém poderia et-me saber se há uma maneira mais elegante de chegar a este trabalho:)
def create
@programme = Programme.find_or_create_by_title(params[:programme])
@programme.save
@rating = current_user.ratings.create!(params[:rating].merge(:programme_id => @programme.id))
redirect_to ratings_path
end
andy