当前位置 : 主页 > 编程语言 > ruby >

ruby-on-rails – 从_form或controller保存的当前用户ID

来源:互联网 收集:自由互联 发布时间:2021-06-23
我正在使用Devise来管理用户,我的目标是使用创建的记录保存当前用户. 我试图将当前用户保存在控制器或_form中,但无论哪种方式都失败了! 感谢大家的帮助. 我的记录模型 class Record A
我正在使用Devise来管理用户,我的目标是使用创建的记录保存当前用户.

我试图将当前用户保存在控制器或_form中,但无论哪种方式都失败了!

感谢大家的帮助.

我的记录模型

class Record < ActiveRecord::Base
  #Associations
  belongs_to :user


  # Validations
  validates :title, :user, presence: true
end

我的记录控制器

class RecordsController < ApplicationController
  before_action :find_record, only: [:show, :edit, :update, :destroy]

  def create
    @record = Record.new(record_params)

    if @record.save
      redirect_to @record
    else
      @records = Record.all
      render 'index'
    end
  end

  def update
    if @record.update(record_params)
      flash[:notice] = "The record was updated successfully"
      redirect_to @record
    else
      render 'edit'
    end
  end

  private

    def find_record
      @record = Record.find(params[:id])
    end

    def record_params
      params.require(:record).permit(:title, :description, :user_id).merge(user: current_user) # as suggested 
    end
end

我的Rspec

require 'rails_helper'

describe RecordsController do
  let(:record) { create(:record) }
  let(:user) { create(:user) }
  let(:title) { "Some title I would like to put in my record" }
  let(:description) { "description I would like to put in my record" }


  describe "#create" do
    it "creates a new record with the given title and description" do
      expect do
        post :create, record: { title: title, description: description, user_id: user }
      end.to change { Record.count }.by(1)

      expect(response).to redirect_to(assigns[:record])

      expect(assigns[:record].title).to eq(title)
      expect(assigns[:record].description).to eq(description)
    end

    it "fails to create a record and returns to the index page" do
      expect(post :create, record: { description: description }).to render_template(:index)
      expect(assigns[:records]).to eq(Record.all)
    end
  end

  describe "#update" do
    it "find the records and sets the new given values" do
      put :update, { id: record.id, record: { title: title, description: description } }

      record.reload
      expect(record.title).to eq(title)
      expect(record.description).to eq(description)

      expect(flash[:notice]).to eq("The record was updated successfully")
    end

    it "fails to create a record and returns to the edit page" do
      expect(put :update, { id: record.id, record: { title: "" } }).to render_template(:edit)
    end
  end
end

现在,当前用户被保存,Rspec会在创建和更新时抛出错误:

1) RecordsController#create creates a new record with the given title and description
     Failure/Error: post :create, record: { title: title, description: description, user_id: user }
     NoMethodError:
       undefined method `authenticate' for nil:NilClass
     # ./app/controllers/records_controller.rb:42:in `record_params'
     # ./app/controllers/records_controller.rb:9:in `create'
     # ./spec/controllers/records_controller_spec.rb:36:in `block (4 levels) in <top (required)>'
     # ./spec/controllers/records_controller_spec.rb:35:in `block (3 levels) in <top (required)>'
     # -e:1:in `<main>'

  2) RecordsController#create fails to create a record and returns to the index page
     Failure/Error: expect(post :create, record: { description: description }).to render_template(:index)
     NoMethodError:
       undefined method `authenticate' for nil:NilClass
     # ./app/controllers/records_controller.rb:42:in `record_params'
     # ./app/controllers/records_controller.rb:9:in `create'
     # ./spec/controllers/records_controller_spec.rb:46:in `block (3 levels) in <top (required)>'
     # -e:1:in `<main>'

  3) RecordsController#update find the records and sets the new given values
     Failure/Error: put :update, { id: record.id, record: { title: title, description: description } }
     NoMethodError:
       undefined method `authenticate' for nil:NilClass
     # ./app/controllers/records_controller.rb:42:in `record_params'
     # ./app/controllers/records_controller.rb:20:in `update'
     # ./spec/controllers/records_controller_spec.rb:62:in `block (3 levels) in <top (required)>'
     # -e:1:in `<main>'

  4) RecordsController#update fails to create a record and returns to the edit page
     Failure/Error: expect(put :update, { id: record.id, record: { title: "" } }).to render_template(:edit)
     NoMethodError:
       undefined method `authenticate' for nil:NilClass
     # ./app/controllers/records_controller.rb:42:in `record_params'
     # ./app/controllers/records_controller.rb:20:in `update'
     # ./spec/controllers/records_controller_spec.rb:72:in `block (3 levels) in <top (required)>'
要添加bo-oz的答案(应该可以使用),你还需要查看 foreign keys.尝试在记录表单中设置record_id根本不起作用,我认为在你对系统如何工作的解释中表现出误解这项重要的技术.

具体而言,您需要确保在保存新记录之前填充了user_id属性.这是一个关系数据库规范,而不是Rails:

每次在Rails中创建关联时,都必须在数据库中设置外键以启用ActiveRecord(Rails中的对象关联构建器)将适当的数据组合在一起:

#app/models/user.rb
class User < ActiveRecord::Base
   has_many :records
end

#app/models/record.rb
class Record < ActiveRecord:Base
   #see diagram above -- this has to have user_id in the schema :)
   belongs_to :user
end

您遇到的问题是您在创建记录时没有设置用户外键.

您的记录表应该有一个user_id外键,这样当Rails拉出一个Record对象时,它就能找到与之关联的用户.

正如bo-oz解释的那样,你可以通过设置@ record.user来实现这一点,你也可以在params中设置它:

#app/controllers/records_controller.rb
class RecordsController < ApplicationController
   def create
      @record = Record.new record_params
      @record.save ..........
   end

   private

   def record_params
      params.require(:record).permit(......).merge(user: current_user)
   end
end

这两个答案都会在新的Record对象中设置适当的外键.

网友评论