Devise with nested_attributes—field showing data but not updating the model - ruby-on-rails

I have the following code (in Slim format), which displays a form for users. The user's data displays and updates on submit. However, phone which is a nested attribute from publisher displays current data when I load the form, but wont update on submit.
View
= form_for current_user, url: user_registration_path, html: {class: 'account'} do |user_form|
.row
.control-group.text-center
label.col-9 Email
= user_form.text_field :email, class: 'col-7'
= fields_for :publisher, current_user.publisher do |publisher_form|
.row
.control-group.text-center
label.col-9 Phone
= publisher_form.text_field :phone, class: 'col-7'
Registrations Controller
class RegistrationsController < Devise::RegistrationsController
def update_resource(resource, params)
resource.update_without_password(params)
end
end
Application Controller
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(:account_update) {|u| u.permit(
:first_name,
:last_name,
:email,
:password,
:password_confirmation,
:current_password,
publisher_attributes: [:phone, :payment_details],
banner_attributes: [:website, :banner_msg, :signup_msg, :bg_col, :txt_col, :btn_col]
)}
end
end
User Model
class User < ActiveRecord::Base
has_one :publisher
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
accepts_nested_attributes_for :publisher
validates_presence_of :first_name, :last_name
validates_length_of :first_name, maximum: 100
validates_length_of :last_name, maximum: 100
end

I finally discovered that
= fields_for :publisher, current_user.publisher do |publisher_form|
should be:
= user_form.fields_for :publisher, current_user.publisher do |publisher_form|

Related

Devise error when creating a new user with username and roles

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

How to fix 'Validation' that is not occurring in my wicked wizard first step

I'm new to programming in Ruby but my code for validation is not occurring at all in the first step of my wizard after logging in. My validation for the two extra fields work for the initial screen but the remaining fields it doesn't work at all?
I'm using Devise gem for the authentication also.
I've tried implementing this code Click here!
I was not successful.
I tried to implement user_id but it would also not work.
I added a puts statement and i can see its being hit but
no validation is occurring?
I tried to do some other things with no luck. I don't quite
understand where this is going sideways.
Please see my code below.
My wicked step controller
class AfterRegistrationController < ApplicationController
include Wicked::Wizard
layout 'noheaderOrfooter', :only => [:new, :show, :create, :update]
#before_action :authenticate_user!
steps :addCompanyInfo, :taxInformation, :achBankInfo, :finalstep
def show
#user = current_user
render_wizard
end
def update
#user = current_user
params[:user][:current_step] = step
case wizard_value(step)
when :addCompanyInfo
#user.update_attributes(company_params)
when :taxInformation
#user.update_attributes(tax_params)
when :achBankInfo
#user.update_attributes(bank_params)
else
#user.update_attributes(final_params)
end
render_wizard #user
end
def company_params
params.require(:user).permit(:CompanyLegName, :CompnayWebsite, :CompanyAddrss, :CompSuitOrApt, :City, :State, :ZipCode, :current_step)
end
def tax_params
params.require(:user).permit(:EINbr, :startdate, :NbrOfTrucks, :estpayroll, :City, :State, :ZipCode)
end
def bank_params
params.require(:user).permit(:BankName, :RoutNbr, :AcctNbr, :confirmAcctNbr)
end
def final_params
params.require(:user).permit(:CompanyLegName, :CompnayWebsite, :CompanyAddrss, :CompSuitOrApt, :City, :State, :ZipCode)
end
end
devise registration controller
def after_sign_up_path_for(resource)
after_registration_path(:addCompanyInfo)
end
user model
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :fname, :lname, :presence => true
validates :CompanyLegName, :CompanyAddrss, :CompSuitOrApt, :City, :State, :ZipCode, :presence => true, if: -> { current_step?(:addCompanyInfo) }
def current_step?(step_key)
current_step == step_key
puts 'I hit this method'
puts step_key
end
# Setup accessible (or protected) attributes for your model
#attr_accessible :email, :password, :password_confirmation, :remember_me, :fname, :lname, #:CompanyLegName, :CompanyAddrss, :CompSuitOrApt, :City, :State, :ZipCode, :Ownersfname, #:OwnersLname
#devise :database_authenticatable, :registerable,
#:recoverable, :rememberable, :trackable, :validatable
end
In my model i was comparing current_step which is a string to my step_key that was returning a parameter which would return false all the time i changed it to return a string which allowed me to compare current_step which is a string to step_key.to_s which is a string
below
def current_step?(step_key)
current_step == step_key.to_s
end

How to permit a new parameter in rails (devise) when implementing role based authorization

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.

Rails 4 Strong Parameters opposite permit all attributes

I am using rails 4 with strong parameters and trying to figure out how to set the strong parameters to not allow any attribute with the parameter.
I read this Rails 4 Strong parameters : permit all attributes? And would like to do the opposite of that.
params.require(:user).permit!
would permit all attributes, how could I do the opposite?
UPDATE THIS IS MY FULL CODE:
in app/controllers/application_controller.rb
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_filter :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) }
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:signin, :password, :remember_me) }
devise_parameter_sanitizer.for(:account_update) {|u| u.permit(:username, :email, :password, :password_confirmation, :current_password)}
devise_parameter_sanitizer.for(:sign_in) { |a| a.permit(:signin, :password, :remember_me) }
devise_parameter_sanitizer.for(:account_update) {|a| a.permit(:username, :email, :password, :password_confirmation, :current_password)}
end
end
in app/models/admin.rb
class Admin < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable, :registerable
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
attr_accessor :signin
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:signin)
where(conditions).where(["username = :value OR lower(email) = lower(:value)", { :value => login }]).first
else
where(conditions).first
end
end
validates :username, presence: true, length: {maximum: 255}, uniqueness: { case_sensitive: false }, format: { with: /\A[a-zA-Z0-9]*\z/, message: "may only contain letters and numbers." }
end
The users.rb model is the same as the admin.rb model. This leads to two different sign up/sign in links- 1 for each model. Also I need to leave the :registerable module so that I can override the default devise's registerable module. However I modified the views to not show the admin page when typed in a browser. --- I only need to block it via command line now.
I also have posted a previous question similar to this:
Rails 4 Devise Strong Parameters Admin Model
If you're not using any user-inputted parameters (like for a GET), you don't need to use params at all. Your controller will just work, and there won't be a security issue.
The default behavior is the opposite of .permit. If you don't mention an attribute in your params arguments, it is like denying the user access to do anything with those attributes.

Rails 4 + Devise 3.0.0 Adding Username

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

Resources