将表单中的其他参数添加到联接表中-has_many通过

时间:2018-08-20 09:40:43

标签: ruby-on-rails parameters has-many-through jointable

我的问题是我在工作人员和培训之间有一个has_many关联,并且有一个特殊的联接表,其中包含有关每个工作人员已完成的培训的其他信息。

training.rb

class Training < ApplicationRecord
  belongs_to :worker, optional: true
  belongs_to :line, optional: true
  has_many :trainingslines
  has_many :trainingsmemberships
  has_many :workers, through: :trainingsmemberships
  has_many :lines, through: :trainingslines
  accepts_nested_attributes_for :worker
  accepts_nested_attributes_for :line
  accepts_nested_attributes_for :trainingsmemberships
  validates :name, presence: true, length: { minimum: 1 }
  mount_uploader :attachement
end

trainings_controller.rb

class TrainingsController < ApplicationController
  before_action :logged_in_user
  before_action :admin_user
  helper_method :sort_column, :sort_direction

  def index
    @trainings = Training.paginate(page: params[:page])
  end

  def new
    @training = Training.new
  end

  def show
    @training = Training.find(params[:id])
  end

  def insert_line(line)
    self.line.clear
    self.line << line
  end

  def insert_worker(worker)
    self.worker.clear
    self.worker << worker
  end

  def create
    @training = Training.new(training_params)
    if @training.save
      flash[:info] = "Training hinzugefügt."
      redirect_to root_url
    else
      render 'new'
    end
  end

  def destroy
    Training.find(params[:id]).destroy
    flash[:success] = "Training gelöscht"
    redirect_to trainings_url
  end

  def edit
    @training = Training.find(params[:id])
  end

  def update
    @training = Training.find(params[:id])
    if @training.update_attributes(training_params)
      flash[:success] = "Training updated"
      redirect_to training_path
    else
      render 'edit'
    end
  end

  def add_worker_tm
    @workers = Worker.order("#{sort_column} #{sort_direction}")
  end

  def addworkers_tm
    @trainings = Training.all
    @training = params[:training_id]
    @tm = Trainingsmembership.new(tm_params)
    if @tm.save
      flash[:success] = "Mitarbeiter eingefügt"
      redirect_to training_path
    else
      render 'add_worker_tm'
    end
  end


  private
  def sortable_columns
    ["name", "line_ids", "shift_id", "position_id"]
  end

  def sort_column
    Worker.column_names.include?(params[:sort]) ? params[:sort] : "name"
  end

  def sort_direction
    %w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
  end

  def training_params
    params.require(:training).permit(:name, :shortname, :clockcycle, :cc, :jcms, :status, :line_ids => [], :worker_ids => [])
  end

  def tm_params
    params.require(:trainingsmembership).permit(:worker_id, :training_id, :duration, :date, :attachement, :comment)
  end

  # Confirms a logged-in user.
  def logged_in_user
    unless logged_in?
      store_location
      flash[:danger] = "Please log in."
      redirect_to login_url
    end
  end

  # Confirms an admin user.
  def admin_user
    redirect_to(root_url) unless current_user.admin?
  end
end

add_worker_tm.html.erb

<%= simple_form_for(@trainingmem = Trainingsmembership.new, url: add_worker_tm_trainings_path) do |f| %>
      <%= f.input :training_id, collection: Training.all, label_method: :name, value_method: :id, label: 'Training:', include_blank: false %>
      <%= f.input :duration, label: 'Gültigkeit:' %>
      <%= f.input :date, :as => :string, :input_html => { data: {behaviour: "datepicker"}}, label: 'Prüfungstermin:' %>
      <%= f.input :worker_id, collection: Worker.all, label_method: :name, value_method: :id, label: 'Mitarbeiter', include_blank: false, input_html: { multiple: true } %>
      <%= f.input :comment, as: :text, label: 'Bemerkung:' %>
      <%= f.input :attachement, as: :file, label: 'PDF-Protokoll:' %>
      <%= f.submit "Edit training", class: "btn btn-primary" %>
    <% end %>

trainingsmembership.rb

