Rails: User info not updating (Rendered ActiveModel Serializer Null with Hash) - ruby-on-rails

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.

Related

Why does Rails rollback even though the model exists?

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.

devise not updating user, redirects to '/users' without any error

Whenever I try to update the user, I get redirected to /users with the edit form filled in but no errors.
Users::RegistrationsController
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_account_update_params, only: [:update]
def update
super
end
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:name,:property,:admin,:phone_number,:organization,:gender,:profile_pic,:birthday])
end
...
end
Rails Server Logs
Started PUT "/users" for ::1 at 2020-07-22 17:55:57 +0500
Processing by Users::RegistrationsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"iqpDtwA8U1jJ10dtaCV/eE0m96KHUa8G7tWrpOLA48AXYnUjT+6M2qwrwncjThvwQnQQycn/dNCWsbnsteJmhA==", "user"=>{"name"=>"Sohail ", "phone_number"=>"(11", "organization"=>"11", "email"=>"user#test.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "current_password"=>"[FILTERED]"}, "commit"=>"Update"}
User Load (1.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 8], ["LIMIT", 1]]
User Load (1.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 8], ["LIMIT", 1]]
User Exists (1.1ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 AND "users"."id" != $2 LIMIT $3 [["email", "user#test.com"], ["id", 8], ["LIMIT", 1]]
Rendering users/registrations/edit.html.erb within layouts/application
Rendered users/registrations/edit.html.erb within layouts/application (3.9ms)
StripeCustomer Load (4.6ms) SELECT "stripe_customers".* FROM "stripe_customers" WHERE "stripe_customers"."user_id" = $1 LIMIT $2 [["user_id", 8], ["LIMIT", 1]]
Rendered layouts/_header.html.erb (97.4ms)
Rendered layouts/_footer.html.erb (15.5ms)
Completed 200 OK in 681ms (Views: 310.2ms | ActiveRecord: 9.0ms)
It seems you have messed a little with your parameters. You sent nested parameters on your form like this:
"user"=>{"name"=>"Sohail ", "phone_number"=>"(11", "organization"=>"11", "email"=>"user#test.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "current_password"=>"[FILTERED]"}, "commit"=>"Update"}
However your permited parameters assume you are nesting everything on a :account_update key.
So you could either change the key sent on your form, or use this sanitizer:
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:name,:property,:admin,:phone_number,:organization,:gender,:profile_pic,:birthday])
end

to_model delegated to attachment, but attachment is nil

