ActiveRecord::NotNullViolation in ReviewsController#create - ruby-on-rails

Receiving this error in Rails:
PG::NotNullViolation: ERROR: null value in column "reviewer_id" violates not-null constraint DETAIL: Failing row contains (26, 2222, 2222, 8, null, 2021-01-30 19:26:03.354983, 2021-01-30 19:26:03.354983).
This app is trying to allow users to give other users reviews.
I am new, so the error may be quite obvious, but not to the untrained eye. After hours of research, this was my last resort.
I'd appreciate in help fixing this. God bless.
routes.rb
resources :users do
resources :reviews, only: [ :new, :create ]
end
reviews_controller.rb
def create
#review = Review.new(review_params)
#review.user_id = current_user.id
if #review.save
redirect_to user_path(current_user), notice: 'Review added!'
else
render :new
end
end
private
def review_params
params.require(:review).permit(:rating, :content)
end
schema.rb
create_table "reviews", force: :cascade do |t|
t.text "content"
t.integer "rating"
t.bigint "user_id", null: false
t.bigint "reviewer_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["reviewer_id"], name: "index_reviews_on_reviewer_id"
t.index ["user_id"], name: "index_reviews_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "username"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
t.index ["username"], name: "index_users_on_username", unique: true
end
add_foreign_key "offers", "games"
add_foreign_key "offers", "users"
add_foreign_key "rentals", "offers"
add_foreign_key "rentals", "users"
add_foreign_key "reviews", "users"
add_foreign_key "reviews", "users", column: "reviewer_id"
user.rb
has_many :reviews, dependent: :destroy
has_many :given_reviews, source: :reviews, foreign_key: :reviewer_id
has_many :received_reviews, source: :reviews, foreign_key: :user_id
review.rb
belongs_to :user
validates :content, presence: true
validates :rating, presence: true

