【问题标题】:How can I pass IDs from two different models to a new one?如何将两个不同模型的 ID 传递给一个新模型?
【发布时间】:2020-04-29 21:59:10
【问题描述】:

我目前正在尝试将 User_id 和 Event_id 作为 Guest 的参数传递:

现在在控制台中,我可以使用以下方法创建一个新的来宾对象:

Guest.new(user_id: #, event_id: #)

创建来宾对象后,我可以调用“User.assited_events”来获取该用户正在协助的所有事件,与事件相同,我可以调用“Event.assitances”来凝聚所有协助该事件的用户。

我只想想办法从 events#index 中提交 user_id 和 event_id。

我在事件控制器中使用了一个名为“Assist”的自定义方法

def assist
    @guest = Guest.create(:user_id => User.find(session[:current_user_id]), :event_id => Event.find(params[:id]))

    respond_to do |format|
      if @guest.save
        format.html { redirect_to root_path, notice: 'You are now assiting this event!' }
        format.json { head :no_content}
      else
        format.html { redirect_to root_path, notice: "An error happened you can't assist this event" }
        format.json { render json: @guest.errors, status: :unprocessable_entity }
      end
    end
  end

这是在 events#index 处链接assist_event_path 的当前行

<td><%= link_to 'Assist', assist_event_path(event), method: :put, data: { confirm: 'Do you want to assist to this event?' } %></td>

服务器日志中的结果是两个 id 都通过了,但没有创建 Guest 对象:

Processing by EventsController#assist as HTML
  Parameters: {"authenticity_token"=>"8nddKRZpYcgYDkfJIv/VXK8Os1FmW1oZ+zRIQUnLlE/dhgIA92chq++leqplfaB+bdqIZnCWlB0vPLRfuoHOGw==", "id"=>"1"}
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
  ↳ app/controllers/events_controller.rb:65:in `assist'
  Event Load (0.2ms)  SELECT "events".* FROM "events" WHERE "events"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/events_controller.rb:65:in `assist'

用户模型

class User < ApplicationRecord
  has_many :events
  has_many :guests
  has_many :assisted_events, :through => :guests, :source => :event
end

事件模型

class Event < ApplicationRecord
  belongs_to :user
  has_many :guests
  has_many :assistances, :through => :guests, :source => :user
end

客座模特

class Guest < ApplicationRecord
  belongs_to :user
  belongs_to :event
end

路由文件

Rails.application.routes.draw do
  resources :events do
     member do
        patch :assist
        put :assist
      end
  end
  resources :users

  root 'events#index'
end

编辑----

事件控制器

class EventsController < ApplicationController
  before_action :set_event, only: [:show, :edit, :update, :destroy]

  # GET /Events
  # GET /Events.json
  def index
    @events = Event.all
  end

  # GET /Events/1
  # GET /Events/1.json
  def show
  end

  # GET /Events/new
  def new
    @event = User.find(session[:current_user_id]).events.build
  end

  # GET /Events/1/edit
  def edit
  end

  # POST /Events
  # POST /Events.json
  def create
    @event = User.find(session[:current_user_id]).events.build(event_params)

    respond_to do |format|
      if @event.save
        format.html { redirect_to @event, notice: 'Event was successfully created.' }
        format.json { render :show, status: :created, location: @event }
      else
        format.html { render :new }
        format.json { render json: @event.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /Events/1
  # PATCH/PUT /Events/1.json
  def update
    respond_to do |format|
      if @event.update(event_params)
        format.html { redirect_to @event, notice: 'Event was successfully updated.' }
        format.json { render :show, status: :ok, location: @event }
      else
        format.html { render :edit }
        format.json { render json: @event.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /Events/1
  # DELETE /Events/1.json
  def destroy
    @event.destroy
    respond_to do |format|
      format.html { redirect_to events_url, notice: 'Event was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  def assist
    @guest = Guest.create(:user_id => User.find(session[:current_user_id]), :event_id => Event.find(params[:id]))

    respond_to do |format|
      if @guest.save
        format.html { redirect_to root_path, notice: 'You are now assiting this event!' }
        format.json { head :no_content}
      else
        format.html { redirect_to root_path, notice: "An error happened you can't assist this event" }
        format.json { render json: @guest.errors, status: :unprocessable_entity }
      end
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_event
      @event = Event.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def event_params
      params.require(:event).permit(:title, :body)
    end
end

事件#索引文件

<p id="notice"><%= notice %></p>

<h1>Events</h1>
<% if session[:current_user_id].is_a? Integer %>
  <h3>Current User ID: <%= session[:current_user_id] %></h3>
<% else %>
  <%= link_to 'Create a new user', new_user_path  %>
<% end %>
<table>
  <thead>
    <tr>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @events.each do |event| %>
    <tr>
      <td><%= event.title  %></td>
      <td><%= event.body  %></td>
      </tr>
      <tr>
        <td><%= link_to 'Show', event %></td>
        <td><%= link_to 'Edit', edit_event_path(event) %></td>
        <td><%= link_to 'Assist', assist_event_path(event), method: :put, data: { confirm: 'Do you want to assist to this event?' } %></td>
    </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New event', new_event_path %>

【问题讨论】:

  • Couple cmets - Guest.create() 完全创建了一条记录,我不知道你为什么在它下面有'if @guest.save' - 它已经被保存了,你是双重的那时的数据库。而且我不知道您为什么要做 User.find(session[:current_user_id] 当您想要的只是您已经拥有的 ID!。您不需要在数据库中搜索 ID存储在会话中或通过参数传递。
  • 我只尝试了 cookie session[:current_user_id] 并且它无法识别 ID,所以只有 User.find 允许我从用户那里获取 ID。现在用户只是我直接从浏览器保存的一个 cookie。我使用 .create 来尝试该功能,我复制粘贴代码时忘记将其更改回 .new。
  • 您应该查看current_user_id 的值,因为听起来您并没有按照您期望的方式使用它。如果 User.find(1) 有效但 current_user_id == 1 无效,那听起来你有一个错误。
  • 它有效。正如我所说的只是一个保存当前用户会话的cookie,它只是user_id。

标签: ruby-on-rails ruby ruby-on-rails-6


【解决方案1】:

嗯,这是一种猜测,因为除了 link_to 之外,您没有发布任何表单。我不知道您已将哪些变量传递给events#index,因为您没有为此发布控制器代码。也就是说,您可以使用link_to 传递您想要的任何参数。 编辑好的,所以看起来用户在session[:current_user_id],所以这就是用户ID的来源......

最新修改以简化

在您的其他路线之前添加这条路线,以确保它位于顶部:

put '/assist' => 'events#assist'

然后以你的形式:

<td><%= link_to 'Assist', assist_path(event_id: event, user_id: session[:current_user_id]), method: :put, data: { confirm: 'Do you want to assist to this event?' } %></td>

确保您的参数在您的强参数部分中被允许。

# Only allow a list of trusted parameters through.
def event_params
  params.require(:event).permit(:title, :body, :event_id, :user_id)
end

编辑清理你的控制器代码:

def assist
    @guest = Guest.new(:user_id => session[:current_user_id], :event_id => event_params[:id])

    respond_to do |format|
      if @guest.save
        format.html { redirect_to root_path, notice: 'You are now assiting this event!' }
        format.json { head :no_content}
      else
        format.html { redirect_to root_path, notice: "An error happened you can't assist this event" }
        format.json { render json: @guest.errors, status: :unprocessable_entity }
      end
    end
  end

您传递了实际的 Event 和 User 对象来创建 @guest 对象。您还使用了参数,这意味着您没有通过 event_params 操作。 event_params 操作的目的是允许/拒绝,以便某人无法提交您不想要的参数。

【讨论】:

  • 感谢您的观察,我使用 events#index HTML 文件和事件控制器编辑了帖子。
  • 我收到此错误:没有路由匹配 {:action=>"assist", :controller=>"events", :event_id=>1, :user_id=>1},缺少必需的键:[:id]
  • 那是因为你没有链接到你正在使用的路由。在命令行上执行rake routes 并查找符合您需要的路线。我将编辑我对可能路径的答案。您正在嵌套路径,当您嵌套三个深度时,这可能很方便,但有时会过于复杂。
  • 实际上这看起来是正确的道路。可能只是参数中所需的许可。
  • 我做了更正,但仍然是同样的错误。我验证了路线并且是该方法的正确路线。另外,我尝试只使用 Guest.new(event_params) 并添加 :user_id 和 :event_id 参数,但我又遇到了同样的错误。
猜你喜欢
  • 2021-12-23
  • 2021-02-20
  • 1970-01-01
  • 1970-01-01
  • 2012-08-24
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多