Why does Rails rollback even though the model exists? - ruby-on-rails

I am trying to find out why my update method is not working in my Rails API. It should update the bio field. I have my API hosted on Heroku and am using the Heroku logs to debug in production. I used the exists? method to make sure the user is in the db and yet when the update method is called it rollsback after doing this check. I don't understand what is the cause of this?
Here are the Heroku logs of the output
2022-04-15T02:54:34.083586+00:00 app[web.1]: I, [2022-04-15T02:54:34.083515 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Started PATCH "/users/8" for 98.248.0.125 at 2022-04-15 02:54:34 +0000
2022-04-15T02:54:34.084345+00:00 app[web.1]: I, [2022-04-15T02:54:34.084290 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Processing by UsersController#update as HTML
2022-04-15T02:54:34.084376+00:00 app[web.1]: I, [2022-04-15T02:54:34.084350 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Parameters: {"bio"=>"test", "id"=>"8", "user"=>{"bio"=>"test"}}
2022-04-15T02:54:34.087450+00:00 app[web.1]: D, [2022-04-15T02:54:34.087403 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] User Load (1.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 8], ["LIMIT", 1]]
2022-04-15T02:54:34.089711+00:00 app[web.1]: D, [2022-04-15T02:54:34.089664 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] User Exists? (1.2ms) SELECT 1 AS one FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 8], ["LIMIT", 1]]
2022-04-15T02:54:34.092004+00:00 app[web.1]: D, [2022-04-15T02:54:34.091963 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] TRANSACTION (0.9ms) BEGIN
2022-04-15T02:54:34.093523+00:00 app[web.1]: D, [2022-04-15T02:54:34.093465 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] User Exists? (1.4ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = $1 AND "users"."id" != $2 LIMIT $3 [["username", "newperson"], ["id", 8], ["LIMIT", 1]]
2022-04-15T02:54:34.095530+00:00 app[web.1]: D, [2022-04-15T02:54:34.095493 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] TRANSACTION (0.9ms) ROLLBACK
2022-04-15T02:54:34.096881+00:00 app[web.1]: I, [2022-04-15T02:54:34.096842 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] [active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (0.07ms)
2022-04-15T02:54:34.097078+00:00 app[web.1]: I, [2022-04-15T02:54:34.097050 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Completed 422 Unprocessable Entity in 13ms (Views: 0.6ms | ActiveRecord: 5.5ms | Allocations: 2816)
2022-04-15T02:54:34.101664+00:00 heroku[router]: at=info method=PATCH path="/users/8" host=anime-axis-api.herokuapp.com request_id=9e5ea776-5b15-420f-8cdc-0601480e0e3d fwd="98.248.0.125" dyno=web.1 connect=0ms service=17ms status=422 bytes=1096 protocol=https
Here is my update method:
def update
if User.exists?(8)
#current_user.update!(user_params)
render json: #current_user, status: :ok
end
end
private
def user_params
# added require
params.require(:user).permit(:username, :password, :password_confirmation, :bio, :avatar, :email)
end
My User model:
class User < ApplicationRecord
has_secure_password
has_many :anime_lists
has_many :animes, through: :anime_lists
has_many :manga_lists
has_many :mangas, through: :manga_lists
validates :username, presence: true, confirmation: {case_sensitive: false}, uniqueness: true, length: {in: 6..30}
validates :password, presence: true, confirmation: true
end

I think your validations are the issue. Password presence is validating on every update. Since User#password is nil and you don't have a password in your params, it fails.
class User < ApplicationRecord
has_secure_password
validates :password, presence: true, confirmation: true
end
>> User.create(email: 'test#user.com', password: '123456');
>> User.first.update!(email: 'test#user.com')
User Load (0.8ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
ActiveRecord::RecordInvalid: Validation failed: Password can't be blank
has_secure_password also adds its own validations.
https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password
If you want to customize password validations use
has_secure_password validations: false
# + your password validations
To get some ideas, you can take a look at how devise does validations:
https://github.com/heartcombo/devise/blob/v4.8.1/lib/devise/models/validatable.rb#L60

I can not be totally sure without knowing the data in your database but I would say you have two users with username=newperson.
When you try to save any change on any of those the validation triggers and the changes are not commited to the dabase.

Related

Why is rails returning a 401 Unauthorized status and why does it say that the user exists?

I'm in the process of writing a single page app with rails, react, and redux; and this is what the full error message looks like:
Started POST "/api/users" for ::1 at 2020-01-27 21:48:27 -0800
Processing by Api::UsersController#create as JSON
Parameters: {"user"=>{"username"=>"racookin", "password"=>"[FILTERED]", "nickname"=>"racookin", "gender"=>"female", "birthday"=>"1990-07-07"}}
(0.2ms) BEGIN
↳ app/controllers/api/users_controller.rb:6
User Exists (0.4ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = $1 LIMIT $2 [["username", "racookin"], ["LIMIT", 1]]
↳ app/controllers/api/users_controller.rb:6
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."email" IS NULL LIMIT $1 [["LIMIT", 1]]
↳ app/controllers/api/users_controller.rb:6
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."session_token" = $1 LIMIT $2 [["session_token", "9B3Uo1FGMnJDeASGGucj_Q"], ["LIMIT", 1]]
↳ app/controllers/api/users_controller.rb:6
(0.2ms) ROLLBACK
↳ app/controllers/api/users_controller.rb:6
Completed 401 Unauthorized in 274ms (Views: 0.2ms | ActiveRecord: 10.6ms)
I'm trying to understand what this is saying so that I can figure out where to even start looking for the bug; it seems that it returns the 401 Unauthorized error, and it's saying that the user exists (even when I try signing up with a new user). What exactly is happening here? Also, is it hitting the database 3 times?
Update: I think I understand that it's failing because the user isn't being saved, which means it's probably failing one of the validations.
Here's what I have on my User model:
class User < ApplicationRecord
attr_reader :password
validates :username, :email, :nickname, :gender, :birthday, :password_digest, :session_token, presence: true
validates :username, :email, :session_token, uniqueness: true
validates :password, length: {minimum: 6}, allow_nil: true
after_initialize :ensure_session_token
...
And here's a more detailed look at my schema for the users table:
# Table name: users
#
# id :bigint not null, primary key
# username :string not null
# email :string not null
# nickname :string not null
# gender :string not null
# birthday :date not null
# password_digest :string not null
# session_token :string not null
# created_at :datetime not null
# updated_at :datetime not null
Could one of these validations be failing? I assumed that because the values for these columns are being set in the form, my user would pass the validations; but am I wrong?
UPDATE: I've fixed the email parameter issue, but I still seem to be getting the 401 status error:
Started POST "/api/users" for ::1 at 2020-01-28 08:54:20 -0800
Processing by Api::UsersController#create as JSON
Parameters: {"user"=>{"username"=>"", "password"=>"[FILTERED]", "nickname"=>"pooh", "gender"=>"male", "birthday"=>"2002-02-02", "email"=>"pooh10"}}
(0.2ms) BEGIN
↳ app/controllers/api/users_controller.rb:6
User Exists (1.3ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = $1 LIMIT $2 [["username", ""], ["LIMIT", 1]]
↳ app/controllers/api/users_controller.rb:6
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 LIMIT $2 [["email", "pooh10"], ["LIMIT", 1]]
↳ app/controllers/api/users_controller.rb:6
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."session_token" = $1 LIMIT $2 [["session_token", "232kGIICEzCUSSesxgeYfg"], ["LIMIT", 1]]
↳ app/controllers/api/users_controller.rb:6
(0.2ms) ROLLBACK
↳ app/controllers/api/users_controller.rb:6
Completed 401 Unauthorized in 284ms (Views: 0.3ms | ActiveRecord: 12.3ms)
As per your request params for api/users.
Parameters: {"user"=>{"username"=>"racookin", "password"=>"[FILTERED]", "nickname"=>"racookin", "gender"=>"female", "birthday"=>"1990-07-07"}}
You are not passing email in your params. And according to your models, you added uniqueness validation for email.
validates :username, :email, :session_token, uniqueness: true
Now when active record trying to validate your record with existing records, it found a record with null email so it returned validation failed message to you.
If you want to save record with null values you need to add :allow_nil => true in your models for the email field.
Edit
to set username random in your users model.
class User < ApplicationRecord
.....
.....
.....
before_save :assign_username
def assign_username
return unless self.username.blank?
self.username = SecureRandom.alphanumeric(8)
end

Error on heroku but on local with Ruby on Rails

I am creating a Blog app. This is working well on local, but on Hroku, when I tried to post comments, We're sorry, but something went wrong. appeared.
On local, I can posts comments on each article.
I use sqLite3 for local, and postgre for heroku.
Error log
2019-03-25T07:15:44.567261+00:00 app[web.1]: D, [2019-03-25T07:15:44.567194 #4] DEBUG -- : [ff69042f-aa16-4d59-8905-8b5beacee242] [1m[36mUser Load (0.8ms)[0m [1m[34mSELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2[0m [["id", 1], ["LIMIT", 1]]
2019-03-25T07:15:44.569317+00:00 app[web.1]: D, [2019-03-25T07:15:44.569236 #4] DEBUG -- : [ff69042f-aa16-4d59-8905-8b5beacee242] [1m[36mArticle Load (1.2ms)[0m [1m[34mSELECT "articles".* FROM "articles" WHERE (2) LIMIT $1[0m [["LIMIT", 1]]
2019-03-25T07:15:44.569537+00:00 app[web.1]: I, [2019-03-25T07:15:44.569468 #4] INFO -- : [ff69042f-aa16-4d59-8905-8b5beacee242] Completed 500 Internal Server Error in 5ms (ActiveRecord: 2.0ms)
2019-03-25T07:15:44.570193+00:00 app[web.1]: F, [2019-03-25T07:15:44.570137 #4] FATAL -- : [ff69042f-aa16-4d59-8905-8b5beacee242]
2019-03-25T07:15:44.570287+00:00 app[web.1]: F, [2019-03-25T07:15:44.570226 #4] FATAL -- : [ff69042f-aa16-4d59-8905-8b5beacee242] ActiveRecord::StatementInvalid (PG::DatatypeMismatch: ERROR: argument of WHERE must be type boolean, not type integer
2019-03-25T07:15:44.570292+00:00 app[web.1]: LINE 1: SELECT "articles".* FROM "articles" WHERE (2) LIMIT $1
2019-03-25T07:15:44.570294+00:00 app[web.1]: ^
2019-03-25T07:15:44.570296+00:00 app[web.1]: : SELECT "articles".* FROM "articles" WHERE (2) LIMIT $1):
2019-03-25T07:15:44.570339+00:00 app[web.1]: F, [2019-03-25T07:15:44.570285 #4] FATAL -- : [ff69042f-aa16-4d59-8905-8b5beacee242]
2019-03-25T07:15:44.570427+00:00 app[web.1]: F, [2019-03-25T07:15:44.570372 #4] FATAL -- : [ff69042f-aa16-4d59-8905-8b5beacee242] app/controllers/comments_controller.rb:7:in `create'
timestamp_create_comments.rb
class CreateComments < ActiveRecord::Migration[5.2]
def change
create_table :comments do |t|
t.string :commenter
t.text :body
t.references :article, foreign_key: true
t.timestamps
end
end
end

When i deploy project on heroku db doesnt work normal

So i have this code in my mode
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# name :string
# surname :string
# user_id :integer
# count :integer default(0)
# was :boolean default(FALSE)
# qrcode :string
# created_at :datetime not null
# updated_at :datetime not null
#
class User < ApplicationRecord
validates :name, presence: true
validates :surname, presence: true
validates :user_id, presence: true
after_create :generate_qr
private
def generate_qr
ian = User.find(id)
ian.update_attribute(:qrcode, "https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=" + user_id.to_s)
# update_attribute(:qrcode, "https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=" + user_id.to_s)
end
end
Its work fine and generate qr code on my local host. But when i deploy on heroku i have this errors in heroku logs.
2018-06-30T14:23:37.200657+00:00 app[web.1]: I, [2018-06-30T14:23:37.200507 #4] INFO -- : [56b953ac-5a43-4b25-980d-f2bc5c53883a] Parameters: {"utf8"=>"✓", "authenticity_token"=>"mBkhE7alyyKGtS4v+tnW2Vpg6c1z0kwQfbnftqTWdSukTpre29vkqVmeuVoGR7NJzs0EoxiQv0rS+WzJ4hUSOw==", "user"=>{"name"=>"fdsfds", "surname"=>"fdsfdsfds", "user_id"=>"53454"}, "commit"=>"Create User"}
2018-06-30T14:23:37.204598+00:00 app[web.1]: D, [2018-06-30T14:23:37.204527 #4] DEBUG -- : [56b953ac-5a43-4b25-980d-f2bc5c53883a] (1.1ms) BEGIN
2018-06-30T14:23:37.207575+00:00 app[web.1]: D, [2018-06-30T14:23:37.207496 #4] DEBUG -- : [56b953ac-5a43-4b25-980d-f2bc5c53883a] User Create (1.5ms) INSERT INTO "users" ("name", "surname", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["name", "fdsfds"], ["surname", "fdsfdsfds"], ["user_id", 53454], ["created_at", "2018-06-30 14:23:37.204956"], ["updated_at", "2018-06-30 14:23:37.204956"]]
2018-06-30T14:23:37.214137+00:00 app[web.1]: D, [2018-06-30T14:23:37.214060 #4] DEBUG -- : [56b953ac-5a43-4b25-980d-f2bc5c53883a] User Load (1.3ms)
SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 7], ["LIMIT", 1]]
2018-06-30T14:23:37.215729+00:00 app[web.1]: D, [2018-06-30T14:23:37.215664 #4] DEBUG -- : [56b953ac-5a43-4b25-980d-f2bc5c53883a] (1.1ms) ROLLBACK
2018-06-30T14:23:37.224955+00:00 app[web.1]: I, [2018-06-30T14:23:37.224881 #4] INFO -- : [56b953ac-5a43-4b25-980d-f2bc5c53883a] Completed 500 Internal Server Error in 24ms (ActiveRecord: 6.1ms)
2018-06-30T14:23:37.225904+00:00 app[web.1]: F, [2018-06-30T14:23:37.225838 #4] FATAL -- : [56b953ac-5a43-4b25-980d-f2bc5c53883a]
2018-06-30T14:23:37.226043+00:00 app[web.1]: F, [2018-06-30T14:23:37.225990 #4] FATAL -- : [56b953ac-5a43-4b25-980d-f2bc5c53883a] NoMethodError (undefined method `qrcode=' for #<User:0x00000004fd1d68>):
2018-06-30T14:23:37.226091+00:00 app[web.1]: F, [2018-06-30T14:23:37.226046 #4] FATAL -- : [56b953ac-5a43-4b25-980d-f2bc5c53883a]
2018-06-30T14:23:37.226146+00:00 app[web.1]: F, [2018-06-30T14:23:37.226103 #4] FATAL -- : [56b953ac-5a43-4b25-980d-f2bc5c53883a] app/models/user.rb:25:in `generate_qr'
Someone please help. I dont know where is error. Its work fine on my localhost.

Rails: User info not updating (Rendered ActiveModel Serializer Null with Hash)

The same code is working in the local but not working in Heroku
def update
current_user.update!(user_params)
response = { message: Message.account_updated}
json_response(response)
end
private
def user_params
params.permit(:first_name, :last_name, :email, :password)
end
routes.rb
namespace :api do
namespace :v1 do
put 'user/update', to: 'users#update'
end
end
user_serializer.rb
class UserSerializer < ActiveModel::Serializer
attributes :id, :username, :first_name, :last_name, :email, :created_at, :updated_at
end
that is my and it's working on my local via Postman, that is for updating user info, but while I push to Heroku and try to update via Postman then not working, log showing like this
2018-04-30T10:15:47.665731+00:00 heroku[router]: at=info method=PUT path="/api/v1/user/update?first_name=John&last_name=Doe" host=my-host.herokuapp.com request_id=79a84b63-be87-46f8-8fad-2d151a63722f fwd="27.147.231.22" dyno=web.1 connect=0ms service=18ms status=500 bytes=283 protocol=https
2018-04-30T10:15:47.648979+00:00 app[web.1]: [79a84b63-be87-46f8-8fad-2d151a63722f] Started PUT "/api/v1/user/update?first_name=John&last_name=Doe"
for 27.147.231.22 at 2018-04-30 10:15:47 +0000
2018-04-30T10:15:47.650866+00:00 app[web.1]: [79a84b63-be87-46f8-8fad-2d151a63722f] Processing by Api::V1::UsersController#update as */*
2018-04-30T10:15:47.650987+00:00 app[web.1]: [79a84b63-be87-46f8-8fad-2d151a63722f] Parameters: {"first_name"=>"John", "last_name"=>"Doe"}
2018-04-30T10:15:47.654619+00:00 app[web.1]: [79a84b63-be87-46f8-8fad-2d151a63722f] User Load (1.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
2018-04-30T10:15:47.656446+00:00 app[web.1]: [79a84b63-be87-46f8-8fad-2d151a63722f] CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
2018-04-30T10:15:47.658345+00:00 app[web.1]: [79a84b63-be87-46f8-8fad-2d151a63722f] (1.1ms) BEGIN
2018-04-30T10:15:47.661446+00:00 app[web.1]: [79a84b63-be87-46f8-8fad-2d151a63722f] User Exists (1.2ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER($1) AND "users"."id" != $2 LIMIT $3 [["email", "j#gmail.com"], ["id", 1], ["LIMIT", 1]]
2018-04-30T10:15:47.663630+00:00 app[web.1]: [79a84b63-be87-46f8-8fad-2d151a63722f] (1.0ms) COMMIT
2018-04-30T10:15:47.664737+00:00 app[web.1]: [79a84b63-be87-46f8-8fad-2d151a63722f] [active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (0.51ms)
2018-04-30T10:15:47.665015+00:00 app[web.1]: [79a84b63-be87-46f8-8fad-2d151a63722f] Completed 500 Internal Server Error in 14ms (Views: 1.1ms | ActiveRecord: 4.5ms)
I think that's the problem
Rendered ActiveModel::Serializer::Null with Hash (0.51ms)
But I don't understand what's going on.
Update
module Response
def json_response(object, status = :ok)
render json: object, status: status
end
end
First of all
Rendered ActiveModel::Serializer::Null with Hash (0.51ms)
That's not the issue for not updating user info, it's showing in the log because ActiveModel::Serializer serialize the columns which have null value.
I think the problem is elsewhere like you need to refactor why causes this e.g you can try to remove ! update!(user_params) try like this current_user.update(user_params) or any other.
# place this method inside NullAttributesRemover or directly inside serializer class
def serializable_hash(adapter_options = nil, options = {}, adapter_instance = self.class.serialization_adapter_instance)
hash = super
hash.each { |key, value| hash.delete(key) if value.nil? }
hash
end
it will serialize columns which have only real values.
I think it will help.

Why is this object undefined? Ruby, Rails, Gmail error

I can't seem to figure out why I am getting the error :
2017-01-03T02:57:35.239505+00:00 app[web.1]: I, [2017-01-03T02:57:35.239437 #4] INFO -- : [89b504ee-5835-4bfa-a3ff-91a3a84549f6] Parameters: {"id"=>"3"}
2017-01-03T02:57:35.243975+00:00 app[web.1]: D, [2017-01-03T02:57:35.243890 #4] DEBUG -- : [89b504ee-5835-4bfa-a3ff-91a3a84549f6] User Load (1.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 22], ["LIMIT", 1]]
2017-01-03T02:57:35.468562+00:00 app[web.1]: true
2017-01-03T02:57:35.476648+00:00 app[web.1]: D, [2017-01-03T02:57:35.476563 #4] DEBUG -- : [89b504ee-5835-4bfa-a3ff-91a3a84549f6] Blueprint Load (2.7ms) SELECT "blueprints".* FROM "blueprints" WHERE "blueprints"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
2017-01-03T02:57:35.477654+00:00 app[web.1]: I, [2017-01-03T02:57:35.477582 #4] INFO -- : [89b504ee-5835-4bfa-a3ff-91a3a84549f6] Completed 500 Internal Server Error in 238ms (ActiveRecord: 5.5ms)
2017-01-03T02:57:35.478257+00:00 app[web.1]: F, [2017-01-03T02:57:35.478177 #4] FATAL -- : [89b504ee-5835-4bfa-a3ff-91a3a84549f6]
2017-01-03T02:57:35.478313+00:00 app[web.1]: F, [2017-01-03T02:57:35.478256 #4] FATAL -- : [89b504ee-5835-4bfa-a3ff-91a3a84549f6] Gmail::Client::DeliveryError (Couldn't deliver email: undefined method `subject' for nil:NilClass):
For some reason the object #current_blueprint doesn't seem to be working inside of the gmail.deliver block. Am I missing something obvious?
Appreciate any help. Thanks!
#current_blueprint = Blueprint.find(params[:id])
mail_status = gmail.deliver! do
to "email#gmail.com"
subject #current_blueprint.subject
html_part do
content_type 'text/html; charset=UTF-8'
body #current_blueprint.body
end
end
puts mail_status
Try just current_blueprint without the # sign.
Sometime a library executes a do end with a different self and can thus not access instance variables, but it should be able to access local variables that are in scope.
Just guessing, let me know whether it works.

Resources