You have a database constraint on Review, for the reviewer_id field, defined in your schema here:
t.bigint "reviewer_id", null: false
In your controller#create action you are defining a user_id, but I don't see where you are passing in the reviewer_id or setting it. If you have a field in the form, you'll need to add that param to the review_params so it can be passed from the form to the controller action. Or you'll need to define it in the create action similar to how you've defined the user_id.
Since your reviewer is the person leaving the review, and the User is being reviewed, I would do this:
In your view where you are leaving the review, (I assume this would be User#show) you are viewing a specific user. You know which user this is and most likely in that view it is defined as #user, so you can most likely use <%= hidden_field_tag :user_id, #user.id %> in the form for the review. This will pass user_id to the Reviews#create action in the params. You will also need to add user_id to review_params so it can be accessed in the #create action.
Then in your Reviews#create action, assign #review.reviewer_id = current_user.id. #review.user_id will be assigned when you call Review.create(review_params) assuming you have added it the the form and the review_params as suggested above.
Try adding a breakpoint in the create action and look at the params object getting sent from the review form, this may be helpful for you to understand what's happening.
Typical Rails practice is to use a model validation as well. This way you'd get an app error before the request ever hits the database.

Related

Actiontext image upload fails in Rails 7

I am attempting to use the trix/actiontext feature of rails 7 to upload images to be included in my blog. I am planning to store them in AWS-S3 bucket, but the problem also happens when trying to store on local disk. Trix works normally when just doing text content with no errors. When I click the "paperclip" icon to attach a file, I get prompted to select a file, and it appears that I am able to, however, there are errors in the console and when I click submit, the file does not save.
This is the error in the console as soon as I choose an image to attach:
POST http://localhost:3000/rails/active_storage/direct_uploads 422
(Unprocessable Entity) actiontext.js:543
Uncaught Error: Direct upload failed: Error creating Blob for
"Screenshot from 2022-10-13 12-38-57.png". Status: 422
at AttachmentUpload.directUploadDidComplete (actiontext.js:849:13)
at BlobRecord2.callback (actiontext.js:618:13)
at BlobRecord2.requestDidError (actiontext.js:560:12)
at BlobRecord2.requestDidLoad (actiontext.js:556:14)
at XMLHttpRequest. (actiontext.js:527:56)
Here is the error from the rails server:
Started POST "/rails/active_storage/direct_uploads" for ::1 at
2022-11-03 14:20:10 -0500 14:20:10 web.1 | Processing by
ActiveStorage::DirectUploadsController#create as JSON 14:20:10 web.1
| Parameters: {"blob"=>{"filename"=>"Screenshot from 2022-10-26
15-49-39.png", "content_type"=>"image/png", "byte_size"=>336871,
"checksum"=>"TZneH7Z7DdCSftEvona6zg=="},
"direct_upload"=>{"blob"=>{"filename"=>"Screenshot from 2022-10-26
15-49-39.png", "content_type"=>"image/png", "byte_size"=>336871,
"checksum"=>"TZneH7Z7DdCSftEvona6zg=="}}} 14:20:10 web.1
Completed 422 Unprocessable Entity in 33ms (ActiveRecord: 8.4ms |
Allocations: 14851)
ActiveRecord::RecordInvalid (Validation failed: Service name can't be
blank): 14:20:10
There is of course a much longer stack trace, but that appears to be the important part. I'm happy to provide the rest if anyone wants it.
When I click submit on the form, I get my normal toast message saying blog is successfully updated, but the image file is not added to the post. I've been searching for the answer to this problem for 3 days and I'm starting to go around in circles. I know that service_name is a column in the actives_storage_blobs database table, but I don't know where it pulls service name from or how to get it there. I'm thinking it's from the service in storage.yml, and it is present there.
storage.yml:
local:
service: Disk
root: <%= Rails.root.join("storage") %>
I'm running out of things to try and search for this problem. I have disabled turbo for the blogs page as I had found a github discussion relating to that, but it hasn't helped. I have read through the guides for active storage and action text multiple times and have not found anything that helped. I would greatly appreciate any suggestions. Thank you.
In case it helps:
Here is the relevant part of the form at app/views/blogs/_form.html.erb:
<div class="form-group">
<%= form.rich_text_area :body, class: 'form-control', rows: 15, placeholder: 'Content' %>
</div>
app/controllers/blogs_controller.rb:
class BlogsController < CommentsController
before_action :set_blog, only: %i[ show edit update destroy toggle_status ]
before_action :set_sidebar_topics, except: [:update, :create, :destroy, :toggle_status]
layout "blog"
access all: [:show, :index], user: { except: [:destroy, :new, :create, :update, :edit, :toggle_status] }, admin: :all, testing: { except: [:destroy, :create, :update]}
def index
if logged_in?(:admin) || logged_in?(:testing)
#blogs = Blog.recent.with_rich_text_body_and_embeds.page(params[:page]).per(5)
else
#blogs = Blog.published.recent.with_rich_text_body_and_embeds.page(params[:page]).per(5)
end
#page_title = "My Portfolio Blog"
end
def show
if logged_in?(:admin) || logged_in?(:testing) || #blog.published?
#blog = Blog.includes(:comments).friendly.find(params[:id])
#comment = Comment.new
#page_title = #blog.title
#seo_keywords = #blog.body
else redirect_to blogs_path, notice: 'You are not authorized to access this page.'
end
end
def new
#blog = Blog.new
end
def edit
end
def create
#blog = Blog.new(blog_params)
respond_to do |format|
if #blog.save
format.html { redirect_to blog_url(#blog), success: "Blog was successfully created." }
else
flash[:danger] = "Blog must have title, body and topic."
format.html { render :new, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #blog.update(blog_params)
format.html { redirect_to blog_url(#blog), success: "Blog was successfully updated." }
else
format.html { render :edit, status: :unprocessable_entity }
end
end
end
def destroy
#blog.destroy
respond_to do |format|
format.html { redirect_to blogs_url, status: :see_other }
end
end
def toggle_status
if #blog.draft? && logged_in?(:admin)
#blog.published!
elsif #blog.published? && logged_in?(:admin)
#blog.draft!
end
redirect_to blogs_url, success: 'Post status has been updated.'
end
private
def set_blog
#blog = Blog.friendly.find(params[:id])
end
def blog_params
params.require(:blog).permit(:title, :body, :topic_id, :status, images: [])
end
def set_sidebar_topics
#side_bar_topics = Topic.with_blogs
end
end
app/models/blog.rb:
class Blog < ApplicationRecord
enum status: { draft: 0, published: 1 }
extend FriendlyId
friendly_id :title, use: :slugged
validates_presence_of :title, :body, :topic_id
has_rich_text :body
has_many_attached :images, dependent: :destroy
has_many :comments, as: :commentable, dependent: :destroy, counter_cache: :commentable_count
belongs_to :topic, optional: true
def self.special_blogs
all
end
def self.featured_blogs
limit(2)
end
def self.recent
order("updated_at DESC")
end
end
ActiveRecord::Schema[7.0].define(version: 2022_10_14_225319) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "action_text_rich_texts", force: :cascade do |t|
t.string "name", null: false
t.text "body"
t.string "record_type", null: false
t.bigint "record_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true
end
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false
t.datetime "created_at", null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
create_table "active_storage_blobs", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.string "service_name", null: false
t.bigint "byte_size", null: false
t.string "checksum"
t.datetime "created_at", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
create_table "active_storage_variant_records", force: :cascade do |t|
t.bigint "blob_id", null: false
t.string "variation_digest", null: false
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
end
create_table "blogs", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "slug"
t.integer "status", default: 0
t.bigint "topic_id"
t.integer "commentable_count"
t.text "body"
t.index ["slug"], name: "index_blogs_on_slug", unique: true
t.index ["topic_id"], name: "index_blogs_on_topic_id"
end
create_table "comments", force: :cascade do |t|
t.bigint "user_id", null: false
t.string "commentable_type", null: false
t.bigint "commentable_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "body"
t.index ["commentable_type", "commentable_id"], name: "index_comments_on_commentable"
t.index ["user_id"], name: "index_comments_on_user_id"
end
create_table "friendly_id_slugs", force: :cascade do |t|
t.string "slug", null: false
t.integer "sluggable_id", null: false
t.string "sluggable_type", limit: 50
t.string "scope"
t.datetime "created_at"
t.index ["slug", "sluggable_type", "scope"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type_and_scope", unique: true
t.index ["slug", "sluggable_type"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type"
t.index ["sluggable_type", "sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_type_and_sluggable_id"
end
create_table "portfolios", force: :cascade do |t|
t.string "title"
t.string "subtitle"
t.text "body"
t.text "main_image"
t.text "thumb_image"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "position"
end
create_table "skills", force: :cascade do |t|
t.string "title"
t.integer "percent_utilized"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "badge"
end
create_table "technologies", force: :cascade do |t|
t.string "name"
t.bigint "portfolio_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["portfolio_id"], name: "index_technologies_on_portfolio_id"
end
create_table "topics", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "name"
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "roles"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "blogs", "topics"
add_foreign_key "comments", "users"
add_foreign_key "technologies", "portfolios"
end
I am going to stop this question. It appears that rails needed updating. I did rails app:update and there were updates related to actiontext and activestorage and the DB schema was updated for those 3 relevant tables. I have done an upload through action text and it has worked. It's not displaying properly but there is data in my storage folder. I am going to go through everything as it is now to see if I can get the image to display properly and will ask a new question if needed. Thank you very much for helping.
Edit to add: Updating rails did fix the uploads completely. The update changed the image processor from mini-magick to vips. Adding this line to application.rb switched it back and then everything worked properly.
config.active_storage.variant_processor = :mini_magick

Rails: Active Record prevents me from using my model in controller:

I've just start to creating new app from scratch and call a Pocket model from this controller:
class HomeController < ApplicationController
def index
end
def wallets_index
end
def wallets_show
end
def wallets_new
#pocket = Pocket.new
end
end
and this odd error appeared:
transaction is defined by Active Record. Check to make sure that you don't have an attribute or method with the same name.
my schema:
create_table "pockets", force: :cascade do |t|
t.string "address"
t.bigint "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "transaction"
t.index ["user_id"], name: "index_pockets_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "pockets", "users"
And Pocket model:
class Pocket < ApplicationRecord
belongs_to :user
end
This is actually the first time that happened to me and I have no idea which attribute should I rename in order to avoid conflicts?
You are using the transaction column in your Pocket model
t.integer "transaction"
I would suggest against using a column which has a similar name to a rails method. The transaction method is defined in transcations.rb module of Rails
But, if you really want to use it, you can check safe_attributes gem.
In your pockets table or migration, transaction is a reserved word, so you cannot use that word.

When I add has_many, some data is suddently not saved

I have 3 models, Challenge, Pun, User (managed by Clearance gem)
A User can create a Challenge. A Challenge contains many puns. A User can also create a Pun.
Everything is fine until I set a Pun to belong_to a User, then suddenly Puns are no longer saved.
class User < ApplicationRecord
include Clearance::User
has_many :challenges
has_many :puns
end
class Challenge < ApplicationRecord
has_many :puns, :dependent => :delete_all
belongs_to :user
end
class Pun < ApplicationRecord
belongs_to :challenge
belongs_to :user
end
In my PunController I have tried to establish the current_user id
def create
#pun = #challenge.puns.create(pun_params)
#pun.user_id = current_user.id if current_user
redirect_to #challenge
end
private
def set_challenge
#challenge = Challenge.find(params[:challenge_id])
end
def pun_params
params[:pun].permit(:pun_text,:user_id)
end
What am I doing wrong? I'm trying to keep it as simple as possible, but seems like Users don't want to be associated with more than one thing, particularly if nested. Is this a Clearance issue?
DB setup:
create_table "challenges", force: :cascade do |t|
t.text "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "start_time"
t.datetime "end_time"
t.bigint "user_id"
t.index ["user_id"], name: "index_challenges_on_user_id"
end
create_table "puns", force: :cascade do |t|
t.text "pun_text"
t.bigint "challenge_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "user_id"
t.index ["challenge_id"], name: "index_puns_on_challenge_id"
t.index ["user_id"], name: "index_puns_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.string "tagline"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "encrypted_password", limit: 128
t.string "confirmation_token", limit: 128
t.string "remember_token", limit: 128
t.index ["email"], name: "index_users_on_email"
t.index ["remember_token"], name: "index_users_on_remember_token"
end
Well in you currrent code you don't save user_id after setting it. And if you do not expect creation to fail you can do "create!".
So you can try:
def create
#challenge.puns.create!(pun_params.merge(user_id: current_user.id))
redirect_to #challenge
end
You can do this using simply hidden_field like in the form
<%= object.hidden_field :user_id, value: current_user.id %>
it won't work without user session because the relationship does not optional, and remove this line from the controller
#pun.user_id = current_user.id if current_user
and redirect
redirect_to #pun
it will work

ActiveModel::MissingAttributeError (can't write unknown attribute `user_id`)

I have problems with my comments when my app is deployed. Locally everything is working. The logs from heroku says:
ActiveModel::MissingAttributeError (can't write unknown attribute `user_id`):
2018-01-02T15:52:43.461794+00:00 app[web.1]: [79cd7190-e2d9-4dd0-bf71-
709552e5c6e5] app/controllers/comments_controller.rb:15:in `create'
I have no ideas what is occuring the error. Maybe some database thing?
My CommentsController
class CommentsController < ApplicationController
def create
#post =Post.find(params[:post_id])
#comment =#post.comments.create(params[:comment].permit(:name, :body).merge(user: current_user))
redirect_to post_path(#post)
end
def destroy
#post = Post.find(params[:post_id])
#comment= #post.comments.find(params[:id])
if current_user.id == #comment.user_id
#comment.destroy
end
redirect_to post_path(#post)
end
end
My Models
class User < ApplicationRecord
has_many :posts
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
class Post < ApplicationRecord
belongs_to :user, optional: true
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 5}
validates :body, presence: true
end
class Comment < ApplicationRecord
belongs_to :post
belongs_to :user
end
My migration-file
class CreateComments < ActiveRecord::Migration[5.1]
def change
create_table :comments do |t|
t.string :name
t.text :body
t.references :post, index: true
t.timestamps
end
end
end
if you need more code or have any ideas please let me know
EDIT: if i add a user_id column i get a SQLite3::SQLException: duplicate column name: user_id: ALTER TABLE "comments" ADD "user_id" integer error
My schema.rb
`create_table "comments", force: :cascade do |t|
t.string "name"
t.text "body"
t.integer "post_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.index ["post_id"], name: "index_comments_on_post_id"
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.string "theme"
t.integer "user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
You'll need to add a user_id column to your comments table. The belongs_to requires this. You're also going to need a post_id column, and user_id for your posts table to.
You can customise the column name, but the convention is to use the format parent_table_id.
Here's the key quote, from the docs:
Associations are implemented using macro-style calls, so that you can
declaratively add features to your models. For example, by declaring
that one model belongs_to another, you instruct Rails to maintain
Primary Key-Foreign Key information between instances of the two
models, and you also get a number of utility methods added to your
model.
This means, for example, if your first user has an id of 1, all of their comments and posts will have a user_id value of 1, which does the actual tying together of the records.
Here's an example migration with the relevant line included:
def change
create_table :comments do |t|
...
t.belongs_to :user, index: true
...
end
end
Does that make sense? Let me know if you've any questions and I can update as needed :)
You need to add user_id
Create the migration with
rails g migration AddUserIdToComment user:references
Then do
rake db:migrate
And you should be fine.
Your migration have missing
t.references :user, index: true
So you need to add user_id column within comments table
Update : It seems like you have some migration problem. I suggest you to check for rake db:migrate:status comment and look for any down migration. Once all are up then just run rake db:migrate:down VERSION='VERSION_NUMBER_HERE' and add your user t.references :user, index: true to the same migration and migrate.
PS: Change existing migration if and only if you have not pushed it.

Ruby on Rails SQLite3::ConstraintException: NOT NULL constraint failed:

I am developing a simple app where a user can add a subject to a cart. Before I add the authentication I was able to add a subject to the cart but as I want a user to be able to has access to just his/her cart I used Devise to create User with authentication. Now, when I click on the button to add a subject to the cart I have the following error:
This is a snapshot of the error I get: 1
SQLite3::ConstraintException: NOT NULL constraint failed: carts.user_id: INSERT INTO "carts" ("created_at", "updated_at") VALUES (?, ?)
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
private
def current_cart
Cart.find(params[:user_id])
rescue ActiveRecord::RecordNotFound
cart = Cart.create
params[:user_id] = cart.id
cart
end
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_one :cart
end
class Cart < ActiveRecord::Base
belongs_to :user
has_many :line_items, dependent: :destroy
scope :user_carts, ->(user) { where(['user_id= ?', user.id]) }
end
class AddUsersToCarts < ActiveRecord::Migration
def up
add_reference :carts, :user, index: true
Cart.reset_column_information
user = User.first
Cart.all.each do |cart|
cart.user_id = user.id
cart.save!
end
change_column_null :carts, :user_id, false
add_foreign_key :carts, :users
end
def down
remove_foreign_key :carts, :users
remove_reference :carts, :user, index: true
end
end
Edit: I added the schema.rb below:
ActiveRecord::Schema.define(version: 20151210213408) do
create_table "carts", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id", null: false
end
add_index "carts", ["user_id"], name: "index_carts_on_user_id"
create_table "line_items", force: :cascade do |t|
t.integer "subject_id"
t.integer "cart_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "subjects", force: :cascade do |t|
t.string "title", null: false
t.string "code", null: false
t.text "description", null: false
t.integer "credits", null: false
t.string "lecturer", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "subjects", ["title"], name: "index_subjects_on_title", unique: true
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
You current_cart method does not make much sense.
You cannot find the user's cart by calling Cart.find(params[:user_id]), because that looks for a cart by an id (not by an user_id).
Cart.create fails, because you do not provide an user_id that is required (your database migrations says that the filed cannot be null).
Furthermore, params[:user_id] = cart.id changes the params hash, but not the new cart.
Change that method to something like this (using find_or_create_by) and use the current_user.id instead of params[:user_id]:
def current_cart
Cart.find_or_create_by(user_id: current_user.id)
end

Resources