to_model delegated to attachment, but attachment is nil - ruby-on-rails

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

Related

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

rails validates_format_of with IP addresses

I'm allowing a user to enter IP addresses in an input field which may be of different types delimited by a comma, such as (in no particular order):
192.168.1.1,192.168.2.1-25,10.10.10.0/24,192.168.1.2
This 'string' would get saved in my DB under device.ips_to_scan.
I want to validates_format_of on these, but am finding it a little difficult to write a regex that seems to work in rails, while it does work on regex101 (https://regex101.com/r/nf2bnM/1):
validates_format_of :ips_scan, with: /\A([0-9]{1,3}\.){3}[0-9]{1,3}(\/([1-2][0-9]|[0-9]|3[0-2]))?(-([0-9]{1,3}))?,?\Z/i, on: :update
This one is expected to fail:
Started PUT "/devices/2" for 127.0.0.1 at 2018-02-19 22:03:15 -0500
Processing by DevicesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"EQCFG6/xoJHtP6Nd3oqaYRW6mypfEoCMrnio1yj6loP+KtvjgLZ9Gmhb0oTwCjD0RGH+qQuctZFVIvF5HBJcGw==", "device"=>{"ips_scan"=>"192.168.1.1,192.168.2.1-25,a.b.c.d", "ips_exclude"=>"10.10.10.1"}, "commit"=>"Save", "id"=>"2"}
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 2], ["LIMIT", 1]]
Device Load (1.6ms) SELECT "devices".* FROM "devices" WHERE "devices"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
(0.5ms) BEGIN
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
(0.5ms) ROLLBACK
Redirected to http://localhost:3000/devices/2/edit
Completed 302 Found in 47ms (ActiveRecord: 12.1ms)
...But this one should have worked:
Processing by DevicesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"JJfmT/0l5MEDc+gUH/WHHp3bbgyzjGa0xTzaXM3E/WHLvbi30mI5SoYXmc0xdS2LzAALj+cCU6k+ZoPy+Sw3+Q==", "device"=>{"ips_scan"=>"192.168.1.1,192.168.2.1-25,192.168.1.2", "ips_exclude"=>"10.10.10.1"}, "commit"=>"Save", "id"=>"2"}
User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 2], ["LIMIT", 1]]
Device Load (0.7ms) SELECT "devices".* FROM "devices" WHERE "devices"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
(0.6ms) BEGIN
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
(0.6ms) ROLLBACK
Redirected to http://localhost:3000/devices/2/edit
Completed 302 Found in 17ms (ActiveRecord: 3.5ms)
Last thing I can think of, is that I do have strong parameters, but I'm permitting ips_scan, so that this shouldn't be an issue:
def update
if #device.update(device_params)
flash[:notice] = 'Successful update'
respond_with :edit, :device
else
flash[:warning] = 'Unable to update'
respond_with :edit, :device
end
end
private def device_params
params.require(:device).permit(:token, :ips_scan, :ips_exclude)
end
I'm hoping you rubyist's out there have a eloquent solution. The first thought that comes to mind is that I have to split the string, and check each element sequentially to ensure it matches instead.
While I'm still open to a nice eloquent one-liner within the Model itself, I was able to get this working through creating a concern:
models/concerns/ip_validator.rb
class IpValidator < ActiveModel::Validator
def validate(record)
ips = record.ips_scan.split(',')
ips.each do |ip|
/([0-9]{1,3}\.){3}[0-9]{1,3}(\/([1-2][0-9]|[0-9]|3[0-2]))?(-([0-9]{1,3}))?/ =~ ip
record.errors.add(:ips_scan, ' is not valid') unless $LAST_MATCH_INFO
end
end
end
The call in my model now looks like:
validates :ips_scan, :ips_exclude, ip: true, on: :update
You can use this method in your custom validator to check an IP address
require 'ipaddr'
def valid_ip_addr?(ip_addr)
IPAddr.new(ip_addr)
true
rescue IPAddr::InvalidAddressError => _error
false
end

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])

POST "/admin/users/26/approve_vip" not working

I want to approve the user to be vip,but when I press the button.The page refreshed but nothing changed.The log in terminal is
Started POST "/admin/users/26/approve_vip" for ::1 at 2016-12-12 16:33:22 +0800
Processing by Admin::UsersController#approve_vip as HTML
Parameters: {"authenticity_token"=>"qYrbaVH/cssY3VBYLw6Hd4wXl42Zz8OqkdHGGoITEeeWtbJ4ZOLOmJF/Jmpx70s9aaL5Yr0vFhqNV9kGHtILpA==", "user_id"=>"26"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 4], ["LIMIT", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 26], ["LIMIT", 1]]
SQL (1.4ms) UPDATE "users" SET "is_vip" = 't' WHERE "users"."id" = ? [["id", 26]]
(0.0ms) begin transaction
(0.0ms) commit transaction
DEPRECATION WARNING: `redirect_to :back` is deprecated and will be removed from Rails 5.1. Please use `redirect_back(fallback_location: fallback_location)` where `fallback_location` represents the location to use if the request has no HTTP referer information. (called from approve_vip at /Users/a1/JDDstore/app/controllers/admin/users_controller.rb:26)
Redirected to http://localhost:3000/admin/users
Completed 302 Found in 6ms (ActiveRecord: 1.7ms)
Started POST "/admin/users/26/approve_vip" for ::1 at 2016-12-12 15:41:47 +0800
Processing by Admin::UsersController#approve_vip as HTML
Parameters: {"authenticity_token"=>"uYc9hdEZaYCgfhdmYK3XnyK2lcraPpHWfuXcQ5cRtLyGuFSU5ATV0yncYVQ+TBvVxwP7Jf7eRGZiY8NfC9Cu/w==", "user_id"=>"26"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 4], ["LIMIT", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 26], ["LIMIT", 1]]
(0.0ms) begin transaction
(0.0ms) commit transaction
DEPRECATION WARNING: `redirect_to :back` is deprecated and will be removed from Rails 5.1. Please use `redirect_back(fallback_location: fallback_location)` where `fallback_location` represents the location to use if the request has no HTTP referer information. (called from approve_vip at /Users/a1/JDDstore/app/controllers/admin/users_controller.rb:26)
Redirected to http://localhost:3000/admin/users
Completed 302 Found in 4ms (ActiveRecord: 0.3ms)
And the code in controller is
def approve_vip
#user = User.find(params[:user_id])
#user.is_vip=true
#user.save
redirect_to :back
end
Can you tell me why it not change the role?
If you want to know more informatian, please let me know. Thank you very much for helping me.
It looks you have some model callback (may be before_save) which is restricting to update the records.
You can use update_column or update_columns to bypass the callbacks/validations and directly make a update query to your db.
def approve_vip
#user = User.find(params[:user_id])
#user.update_columns(is_vip: true)
redirect_to :back
end
You need to read error's message. Probably the user's validation is failed.
def approv!
update_attributes!(is_vip: true)
end
This code give you exception with the error's message.