class Trainingsmembership < ApplicationRecord
      belongs_to :worker
      belongs_to :training
    end

我的trainingsmembership表包含以下列:

create_table :trainingsmemberships, id: false do |t|
      t.belongs_to :worker, index: true
      t.belongs_to :training, index: true
      t.integer :duration
      t.timestamp :date
      t.string :attachement
      t.text :comment
      t.timestamps
    end

我想使用带有此simple_form的培训控制器,将带有所有其他参数的工作人员添加到trainingsmembership表中。

我对使用ruby还是很陌生的,使其他一些人可以通过关系工作很多,但是所有这些在联接表中都没有任何其他数据。还是我需要一个新的trainingsmembership控制器?

我已经用Google搜索过,但是没有找到任何有用的建议。

编辑:当前我没有收到任何错误消息,我将被重定向到同一页面。我的调试器提供了以下信息:

Started POST "/trainings/add_worker_tm" for 127.0.0.1 at 2018-08-20 15:32:44 +0200
Processing by TrainingsController#addworkers_tm as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"bZ0MxPcFgUe0EvoVd6VSeUWm4ZT5y0fc8A+eYZmuvvCLh8VoV0e63pxKTKSmvkUuNx1WUMB70Av6uahnt6Av/A==", "trainingsmembership"=>{"training_id"=>"1", "duration"=>"12", "date"=>"21.08.2018", "worker_id"=>["", "1"], "comment"=>""}, "commit"=>"Training bearbeiten"}
  User Load (1.0ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
  ↳ app/helpers/sessions_helper.rb:22
Unpermitted parameter: :worker_id
   (1.0ms)  BEGIN
  ↳ app/controllers/trainings_controller.rb:72
  Training Load (0.0ms)  SELECT  `trainings`.* FROM `trainings` WHERE `trainings`.`id` = 1 LIMIT 1
  ↳ app/controllers/trainings_controller.rb:72
   (0.0ms)  ROLLBACK
  ↳ app/controllers/trainings_controller.rb:72
  Rendering trainings/add_worker_tm.html.erb within layouts/application
  Training Load (1.0ms)  SELECT `trainings`.* FROM `trainings`
  ↳ app/views/trainings/add_worker_tm.html.erb:54
  Worker Load (1.0ms)  SELECT `workers`.* FROM `workers`
  ↳ app/views/trainings/add_worker_tm.html.erb:57
  Rendered trainings/add_worker_tm.html.erb within layouts/application (429.9ms)
  Rendered layouts/_shim.html.erb (0.0ms)
  Rendered layouts/_header.html.erb (2.0ms)
  Rendered layouts/_footer.html.erb (1.0ms)
Completed 200 OK in 654ms (Views: 594.1ms | ActiveRecord: 3.9ms)

1 个答案:

答案 0 :(得分:0)

我以类似您的行为的方式设置了应用程序,发现在tm_params方法中设置强参数时,您需要为worker_id传递数组,但是您将其作为整数值传递。这是因为您允许multiple: true作为工作人员字段。因此,当您尝试保存记录时,只需从参数中删除worked id即可,但是worker_id是必填字段,因此它回滚了事务。因此,您需要从

更改tm_params方法
def tm_params
    params.require(:trainingsmembership).permit(:worker_id, :training_id, :duration, :date, :attachement, :comment)
end

def tm_params
    params.require(:trainingsmembership).permit(:training_id, :duration, :date, :attachement, :comment, worker_id: [])
end

编辑:

要使其倍增,您可以使用另一个参数并像下面这样遍历它:

def addworkers_tm
    @workerall = Worker.all
    @ws = params[:worker_ids].require('worker_ids')
    @trainings = Training.all
    @ws.each do |w|
      @tm = Trainingsmembership.new(tm_params)
      @tm.worker_id = w
      if @tm.save
        flash[:success] = "Mitarbeiter eingefügt"
      else
        @tm.errors
        render 'add_worker_tm'
        return
      end
    end
    redirect_to root_path
end

<% @workerall.each do |worker| %>
          <tr>
            <td><%= check_box_tag "worker_ids[worker_ids][]", worker.id %></td>
            <td><%= worker.name %></td>