I'm using:
ruby 2.6
rails 6.1.4
devise
devise_token_auth
active-storage usingl locally disk service
I'm creating api in which I can storage and upload pictures. I can upload pic via Insomnia but problem is when I want to add second image to the same user. Image is just replacing.
user.rb
# frozen_string_literal: true
class User < ActiveRecord::Base
def initialize
self.pictures = []
end
extend Devise::Models #added this line to extend devise model
# Include default devise modules. Others available are:
# :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :confirmable
include DeviseTokenAuth::Concerns::User
VALID_USERNAME_REGEX= /^(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(?<![_.])$/ix
validates :username, presence: true, length: {minimum:3, maximum:26},
format: { with: VALID_USERNAME_REGEX, :multiline => true,
message: :invalid_username }
validate :password_complexity
attr_accessor :pictures
has_many_attached :pictures
validates :pictures, content_type: ['image/png', 'image/jpg', 'image/jpeg'],
size: { less_than: 5.megabytes , message: :invalid_size }
def password_complexity
return if password.blank? || password =~ /^((?!.*[\s]))/
errors.add :password, :invalid_password
end
end
application_controller.rb
class ApplicationController < ActionController::API
include DeviseTokenAuth::Concerns::SetUserByToken
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:account_update, keys: [:pictures, :username, :email])
end
end
All controllers which I use are default from devise_token_auth. I found tip to add in config/application.rb
config.active_storage.replace_on_assign_to_many = false
but after that I'm always getting status 500
Did you add an array to the parameter so you can store multiple image ?
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:account_update, keys: [:pictures [], :username, :email])
end
I solved a similar problem by adding this to the config/environment/development.rb (as per the Rails Guide):
config.active_storage.replace_on_assign_to_many = false
Good luck!
The best way to solve this is to open application.rb and inside your module add.
config.active_storage.replace_on_assign_to_many = false
That is all you need to do. It works, Just make sure you save all your files, and restart your server.
You can see in the rails docs it says the following:
Optionally replace existing files instead of adding to them when assigning to a collection of attachments (as in #user.update!(images: [ … ])). Use config.active_storage.replace_on_assign_to_many to control this behavior.
Rails Guides
Related
Alright so I’m building an app using Rails 7, Devise, and Rolify. I want to start using Friendly ID to create the URL slugs for my different database tables. I’m applying this to the user table first so I’m adding the username column to the User table. I was able to successfully add the username string to the existing user records I had and I was able to update my User model with the proper syntax to view the users with their friendly ID URL slug based on the username.
I’m running into an error when creating a new user.
NoMethodError (undefined method `for' for #<Devise::ParameterSanitizer:0x00007fc11795a7b0 #auth_keys=[:email], #params=#<ActionController::Parameters {"authenticity_token"=>"bhh5F5BA1ERwI22Trejc1NvudieV9akyOtzS69kAi4Za6sRFpYB65OseiLWBSelfMkS-AAHld-vhDeSX7cMWbQ", "user"=>{"username"=>"bootyman", "email"=>"bootyman#gmail.com", "role_ids"=>["", "3"], "password"=>"password", "password_confirmation"=>"password"}, "commit"=>"Sign up", "controller"=>"devise/registrations", "action"=>"create"} permitted: false>, #resource_name=:user, #permitted={:sign_in=>[:email, :password, :remember_me], :sign_up=>[:email, :password, :password_confirmation], :account_update=>[:email, :password, :password_confirmation, :current_password]}>):
22:42:42 web.1 |
22:42:42 web.1 | app/controllers/application_controller.rb:10:in `configure_permitted_parameters'
Based on some research on the Devise gem GitHub page I found some things that pointed to adding some code to the application_controller.rb
Here's my application controller:
class ApplicationController < ActionController::Base
respond_to :html, :json
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:email, :username, :password, :password_confirmation)
end
end
def require_user
unless user_signed_in?
flash[:alert] = "You must be logged in to perform that action"
redirect_to new_user_session_path
end
end
end
Here's my User model:
class User < ApplicationRecord
has_many :events, dependent: :destroy
has_many :artists, dependent: :destroy
rolify
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :email, presence: true,
uniqueness: { case_sensitive: false },
length: { maximum: 105 },
format: { with: URI::MailTo::EMAIL_REGEXP }
validates :password, :presence => true, :on => :create
validates :username, :presence => true, :on => :create
validates_uniqueness_of :username, case_sensitive: false
validates :roles, presence: true
extend FriendlyId
friendly_id :username, use: :slugged
def admin?
self.has_role?(:Admin)
end
end
I found on GitHub that the .for method was deprecated and the replacement code in the devise/parameter_sanitizer.rb for the method is
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
devise_parameter_sanitizer.permit(:account_update, keys: [:name])
end
To access this file you need to run bundle open devise to access the gem files for Devise.
Reference link
I am new to Rails and I've started building an authentication feature in a sample rails app using "Devise" gem.
I've added a migration to add a new column named username in my devise model named User.
I've also added some validations regarding the username column that I had created, so my user.rb looks like this:
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable
validates_presence_of :username
validates_uniqueness_of :username
validates_length_of :username, :minimum => 5, :maximum => 10
end
Now every time during sign up of a new user, I get the validations for username even though it shouldn't.
For example, it tells me username shouldn't be blank even though username is filled.
Username should be minimum 5 characters, even though it is.
What am I doing wrong?
In the console, I can see the username being passed in the params during form submit and also : Unpermitted parameter :username.
Secondly, I want to create multiple signups using same email address but different username.
How can I do that?
I'm using ruby 2.4.1 and rails 5.1.4. Thanks.
You have to do at least four things to get this to work:
1. Setup the proper validations
Since you are not using the authenticable module you should make sure you validate the user properly:
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable
validates_presence_of :email # optional
validates_presence_of :username # required
validates_uniqueness_of :username # required
validates_presence_of :password, if: :password_required? # recommended
validates_confirmation_of :password, if: :password_required? # recommended
validates_length_of :password, within: password_length, allow_blank: true # recommended
end
2. Configure devise to use :username instead of :email as the authentication column:
# config/initializers/devise.rb
# ...
config.authentication_keys = [ :username ]
config.reset_password_keys = [ :username ]
config.confirmation_keys = [ :username ]
You might want to search config/initializers/devise.rb for :email to find additional options.
3. Remove the database uniqueness constraint for email:
Generate a new migration and place this in the change block:
remove_index "users", name: "index_users_on_email"
add_index "users", "email", unique: false
If you have not already make sure you have a unique index on users.username.
4. Whitelist the params.
Params whitelisting in Devise is a bit more complicated than for your average rails resource due to the amount of configurability.
You need to whitelist the username param both for sign_up and sign_in:
class ApplicationController < ActionController::Base
# ...
before_action :configure_devise_parameters, if: :devise_controller?
# ...
private
def configure_devise_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
devise_parameter_sanitizer.permit(:sign_in, keys: [:username], except: [:email])
end
end
The best refence is by reading the source which is very well commented.
You need to permit username in strong parameters.
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
end
end
Please follow https://github.com/plataformatec/devise#strong-parameters
For youre second question :
you need to overwrite devise validation for Email
https://github.com/plataformatec/devise/wiki/How-to:-Use-a-custom-email-validator-with-Devise Will help you,
Follow Skip email validation in Devise
I'm working on creating an application with role based authorization.So,In i have created a migration to devise users to add a new column "role"
And I have the following code block in my applications controller to permit the new parameter(role).But still when i try to sign up as a new user.I get the error that the parameter role is unpermitted.Please help me to solve this issue.
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit( :email, :password, :password_confirmation, roles: [] ) }
end
end
This is what i've got in my user model
class User < ApplicationRecord
belongs_to :role
# has_many :Product
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
ROLES = %i[admin manager customer]
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation, :role)
end
end
migration is as follows
class AddRoleToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :role, :string
end
end
Please help me to solve this issue.Thank you.
Your user model doesn't have access to params, so you can remove the user_params method from there. Unless you're nesting attributes, you won't need to pass in the array for the role attribute, so change
devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit( :email, :password, :password_confirmation, roles: [] ) }
to
devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit( :email, :password, :password_confirmation, :role ) }
#
And you should be good to go.
I am using devise for my rails app. I wanted to add the username field so I added a migration to the database.
Now I want devise to validate the user_name field for uniqueness but I am not able to figure out how to do that.
I also want it to show the error as it does with the default email field.
Just add validation for user_name in User model
validates :user_name, uniqueness: true
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
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation, :remember_me) }
end
end
User Model code change - add validation
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates :username , uniqueness: {case_sesitive: false}
end
I'm working with Rails 4 and Devise 3.0.0 and am new to using these new strong paramters. I added a username to the User model using the documentation on the Devise wiki. The problem I'm running into is the strong parameters change in Rails 4.
How do I add the :login attribute to the user model to enable logging in with either the username or email?
From the rails4 readme on devise: https://github.com/plataformatec/devise/tree/rails4#strong-parameters
class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:login, :email) }
end
end
#justin.chmura
Here is a gist of how we ended up getting it working.
https://gist.github.com/AJ-Acevedo/6077336
Gist contains:
app/controllers/application_controller.rb
app/models/user.rb
config/initializers/devise.rb
You should make sure that you include the
attr_accessor :login
in the user model. Here is where I found the question explaining that attr_accessible is deprecated.
Rails 4 + Devise Login with email or username and strong parameters
Difference between attr_accessor and attr_accessible
This is what my app/models/user.rb file looks like.
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessor :login
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions).where(["username = :value OR lower(email) = lower(:value)", { :value => login }]).first
else
where(conditions).first
end
end
validates :username,
:uniqueness => {
:case_sensitive => false
}
end
It will works fine if you add an module in config/initializers as followings with all parameters,
File config/initializers/devise_permitted_parameters.rb with following contents:
module DevisePermittedParameters
extend ActiveSupport::Concern
included do
before_filter :configure_permitted_parameters
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation) }
end
end
DeviseController.send :include, DevisePermittedParameters