Nested resource failing to update

I'm trying to do what I think should be simple: do a simple edit on a single text string field with the default update action. But it just doesn't seem to work, despite many attempts and alterations.
There are no errors and the flash message responds successfully, but information isn't saved to the database at all:
routes.rb
resources :interviews do
resources :invitations do
put :accept
end
end
views/invitations/edit.html.haml
= simple_form_for [#interview, #invitation] do |f|
= f.error_notification
= f.input :testing
= f.submit 'Edit Invitstion', :class => 'button small'
controllers/invitations_controller.rb
def update
#invitation = Invitation.find(params[:id])
#interview = Interview.find(params[:interview_id])
#invitation.update_attributes(invitation_params)
if #invitation.update_attributes(invitation_params)
redirect_to edit_interview_invitation_path(#interview, #invitation), notice: "Your profile has been successfully updated."
else
render action: "edit"
end
end
private
def invitation_params
params.permit(:user_id, :interview_id, :invitation_id, :session_time, :workflow_state, :testing)
end
And here's the log:
Started PATCH "/interviews/3/invitations/7" for ::1 at 2016-05-15 19:01:52 +0800
Processing by InvitationsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"o0U5t0yPN0aE2er+DWK0uxqRGyp4ywfdSrEfvwiSQ3UUaOnr3Fd0raFs1IUqVzizKoqxRU0DDpmvysntB9fdhQ==", "invitation"=>{"interview_id"=>"3", "workflow_state"=>"invited", "session_time"=>"", "testing"=>"testtesttest"}, "commit"=>"Edit Invitstion", "interview_id"=>"3", "id"=>"7"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 7]]
Invitation Load (0.2ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT 1 [["id", 7]]
Role Load (0.2ms) SELECT "roles".* FROM "roles" WHERE "roles"."id" = $1 LIMIT 1 [["id", 3]]
Interview Load (0.2ms) SELECT "interviews".* FROM "interviews" WHERE "interviews"."id" = $1 ORDER BY created_at DESC LIMIT 1 [["id", 3]]
CACHE (0.0ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT 1 [["id", "7"]]
CACHE (0.0ms) SELECT "interviews".* FROM "interviews" WHERE "interviews"."id" = $1 ORDER BY created_at DESC LIMIT 1 [["id", "3"]]
Unpermitted parameters: utf8, _method, authenticity_token, invitation, commit, id
(0.1ms) BEGIN
Invitation Exists (0.4ms) SELECT 1 AS one FROM "invitations" WHERE ("invitations"."user_id" = 3 AND "invitations"."id" != 7 AND "invitations"."interview_id" = 3) LIMIT 1
(0.1ms) COMMIT
Redirected to http://localhost:3000/interviews/3/invitations/7/edit
Completed 302 Found in 12ms (ActiveRecord: 1.6ms)
Started GET "/interviews/3/invitations/7/edit" for ::1 at 2016-05-15 19:01:52 +0800
Processing by InvitationsController#edit as HTML
Parameters: {"interview_id"=>"3", "id"=>"7"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 7]]
Invitation Load (0.3ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT 1 [["id", 7]]
Role Load (0.2ms) SELECT "roles".* FROM "roles" WHERE "roles"."id" = $1 LIMIT 1 [["id", 3]]
Interview Load (0.2ms) SELECT "interviews".* FROM "interviews" WHERE "interviews"."id" = $1 ORDER BY created_at DESC LIMIT 1 [["id", 3]]
Rendered invitations/edit.html.haml within layouts/application (6.1ms)
Completed 200 OK in 48ms (Views: 39.1ms | ActiveRecord: 1.6ms)
Check the format of your params object in your logs. Your invitation params are being passed within the params["invitation"] key, yet you're whitelisting and updating your object based on the params in the root params hash.
Also note that your logs are reporting that you're trying to update your invitation with unpermitted params:
Unpermitted parameters: utf8, _method, authenticity_token, invitation, commit, id
You can fix this by simply updating your invitation_params to use params[:invitation] rather than params like so:
def invitation_params
params.require(:invitation).permit(:user_id, :interview_id, :invitation_id, :session_time, :workflow_state, :testing)
end
Also, you might want to consider raising an error if you're trying to update a parameter that's not whitelisted to prevent these sorts of issues in the future.
In your rails config:
config.action_controller.action_on_unpermitted_parameters = :raise

Resources