ruby-on-rails - 在表单中创建带有子对象的嵌套对象
问题描述
我是一个正在尝试在他的应用程序中做某事的 Rails 菜鸟。我的问题是:
我有一个 Corso 模型、一个 Libro 模型和一个 Annuncio 模型。Corso has_many Libro, Libro has_many Annuncio, Annuncio belongs_to Libro 和 Libro belongs_to Corso。我想要一个用户可以创建 Libro 的表单(必须与 Corso 相关联),同时必须创建该 Libro 的 Annuncio。我真的吓坏了,我看到了数百次讨论,但没有解决我的问题。每次我改变一些东西时,我都会得到一些不同的错误。
我的重点是: - 当我提交表单时,如何将 corso_id(我的意思是,对象 Corso 已经在数据库中定义)传递给新的 Libro;-我不明白为什么要创建 Libro 对象(所有字段为零),但 Annuncio 对象却没有。似乎 LibroController/new 中的代码 @libro.annuncios.build 没用。
我希望你能帮助我让这个表格正常工作。
图书馆控制器:
class LibroController < ApplicationController
def new
@corso = Corso.find(params[:corso_id])
@libro = @corso.libros.build
@libro.annuncios.build
end
def create
@corso = Corso.find(params[:corso_id])
@libro = @corso.libros.build(libro_params)
if @libro.save
redirect_to @libro
else
redirect_to root_path
end
end
def show
@libro = Libro.find(params[:id])
end
def index
end
private
def libro_params
params.require(:libro).permit(:titolo, :autori, :casa_editrice, :edizione, :anno_pubblicazione, :ISBN, :immagine, :corso_id, annuncios_attributes[:prezzo, :note])
end
end
Annuncio控制器:
class AnnuncioController < ApplicationController
def new
@annuncio = Annuncio.new
end
def create
@libro = Libro.find(params[:libro_id])
@annuncio = @libro.annuncio.build(annuncio_params)
if @annuncio.save
redirect_to @libro
else
redirect_to root_path
end
end
private
def annuncio_params
params.require(:annuncio).permit(:prezzo, :note)
end
end
天秤座型号:
class Libro < ApplicationRecord
belongs_to :corso, inverse_of: :libros
has_many :annuncios, inverse_of: :libro
accepts_nested_attributes_for :annuncios
end
通告型号:
class Annuncio < ApplicationRecord
belongs_to :utente, inverse_of: :annuncios
belongs_to :libro, optional: true, inverse_of: :annuncios
end
科索型号:
class Corso < ApplicationRecord
belongs_to :facolta
has_many :libros
validates :nome, uniqueness: true
end
routes.rb(有点乱)
Rails.application.routes.draw do
get 'facolta/new'
get 'sessions/create'
get 'sessions/destroy'
get 'users/new'
get 'corso/index'
get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
get 'signout', to: 'sessions#destroy', as: 'signout'
resources :sessions, only: [:create, :destroy]
resource :home, only: [:show]
root 'facolta#index'
get 'corso_new' => 'corso#new'
get 'libro_new' => 'libro#new'
get 'about_us' => 'static_pages#about_us'
get 'faq' => 'static_pages#faq'
resources :facolta do
resources :corso
end
resources :corsos, shallow: true do
resources :libro
end
resources :libros do
resources :annuncio
end
resources :user do
resources :annuncio
end
end
意见/图书馆/新
<h1>FORM DI REGISTRAZIONE HERE</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for([@corso, @libro]) do |libro| %>
<p>
<%= libro.label :titolo %>
<%= libro.text_field :titolo %>
</p>
<p>
<%= libro.label :autori %>
<%= libro.text_field :autori %>
</p>
<p>
<%= libro.label :casa_editrice %>
<%= libro.text_field :casa_editrice %>
</p>
<p>
<%= libro.label :edizione %>
<%= libro.text_field :edizione %>
</p>
<p>
<%= libro.label :anno_pubblicazione %>
<%= libro.text_field :anno_pubblicazione %>
</p>
<p>
<%= libro.label :ISBN %>
<%= libro.text_field :ISBN %>
</p>
<p>
<%= libro.label :immagine %>
<%= libro.text_field :immagine %>
</p>
<%= libro.fields_for :annuncios do |annuncio| %>
<p>
<%= annuncio.label :prezzo %>
<%= annuncio.text_field :prezzo %>
</p>
<p>
<%= annuncio.label :note %>
<%= annuncio.text_field :note %>
</p>
<% end %>
<%= libro.hidden_field :corso_id, value: params[:post_id]%>
<%= libro.submit "Inserisci il libro", class: "btn btn-primary" %>
<% end %>
</div>
</div>
架构.rb
create_table "annuncios", force: :cascade do |t|
t.integer "user_id"
t.integer "libro_id"
t.string "prezzo"
t.text "note"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["libro_id"], name: "index_annuncios_on_libro_id"
t.index ["user_id"], name: "index_annuncios_on_user_id"
end
create_table "corsos", force: :cascade do |t|
t.string "nome"
t.integer "facolta_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["facolta_id"], name: "index_corsos_on_facolta_id"
end
create_table "facolta", force: :cascade do |t|
t.string "nome"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "libros", force: :cascade do |t|
t.string "titolo"
t.string "autori"
t.string "casa_editrice"
t.string "edizione"
t.string "anno_pubblicazione"
t.string "ISBN"
t.string "immagine"
t.integer "corso_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["corso_id"], name: "index_libros_on_corso_id"
end
create_table "users", force: :cascade do |t|
t.string "provider"
t.string "uid"
t.string "name"
t.string "oauth_token"
t.datetime "oauth_expires_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email"
end
编辑:使用@arieljuod 建议编辑
解决方案
您不需要在corso_id
此处合并:@libro = @corso.libros.build(libro_params.merge({corso_id: @corso.id}))
。ActiveRecord 已经设置了 corso_id ,因为你正在这样做@corso.libros.build(...)
。
您也不需要带有 Corso id 的 hidden_field,因为您已经从 URL 中获得了它。
你可能也想做@libro = @corso.libros.build
你的new
行动。
最后,我认为这是主要问题:这是错误belongs_to :corso, inverse_of: :corsos
的,应该是inverse_of: :libros
修复我指出的其他内容以清理您的代码。
编辑:
添加一个选择做这样的事情:
= libro.select :corso_id, options_from_collection_for_select(Corso.all, :id, :name)
推荐阅读
- php - 如何在特征中键入提示“$this”属性
- flutter - 未找到 Flutter 网络图像图像
- android - ItemTouchHelper.Callback.getDefaultUIUtil().onDraw() 改变 z-index
- c# - 如何使用启动表单应用程序打开 API 控制器?
- node.js - 如何在自定义 Jest 节点环境中使用 ES6?
- python - 如何查找用户在服务器 Discord.py 中发送的消息数
- c# - Entity Framework Core 迁移问题与动态连接字符串取决于标头值和另一个数据库
- apache-nifi - 如何将 HDF NiFi 版本升级到最新版本?
- java - 自定义警报对话框背景颜色
- python - 使用列表导航 selenium web 驱动程序