视图中的按钮,用于调用控制器操作以更新数据库列

Button from view to call a controller action to update database column

本文关键字:操作 更新 数据库 控制器 调用 按钮 用于 视图      更新时间:2023-09-26

当单击按钮时,我正在尝试将用户添加到表列(PostgreSQL)中的数组中。按钮单击将注册,但不会调用控制器方法,也不会给出任何错误。

我有以下带有按钮的视图。

views/users/index.html.erb

<%= form_for(Pairing.new, url: users_path, method: :patch, html: { id: 'my_special_form' }) do |f| %>
  <div class="field">
    <%= f.label :supervisor_id %>
    <%= f.collection_select(:supervisor_id, User.where(role: 1), :id, :name) %>
  </div>
  <div class="field">
    <%= f.label :student_id %>
    <%= f.collection_select(:student_id, User.where(role: 0), :id, :name) %>
  </div>
  <%= f.submit %>
<% end %>

以及另一个文件中的 javascript。

assets/javascripts/pair.js

$("#my_special_form").submit(function(){
  var url = this.action + "/" + this.elements["pairing[student_id]"].value;
  $.ajax(url, {
    beforeSend: $.rails.CSRFProtection,
    data: {
      user: {
        supervisor_id: this.elements["pairing[supervisor_id]"].value
      }
    }
    type: 'PATCH',
    dataType: 'JSON',
    success: function(data, textStatus, jqXHR) {
      console.log('Success', data, textStatus, jqXHR);
    }
  });
  return false; // cancels out the normal form submission
});

我正在尝试在控制器中调用此方法

控制器/users_controller

class UsersController < ApplicationController
  before_action :authenticate_user!
  after_action :verify_authorized
  def index
    @users = User.all
    authorize User
  end
  def show
    @user = User.find(params[:id])
    authorize @user
  end
  def update
    @user = User.find(params[:id])
    authorize @user
    if @user.update_attributes(secure_params)
      redirect_to users_path, :notice => "User updated."
    else
      redirect_to users_path, :alert => "Unable to update user."
    end
  end
  def destroy
    user = User.find(params[:id])
    authorize user
    user.destroy
    redirect_to users_path, :notice => "User deleted."
  end
  def pair
    supervisor = User.find(params[:id1])
    student = User.find(params[:id2])
    studentlist = supervisor.select(:supervised_students)
    studentlist << student.
    supervisor.update_attribute(:supervised_students => studentlist)
    @supervisor.save
  end
  private
  def secure_params
    params.require(:user).permit(:role)
  end
end

add_supervisor迁移

class AddSupervisor < ActiveRecord::Migration
  def change
    add_column :users, :supervisor_id, :integer
  end
end

用户模型

enum role: [:student, :supervisor, :admin]
  after_initialize :set_default_role, :if => :new_record?
  has_many :students, class_name: "Users",
                      foreign_key: "supervisor_id"
  belongs_to :supervisor, class_name: "User"
  def set_default_role
    self.role ||= :student
  end

路线.rb

Rails.application.routes.draw do
  devise_for :users
  resources  :users
  resources  :pairings
  resources  :conversations, only: [:index, :show, :destroy] do
    member do
      post :reply
    end
  end
  resources :conversations, only: [:index, :show, :destroy] do
    member do
      post :restore
    end
  end
  resources :conversations, only: [:index, :show, :destroy] do
    collection do
      delete :empty_trash
    end
  end
  resources :conversations, only: [:index, :show, :destroy] do
    member do
      post :mark_as_read
    end
  end
  resources  :messages, only: [:new, :create]
  devise_scope :user do
    authenticated :user do
      root 'pages#index', as: :authenticated_root
    end
    unauthenticated do
      root 'pages#welcome', as: :unauthenticated_root
    end
  end

  root to: 'pages#index'
end

URI中的#用于片段标识符 - 根据规范,它对服务器是透明的。

因此,当您发送 ajax 请求时,它实际上被解释为 POST /users .

root用于设置/路径的处理程序。如果你想添加POST users/pair你会做的

resources :users do
   collection do
     post 'pair', to: "users#pair"
   end
end  

请注意,路由中的#意味着controller#action,与结果无关

然而,这就是我解决问题的方式。

设置关系

确保您在users上有supervisor_id列。

class User < ActiveRecord::Base
  has_many :students, class_name: "Users",
                      foreign_key: "supervisor_id"
  belongs_to :supervisor, class_name: "User"
end
  • http://guides.rubyonrails.org/association_basics.html#self-joins

设置路线

在这种情况下,您可能需要考虑是否真的需要特殊路线。特别是因为你正在使用ajax。

事实上,如果你想指派一个学生来监督,你真正需要的只是一个补丁请求。

PATCH /users/5 { supervisor_id: 6 }

表格

如果您只是简单地列出学生,您可以使用这样的简单表格,您将很高兴:

<%= form_for(user) do |f| %>
  <%= f.collection_select :supervisor, User.where(role: 1) %> 
  <%= f.submit %>
<% end %>

但是,如果要有两个选择,则需要动态设置 ajax 请求 URL。我们将使用一个小技巧来正确使用表单助手:

# app/models/pairing
class Pairing
  include ActiveModel::Model
  attr_accessor :supervisor_id, :student_id
end
  • http://api.rubyonrails.org/classes/ActiveModel/Model.html
  • http://railscasts.com/episodes/193-tableless-model

这是一个不受数据库表支持的模型。我们可以简单地使用它来绑定表单输入:

<%= form_for(Pairing.new, url: users_path, method: :patch, html: { id: 'my_special_form' }) do |f| %>
  <div class="field">
    <%= f.label :supervisor_id %>
    <%= f.collection_select(:supervisor_id, User.where(role: 1), :id, :name) %>
  </div>
  <div class="field">
    <%= f.label :supervisor_id %>
    <%= f.collection_select(:student_id, User.where(role: 0), :id, :name) %>
  </div>
  <%= f.submit %>
<% end %>

这种形式不会正常工作,因为它会修补到/users。我们要做的是在提交表单时将 url 更改为指向 currect 用户。

$("#my_special_form").submit(function(){
  var url = this.action + "/" + this.elements["pairing[student_id]"].value;
  $.ajax(url, {
    beforeSend: $.rails.CSRFProtection,
    data: {
      user: {
        supervisor_id: this.elements["pairing[supervisor_id]"].value
      }
    },
    type: 'PATCH',
    dataType: 'JSON',
    success: function(data, textStatus, jqXHR) {
      console.log('Success', data, textStatus, jqXHR);
    }
  });
  return false; // cancels out the normal form submission
});