我正在通过克隆和调整现有项目来学习并使用Ruby on Rails构建我的第一个应用程序。我在编写控制器时陷入困境,并希望有人有一个提示帮助我。
上下文 我正在建立一个培训平台:用户可以设计培训,这些培训可以在几个日期进行(我称之为培训课程和#39;),(其他)用户可以通过预订订阅这些惊险刺激。
并发症 我现在正在运行用户,培训和预订模型,但我想在两者之间添加刺激模型(我知道这不是最简单的方法,但我遵循了不包括刺激模型的培训)。我设置了模型和一个简单的视图,教练应该能够为现有的训练添加刺激(在训练/编辑中)。不幸的是,经过一天的尝试,我还没有成功,我一直得到:
ThrillsController中的NoMethodError #create
NoMethodError(未定义的方法`刺激'对于nil:NilClass):(第16行)
我的用于def编辑的TrainingsController看起来像
def edit
if current_user.id == @training.user.id
@photos = @training.photos
@thrill = @training.thrills.create(thrill_params)
@thrills = @training.thrills
else
redirect_to root_path, notice: "Je hebt hier helaas geen toegang tot"
end
end
def update
if @training.update(training_params)
if params[:images]
params[:images].each do |image|
@training.photos.create(image: image)
end
end
@thrill = @training.thrills.create(thrill_params)
@thrills = @training.thrills
@photos = @training.photos
redirect_to edit_training_path(@training), notice: "Updated..."
else
render:edit
end
end
我的ThrillsController看起来像
class ThrillsController < ApplicationController
def create
@thrill = @training.thrills.create(thrill_params)
redirect_to @thrill.training, notice: "Je thrill is aangemaakt!"
end
private
def thrill_params
params.require(:thrill).permit(:trilldate, :thrillhr, :thrillmin, :training_id)
end
end
我的表单可以在views / trainings / edit.html.erb中呈现的views / thrills / _form.html.erb中添加刺激
<%= form_for([@training.thrills.new]) do |f| %>
<div class="form-group">
<%= f.text_field :thrillhr, placeholder: "Uur", class: "form-control" %>
</div>
<%= f.hidden_field :training_id, value: @training.id %>
<div class="actions">
<%= f.submit "Create", class: "btn btn-primary" %>
</div>
<% end %>
可在此处找到该应用的完整代码https://github.com/chrisrutte/musc
问题 我明显在这里做了一些简单的错误,所以我希望有人可以提供我如何在我的Thrills模型中保存新刺激的提示。
如果需要更多信息,请不要犹豫问我。
提前致谢!
答案 0 :(得分:0)
首先让我们看看这种设置的模型是什么样的:
class Training < ActiveRecord::Base
has_many :thrills
has_many :users, through: :thrills
end
class Thrills < ActiveRecord::Base
belongs_to :training
has_many :reservations
has_many :users, through: :reservations
end
class Reservation < ActiveRecord::Base
belongs_to :user
belongs_to :thrill
has_one :training, though: :thrill
end
class User < ActiveRecord::Base
has_many :reservations
has_many :thrills, through: :reservations
has_many :trainings, through: :thrills
end
请务必阅读Rails guide on associations,因为这非常复杂。
请注意,Reservation用作连接模型。
预订也与培训有间接关系。这是为了避免在多个级别上具有重复的外键。这同样适用于User模型。主要原因是ActiveRecord只会在一次写入外键!
设置路线时,您很可能需要to use nesting:
resources :trainings, shallow: true do
resources :thrills
end
然后我们可以设置控制器。
class ThrillsController < ApplicationController
before_action :set_training!, only: [:new, :create, :index]
before_action :set_thrill!, only: [:show, :edit, :update, :destroy]
# GET /trainings/:training_id/thrills/new
def new
@thrill = @training.thrills.new
end
# POST /trainings/:training_id/thrills
def create
@thrill = @training.thrills.new(thrill_params)
if @thrill.save
redirect_to @thrill
else
render :new
end
end
# GET /trainings/:training_id/thrills
def index
@thrills = @training.thrills
end
# this is not nested.
# GET /thrills/:id
def show
end
# this is not nested.
# GET /thrills/:id/edit
def edit
end
# this is not nested.
# PUT|PATCH /thrills/:id
def update
if @thrill.update(thrill_params)
redirect_to @thrill
else
render :edit
end
end
# ...
private
def set_training!
@training = Training.find(params[:training_id])
end
def set_thrill!
@thill = Thrill.joins(:training).find(params[:id])
@training = @thill.training
end
def thrill_params
params.require(:thrill)
.permit(:trilldate, :thrillhr, :thrillmin, :training_id)
end
end
然后设置表单:
<%= form_for( [@training, @thrill] ) do |f| %>
<div class="form-group">
<%= f.text_field :thrillhr, placeholder: "Uur", class: "form-control" %>
</div>
<div class="actions">
<%= f.submit "Create", class: "btn btn-primary" %>
</div>
<% end %>
由于我们希望通过training_id
形式通过action
而不是表单正文,我们使用form_for( [@training, @thrill] )
,例如,它会为我们提供路径/trainings/6/thrills
。
但是对于我们的编辑表单,我们需要/thrills/1
。所以我们来解决这个问题:
<%= form_for( @thrill.new_record? ? [@training, @thrill] : @thrill ) do |f| %>
# ...
<% end %>