我是Rails新手,正在尝试在他的应用中执行某项操作。 我的问题是:
我有一个Corso模型,一个Libro模型和一个Annuncio模型。 Corso has_many Libro,Libro has_many Annuncio,Annuncio属于Libro,而Libro属于Corso。我想要一个用户可以创建Libro(必须与Corso相关联)的表单,同时必须创建该Libro的Annuncio。我真的吓坏了,我看到了数百个讨论,但没有任何解决我的问题的方法。每次我更改某些内容时,都会遇到一些不同的错误。
我的重点是: -提交表单时如何将corso_id(我的意思是说,Corso对象已经在数据库中定义)传递给新的Libro了; -我看不到为什么创建了一个Libro对象(所有字段均为nil),但没有创建Annuncio对象。看来LibroController / new中的@ libro.annuncios.build代码是没有用的。
希望您能帮助我使此表格生效。
LibroController:
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
AnnuncioController:
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
Libro型号:
class Libro < ApplicationRecord
belongs_to :corso, inverse_of: :libros
has_many :annuncios, inverse_of: :libro
accepts_nested_attributes_for :annuncios
end
Annuncio模型:
class Annuncio < ApplicationRecord
belongs_to :utente, inverse_of: :annuncios
belongs_to :libro, optional: true, inverse_of: :annuncios
end
Corso模型:
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
views / libro / new
<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>
schema.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建议进行编辑
答案 0 :(得分:0)
也许这可以帮助您。
https://stackoverflow.com/a/55476498/10895713
或者您可以那样做。
Corso模型
class Corso < ApplicationRecord
after_create :create_libro
end
Libro模型
class Libro < ApplicationRecord
after_create :create_annuncio
end
来源:https://guides.rubyonrails.org/active_record_callbacks.html
答案 1 :(得分:0)
您无需在此处合并corso_id
:@libro = @corso.libros.build(libro_params.merge({corso_id: @corso.id}))
。自从您执行@corso.libros.build(...)
以来,ActiveRecord已经设置了corso_id。
您也不需要带有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)