首页 > 解决方案 > Rails 6 form_with 不会通过 Association 传递资源

问题描述

我正在使用 Rails 6。我有一个需要传递的表单,remote: true所以我得到 POST 以作为 JS 处理:

LOG: MessagesController#create as JS

这是我尝试过的:

<%= form_for [@hangout, Message.new] do |f| %>

结果很好地保存到数据库,但处理为 HTML:

LOG: MessagesController#create as HTML

所以我尝试了:

<%= form_for [@hangout, Message.new], remote: true do |f| %>

我了解到这会产生 InvalidAuthenticityToken 错误:

LOG: ActionController::InvalidAuthenticityToken - ActionController::InvalidAuthenticityToken:

试过这个:

<%= form_for [@hangout, Message.new], authenticity_token: true do |f| %>

它作为 HTML 传递,而不是 JS

我为 Rails 6 读到过,最好的方法是使用 form_with,因为它通过了remote:true

<%= form_with(model: [@hangout, Message.new]) do |f| %>

不幸的是,这永远不会到达控制器,所以我没有得到任何回应。我知道自从第一次尝试使用 form_for 以来我的模型和控制器设置正确,所以它必须与我编写 form_with 的方式一致,对吧?

有人有建议吗?

谢谢!

#model
class Message < ApplicationRecord
  belongs_to :hangout
  belongs_to :user
end

#controller
class MessagesController < ApplicationController
  before_action :authenticate_user!
  before_action :set_hangout
  def create
    message = @hangout.messages.new(message_params)
    message.user = current_user
    message.save
    redirect_to @hangout
  end
  private
    def set_hangout
      @hangout = Hangout.find(params[:hangout_id])
    end
    def message_params
      params.require(:message).permit(:body)
    end
end

#routes
require 'sidekiq/web'

Rails.application.routes.draw do
  resources :hangouts do
    resource :hangout_users
    resources :messages
  end

  resources :notes

  authenticate :user, lambda { |u| u.admin? } do
    mount Sidekiq::Web => '/sidekiq'
  end

  devise_for :users, controllers: { registrations: 'users/registrations' }

  get 'mine', to: 'notes#mine'

  root to: 'application#root'

  mount Shrine.presign_endpoint(:cache) => '/images/upload'
end

# application.js
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require('stylesheets/application.scss')
require('jquery')
require("packs/notes")
require("packs/hangouts")
window.Jquery = $;
window.$ = $;

更新

我取得了进展,但并不完全在那里。我使用正确的条目正确地发布到数据库,但没有重定向到 hangouts#show 页面。而是呈现 Create.js.erb:

Form: 
<%= form_for [@hangout, Message.new], 
  remote: true, authenticity_token: true, 
  format: :js  do |f| %>

Controller: 
def create    
  @message =  @hangout.messages.build(message_params)
  @message.user = current_user
  respond_to do |format|
        if @message.save
          format.js
          format.html { redirect_to @hangout, notice: 'Success' }
        else
          format.html { render action: 'new' }
   end
  end
 end
LOG: Processing by MessagesController#create as JS

但是现在 create.js.erb 在 hangouts#show 应该被渲染时被渲染:

views/messages/create.js.erb
 $("#new_message")[0].reset();

Rendered in the browser:
/hangouts/1/messages.js$("#message_body")[0].reset();

任何想法?

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

解决方案


推荐阅读