Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

current user id saved from _form or controller

I'm using Devise to manage users and my goal get the current user to be saved with the created record.

I have tried to save the current user in the controller or in the _form, but either ways it has failed!

Thank you all for your help.

My record Model

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


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

My record Controller

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

My 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

Now with the current user being saved Rspec throws me errors in create and update:

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)>'
like image 316
Jony Avatar asked Jan 07 '23 01:01

Jony


2 Answers

To add to bo-oz's answer (which should work), you also need to look into foreign keys. Trying to set record_id in your record form simply won't work, and I think demonstrates a misunderstanding in your interpretation of how the system works with this important piece of technology.

Specifically, you need to make sure your user_id attribute is populated before you save the new record. This is a relational database specification, not Rails:

enter image description here

Each time you create an association in Rails, it has to have foreign keys set in the database to enable ActiveRecord (the object association builder inside Rails) to combine the appropriate data together:

#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

--

The problem you're having is that you're not setting your user foreign key when you create a record.

Your records table should have a user_id foreign key, so that when Rails pulls out a Record object, it will be able to find the User who's associated to it.

As bo-oz explained, you can achieve this by setting @record.user, you can also set it in the 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

Both these answers would set the appropriate foreign key inside your new Record object.

like image 200
Richard Peck Avatar answered Jan 17 '23 18:01

Richard Peck


You forgot to assign the user to the new record:

  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
like image 38
bo-oz Avatar answered Jan 17 '23 17:01

bo-oz