从_form或控制器保存的当前用户ID

时间:2015-12-06 21:20:21

标签: ruby-on-rails ruby devise

我正在使用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)>'

2 个答案:

答案 0 :(得分:4)

要添加到bo-oz的答案(应该有效),您还需要查看foreign keys。试图在record_id表单中设置record根本行不通,我认为在解释系统如何使用这一重要技术时会产生误解。

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

enter image description here

每次在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外键

您的记录表具有user_id外键,以便当Rails提取Record对象时,它将能够找到User谁与之相关。

正如bo-oz所述,您可以通过设置@record.user来实现此目的,您也可以 在参数中设置它:

#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对象中设置相应的外键。

答案 1 :(得分:3)

您忘记将用户分配到新记录:

  def create
    @record = Record.new(record_params)
    @record.user = current_user

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