So I asked this question already here:
previous question
and didn't get much help, I looked for other questions similar to mine, but no resolution. So I'll ask the question again in hopes of getting help.
The issue is that the image that is uploaded for a user profile banner isnt showing on the user show page aka profile page. I'm using active storage. I already have the
has_on_attached :banner_image
.profile-header
= image_tag url_for(#user.banner_image)
def set_user
#user = User.find(params[:id])
end
devise registration config:
def configure_account_update_params
before_action :configure_account_update_params, only: [:update]
devise_parameter_sanitizer.permit(:sign_up, keys: [:firstname, :banner_image])
end
error msg image
Terminal reads when refreshing the profile page:
Started GET "/users/1" for ::1 at 2019-09-20 21:51:59 -0700
Processing by UsersController#show as HTML
Parameters: {"id"=>"1"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
↳ app/controllers/users_controller.rb:11
Rendering users/show.html.haml within layouts/application
ActiveStorage::Attachment Load (0.2ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ? [["record_id", 1], ["record_type", "User"], ["name", "banner_image"], ["LIMIT", 1]]
↳ app/views/users/show.html.haml:2
Listing Load (0.1ms) SELECT "listings".* FROM "listings" WHERE "listings"."user_id" = ? [["user_id", 1]]
↳ app/views/users/show.html.haml:5
Rendered users/show.html.haml within layouts/application (5.5ms)
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
↳ app/views/layouts/_navigation.html.haml:18
Rendered layouts/_navigation.html.haml (8.7ms)
Completed 200 OK in 61ms (Views: 57.8ms | ActiveRecord: 0.7ms)
ISSUE RESOLVED:
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:firstname, :image])
end
# If you have extra params to permit, append them to the sanitizer.
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:firstname, :image])
end
so the configure_account_update_params defenition was set to permit the :signup not :account_update. I changed it to :account_update and it worked!
It seems that you don't have a banner image for the user. If your view layout breaks because the user has no banner so use conditional if in your code
image_tag url_for(#user.banner_image) if #user.banner_image.present?
Or you may want to have a fallback image to preserve the layout
image_tag url_for(#user.banner_image || '/public/fallback_banner_image.jpg')
The above line is an example but you will need to include an actual file image/path

Rails api - why incorrect ID send null instead of 404?

When I enter an incorrect track_id in url for example : tracks/123456
=> it returns 404 not found as expected !
If I try with incorrect challenge_id which is one of my other model : tracks/1/challenges/12345
=> it return null instead of 404 not found.
The code of both seems to be the same so I can't found the issue.
If you could help me to found why I get null instead of 404, seeing the code below :
routes.rb
resources :tracks do
resources :challenges do
resources :ressources
end
end
challenges_controller.rb
def show
render json: #challenge, include: [:ressources, :challenges_startups]
end
private
def set_challenge
#track = Track.find(params[:track_id])
#challenge = #track.challenges.where(id: params[:id]).first
end
tracks_controller.rb
def show
render json: #track, include: [:challenges]
end
private
def set_track
#track = Track.find(params[:id])
end
rails_server
For challenges => the wrong one
Started GET "/tracks/3/challenges/20/" for 127.0.0.1 at 2017-07-31 12:24:19 +0200
ActiveRecord::SchemaMigration Load (0.5ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by ChallengesController#show as */*
Parameters: {"track_id"=>"3", "id"=>"20"}
Track Load (0.4ms) SELECT "tracks".* FROM "tracks" WHERE "tracks"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
Challenge Load (0.3ms) SELECT "challenges".* FROM "challenges" WHERE "challenges"."track_id" = ? AND "challenges"."id" = ? ORDER BY "challenges"."id" ASC LIMIT ? [["track_id", 3], ["id", 20], ["LIMIT", 1]]
Startup Load (0.4ms) SELECT "startups".* FROM "startups" ORDER BY "startups"."id" ASC LIMIT ? [["LIMIT", 1]]
[active_model_serializers] Rendered ActiveModel::Serializer::Null with Class (0.18ms)
Completed 200 OK in 63ms (Views: 19.3ms | ActiveRecord: 2.6ms)
For tracks
Started GET "/tracks/222" for 127.0.0.1 at 2017-07-31 12:30:37 +0200
Processing by TracksController#show as */*
Parameters: {"id"=>"222"}
Track Load (0.2ms) SELECT "tracks".* FROM "tracks" WHERE "tracks"."id" = ? LIMIT ? [["id", 222], ["LIMIT", 1]]
Startup Load (0.3ms) SELECT "startups".* FROM "startups" ORDER BY "startups"."id" ASC LIMIT ? [["LIMIT", 1]]
[active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (0.16ms)
Completed 404 Not Found in 6ms (Views: 4.1ms | ActiveRecord: 0.5ms)
You have defined #challenge like below
#challenge = #track.challenges.where(id: params[:id]).first
where returns nil if there is no record matching the condition. That is why you get null instead of 404 not found.
Whereas find in contrast returns 404 not found if the record doesn't exist.
If you want to get 404 not found, then modify #challenge like below
#challenge = #track.challenges.find(params[:id])

uninitialized constant ApplicationController::PermittedParams strong parameters

Don't know where i'm getting wrong, i have searched a lot googling and also in SO but i don't understand what i am doing wrong.
My Application Controller
class ApplicationController < ActionController::Base
helper_method :clipboard, :current_user, :signed_in?, :permitted_params
def permitted_params
#permitted_params ||= PermittedParams.new(params, current_user)
end
My Model Permitted_Param.rb
class PermittedParams < Struct.new(:params, :current_user)
%w{folder group share_link user user_file}.each do |model_name|
define_method model_name do
params.require(model_name.to_sym).permit(*send("#{model_name}_attributes"))
end
end
def folder_attributes
[:name]
end
def group_attributes
[:name]
end
def share_link_attributes
[:emails, :link_expires_at, :message]
end
def user_attributes
if current_user && current_user.member_of_admins?
[:name, :email, :password, :password_confirmation, { :group_ids => [] }]
else
[:name, :email, :password, :password_confirmation]
end
end
def user_file_attributes
[:attachment, :attachment_file_name]
end
end
Log
Started GET "/" for 127.0.0.1 at 2015-04-16 19:37:02 +0530
ActiveRecord::SchemaMigration Load (0.6ms) SELECT
"schema_migrations".* FROM "schema_migrations" Processing by
FoldersController#index as HTML User Load (0.5ms) SELECT "users".*
FROM "users" WHERE "users"."is_admin" = ? LIMIT 1 [["is_admin", "t"]]
Redirected to http://localhost:3000/admins/new Filter chain halted as
:require_admin_in_system rendered or redirected Completed 302 Found in
207ms (ActiveRecord: 1.0ms) Started GET "/admins/new" for 127.0.0.1 at
2015-04-16 19:37:03 +0530 Processing by AdminsController#new as HTML
User Load (0.2ms) SELECT "users".* FROM "users" WHERE
"users"."is_admin" = ? LIMIT 1 [["is_admin", "t"]] Rendered
admins/new.html.erb within layouts/application (331.3ms) User Load
(0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL
LIMIT 1 Rendered shared/_header.html.erb (21.3ms) CACHE (0.1ms)
SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
Rendered shared/_menu.html.erb (8.4ms) Rendered
shared/_footer.html.erb (0.8ms) Completed 200 OK in 1789ms (Views:
1707.5ms | ActiveRecord:
1.7ms)
Started POST "/admins" for 127.0.0.1 at 2015-04-16 19:37:19 +0530 Processing by AdminsController#create as HTML Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"5VPDMdM6Cny63T00tcgU55ukkDD9XChTQwWjAJ7IUZ0ELh6D5c7UhbpbOKdQ3atdaNIaBVk5AxctcC0j09pcvQ==",
"user"=>{"name"=>"ChiragArya", "email"=>"edwardmaya008#gmail.com",
"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"},
"commit"=>"Create admin account"} User Load (0.4ms) SELECT
"users".* FROM "users" WHERE "users"."is_admin" = ? LIMIT 1
[["is_admin", "t"]] Completed 500 Internal Server Error in 26ms
(ActiveRecord: 0.4ms)
NameError (uninitialized constant ApplicationController::PermittedParams):
app/controllers/application_controller.rb:26:in permitted_params'
app/controllers/admins_controller.rb:10:in
Rendered /home/chirag/.rvm/gems/ruby-2.2.2/gems/actionpack-4.2.1/lib/action_dispatch/middleware/templates/rescues/_source.erb
(54.9ms) Rendered
/home/chirag/.rvm/gems/ruby-2.2.2/gems/actionpack-4.2.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (35.3ms) Rendered
/home/chirag/.rvm/gems/ruby-2.2.2/gems/actionpack-4.2.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
(10.4ms) Rendered
/home/chirag/.rvm/gems/ruby-2.2.2/gems/actionpack-4.2.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb
within rescues/layout (227.5ms)
I got the same problem and i resolved that after renaming my strong parameter function name to controllername_params
I don't know where is the mention but i'd love to know that .

Resources