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)>'
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:
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With