为预订应用设置Controller

时间:2016-08-17 15:45:56

标签: ruby-on-rails model-view-controller

我正在通过克隆和调整现有项目来学习并使用Ruby on Rails构建我的第一个应用程序。我在编写控制器时陷入困境,并希望有人有一个提示帮助我。

上下文 我正在建立一个培训平台:用户可以设计培训,这些培训可以在几个日期进行(我称之为培训课程和#39;),(其他)用户可以通过预订订阅这些惊险刺激。

Conceptualization of models

并发症 我现在正在运行用户,培训和预订模型,但我想在两者之间添加刺激模型(我知道这不是最简单的方法,但我遵循了不包括刺激模型的培训)。我设置了模型和一个简单的视图,教练应该能够为现有的训练添加刺激(在训练/编辑中)。不幸的是,经过一天的尝试,我还没有成功,我一直得到:

  

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模型中保存新刺激的提示。

如果需要更多信息,请不要犹豫问我。

提前致谢!

1 个答案:

答案 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 %>