I'm working on a Ruby on Rails project and I have two models:
1. User
2. Merchant
their relationships are:
User has_one :merchant
Merchant belongs_to :user
then in my user.rb
attr_accessor :merchant_name
after_create :create_merchant
def create_merchant
create_merchant(name: merchant_name)
end
In my user's form:
= form_for #user do |f|
= f.text_field :merchant_name
= f.text_field :email
= f.text_field :password
the problem is the user and a merchant has been created but the merchant's name is nil
In my Account::RegistrationsController
class Account::RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
account_users_path
end
private
def registration_params
params.require(:user).permit(:merchant_name)
end
end
I'm getting this error:
Processing by Account::RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ht8vHG8I4bz2ylt+mtLC7hilQnK3VnYtcHgSNv8nSeg=", "user"=>{"merchant_name"=>"Zara 123", "email"=>"allen.chun#hotmail.com",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign Up"}
Unpermitted parameters: merchant_name
I wouldn't override the create_merchant method if I were you, try something like this:
after_create -> { create_merchant!(:name => self.merchant_name) }
and make sure your merchant_name is permitted in the users controller, something like this:
def create
#user = User.new(user_params)
if #user.save
redirect_to #user
else
render :new
end
end
private
def user_params
params.require(:user).permit(:merchant_name, :email, :password, :password_confirmation)
end
Perhaps it should be
attr_accessor :merchant_name
after_create :create_merchant
def create_merchant
build_merchant(name: merchant_name)
save
end
create_association hasn't supported in rails 4
Also don't forget to permit merchant_name. According to this info:
class Account::RegistrationsController < Devise::RegistrationsController
before_action :configure_permitted_parameters
protected
def after_sign_up_path_for(resource)
account_users_path
end
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :merchant_name
end
end
Related
One thing that confuses me the most is when doing validation in one model with two controllers. I have a login system which register and logs users in. There both use the same model but both does not use the same amount of HTML widgets. One controller contains password, retype password, user name, first & second name and so on. The second controller uses only the user name and password fields. How would you do validation in the same model for this situation?
Thank you
here is the controller that register new users:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
redirect_to '/cool'
else
#user = Newuser.new
#user.valid?
#user.errors.messages
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :salt, :firstname, :secondname, :address, :postcode)
end
end
second controller:
class LoginsController < ApplicationController
before_filter :authorize
def index
#rentals = Rental.where(user_id: current_user.id).limit(5)
#buys = Buy.where(user_id: current_user.id).limit(5)
#users = User.where(id: current_user.id)
#buyGames = BuyGame.where(user_id: current_user.id).limit(5)
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to '/logout'
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update(account_params)
redirect_to '/cool'
else
render 'edit'
end
end
private
def account_params
params.require(:user).permit(:name, :email, :password, :salt, :firstname, :secondname, :address, :postcode)
end
end
Here is my model:
class User < ApplicationRecord
has_secure_password
end
One way to go is to remove validations from the model and put them in form objects. For this case, you'll have two form objects, each with its own set of validations. And you use the appropriate one in respective controllers. Something along these lines:
# logins_controller
def update
login_form = FormObjects::LoginForm.new(login_params)
if login_form.valid?
redirect_to '/cool'
else
render 'edit'
end
end
# users controller
def create
signup_form = FormObjects::SignupForm.new(user_params)
if signup_form.save
redirect_to '/cool'
else
render 'new'
end
end
# signup_form
module FormObjects
class SignupForm
include ::ActiveMode::Model
validate_presense_of :email, :password, :password_confirmation, :address, :whatever_else
def save
# create user here
end
end
end
# login_form
module FormObjects
class LoginForm
include ::ActiveMode::Model
validate_presense_of :email, :password
end
end
You can simply specify validations on actions, that is:
validates :first_name, presence: true, on: :create # which won't validate presence of first name on update or any other action
I believe the trick you are looking for is to define validation actions on create/update of the model. Something roughly along these lines:
class User < ActiveRecord::Base
# These are example validations only; replace with your actual rules.
validates :password, confirmation: true
validates_presence_of :username
validates :first_name, presence: true, format: {with: /.../}, on: create
validates :last_name, presence: true, format: {with: /.../}, on: create
end
...However, I am unclear why you would want to do this in your specific example. It would be advisable to always run all validation checks on fields like first_name, to help maintain data integrity.
I have been stuck up with this exception.I am using rails 4.2.5.1 and ruby 2.3.0. I am creating a model using devise in rails. I have override the devise create method. I am getting error in postgres as PG::NotNullViolation: ERROR: null value in column "id" violates not-null constraint.I want the ID to be created with the help of parameters i am passing. ID is not getting created. As am new to rails am getting stuck up for hours now.
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"SAiVJEULEa7RsieW+OTW1a/946f2xVbhA/sZWWn3KdX1Wt0Ozx+tq6eQfhTpaAJ+4Cxu2DMnPfqd0Vcle7ow0w==",
"employee"=>{"email"=>"safi123#gmail.com",
"first_name"=>"sss",
"last_name"=>"dddnjnfj",
"phone_number"=>"9944253677",
"alternative_phone_number"=>"9659392682",
"alternative_email_id"=>"dd#gmail.com",
"date_of_joining"=>"12-02-2015",
"date_of_birth"=>"03-02-1999",
"status"=>"Active",
"gender"=>"M",
"blood_group"=>"A +"},
"commit"=>"Sign up"}
Application Controller:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_employee!
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |employee_params|
employee_params.permit :first_name, :last_name, :blood_group, :phone_number, :gender, :date_of_birth, :email, :alternative_email_id, :status, :date_of_joining, :alternative_phone_number
end
devise_parameter_sanitizer.for(:account_update) do |employee_params|
employee_params.permit :first_name, :last_name, :blood_group, :phone_number, :gender, :date_of_birth, :email, :alternative_email_id, :status, :date_of_joining, :alternative_phone_number
end
end
end
Registrations Controller
class RegistrationsController < Devise::RegistrationsController
def new
super
end
def index
#employees = Employee.all
end
def create
#employee = Employee.new(employee_params)
if #employee.save
redirect_to :action => :new
else
render 'new'
end
#employee.save
end
# Never trust parameters from the scary internet, only allow the white list through.
def employee_params
params.require(:employee).permit(:first_name, :last_name, :blood_group, :phone_number, :gender, :date_of_birth, :email, :alternative_email_id, :status, :date_of_joining, :alternative_phone_number)
end
def update
super
end
end
Database schema :
I can understand the ID is not generated and it is not stored in the database. What is the problem here? Can anyone explain me what is the mistake am making?
You are saving the employee record twice. That may be the problem, please save only once.I have given the action please check.
def create
#employee = Employee.new(employee_params)
if #employee.save
redirect_to :action => :new
else
render 'new'
end
/* Here you had saved again. */
end
Your Employee params,
def employee_params
params.require(:employee).permit(:first_name, :last_name, :blood_group, :phone_number, :gender, :date_of_birth, :email, :alternative_email_id, :status, :date_of_joining, :alternative_phone_number)
end
Now you will get the id through params and it will be saved.
So I have a User model generated with devise, and I am using Wicked gem to give me multiform option on taking more data from the user and storing it in the user model.
Everything is working fine but know I'm trying to add another model where user has many degree. I am using cocoon gem to allow me to add extra degrees. I am able to go to the multiform page and enter degree information and even add many more degrees to the user, but when i submit the form i get an error;
param is missing or the value is empty: user
Everything else actually gets saved am i can view the user and the rest of the fields entered but non of the degrees.
user model:
has_many :degrees
accepts_nested_attributes_for :degrees, reject_if: :all_blank, allow_destroy: true
degree model:
belongs_to :user
user_steps_controller (this is the wicked gem controller):
class UserStepsController < ApplicationController
include Wicked::Wizard
steps :personal, :avatar_and_about_yourself, :social, :education
def show
#user = current_user
render_wizard
end
def update
#user = current_user
#user.update_attributes(user_params)
render_wizard #user
end
private
def user_params
params.require(:user).permit(:name, :middlename, :lastname, :avatar, :aboutMe, :twitterlink, :githublink, :stackoverflowlink, :mediumlink, :dribblerlink, degrees_attributes: [:id, :degreeName, :university, :level, :done, :_destroy])
end
end
Registration controller (for devise):
class Users::RegistrationsController < Devise::RegistrationsController
# before_filter :configure_sign_up_params, only: [:create]
# before_filter :configure_account_update_params, only: [:update]
# GET /resource/sign_up
def new
super
end
# POST /resource
def create
super
end
# PUT /resource
def update
super
end
protected
# The path used after sign up.
def after_sign_up_path_for(resource)
user_steps_path
end
# The path used after sign up for inactive accounts.
def after_inactive_sign_up_path_for(resource)
user_steps_path
end
def sign_up_params
params.require(:user).permit(:email, :password, :password_confirmation, :name, :middlename, :lastname, :avatar, :aboutMe, :twitterlink, :githublink, :stackoverflowlink, :mediumlink, :dribblerlink, degrees_attributes: [:id, :degreeName, :university, :level, :done, :_destroy])
end
end
Im getting an error in the user_steps_controller:
ActionController::ParameterMissing in UserStepsController#update
param is missing or the value is empty: user
and that the error is within this line:
def user_params
params.require(:user).permit(:name, :middlename, :lastname, :avatar, :aboutMe, :twitterlink, :githublink, :stackoverflowlink, :mediumlink, :dribblerlink, degrees_attributes: [:id, :degreeName, :university, :level, :done, :_destroy])
end
Also how would i go and view the entered fields, for example if i wanted to view user name it is:
<%= #user.name %>
but how would i show each degree? is it just a loop?
<% #users.degree.each do |degree| %>
Terminal log:
Started PATCH "/user_steps/education" for ::1 at 2016-02-09 11:23:29 +0000
Processing by UserStepsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"EXN7ts6xPVK8vkC7q6UcNleJJWLUtKmOw41T0qsDqXCrPJ0vIHrB/6xIfpp/o+cXKR47F+6LxUY5LjXlCobKZQ==", "commit"=>"Update User", "id"=>"education"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 16]]
Completed 400 Bad Request in 2ms (ActiveRecord: 0.2ms)
ActionController::ParameterMissing (param is missing or the value is empty: user):
app/controllers/user_steps_controller.rb:20:in `user_params'
app/controllers/user_steps_controller.rb:13:in `update'
This is too long to comment, I fully expect to update it.
The problem you have is that your form submission does not include any user params:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"EXN7ts6xPVK8vkC7q6UcNleJJWLUtKmOw41T0qsDqXCrPJ0vIHrB/6xIfpp/o+cXKR47F+6LxUY5LjXlCobKZQ==", "commit"=>"Update User", "id"=>"education"}
This might be Wicked, but judging form your spurious use of RegistrationsController, I'd imagine it could be to do with formatting etc:
--
If you're updating your current_user, you should not be invoking your registrations controller. That is for registrations -- you should be using your users controller:
#config/routes.rb
resource :user_steps, path: "user", only: [:show, :update] #-> url.com/user (singular resource)
#app/controllers/user_steps_controller.rb
class UserStepsController < ApplicationController
def show
end
def update
#user = current_user.update user_params
render_wizard #user
end
private
def user_params
params.require(:user).permit(:name, :middlename, :lastname, :avatar, :aboutMe, :twitterlink, :githublink, :stackoverflowlink, :mediumlink, :dribblerlink, degrees_attributes: [:id, :degreeName, :university, :level, :done, :_destroy])
end
end
This is just the controller; you need to look at how the form is being rendered & passed.
If you're sending data with the above code, you'll want to pull your form HTML and show how Wicked is working with it.
You need to be looking in app/views/users/show.html.erb for the form to display, not /app/views/registrations
I created a project in Ruby On rails and I have controller user like this:
class UsersController < ApplicationController
before_action :set_user, only: [:edit, :update]
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to root_url, :notice => "Signed up!"
else
render "new"
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
And model user like this:
class User < ActiveRecord::Base
#attr_accessible :email, :password, :password_confirmation
attr_accessor :password
before_save :encrypt_password
def self.authenticate(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
end
And when I try to create new user i get Error: ActiveModel::ForbiddenAttributesError
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"74Mhbpn9FF/tY/cgfuVmX7ribN4rOkkdUjSgbLNsces=",
"user"=>{"email"=>"henio180#interia.pl",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]"},
"button"=>""}
I am using Ruby on Rails 4.0.3.
In your create method change:
#user = User.new(params[:user])
to
#user = User.new(user_params)
Although you created the method correctly to set up strong parameters, you are not actually using it. There is good detail about using strong parameters in the Rails guide: http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters
I receive the following error even though I have the fields to be updated in attr_accessible
Can't mass-assign protected attributes: utf8, _method, authenticity_token, profile, commit, action, controller, id
I'm guessing the other attributes that I don't want to save are raising the exception, but how can I filter them out?
this is the params hash
{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"1aabj2DxleZoDu/U0SzGXSZrPcesRKXkIXTRVbk9f0A=",
"profile"=>{"name"=>"Aaron Dufall",
"company"=>"Supreme Windows",
"location"=>"",
"professional_bio"=>""},
"commit"=>"Update",
"id"=>"1"}
profiles_controller.rb
class ProfilesController < ApplicationController
respond_to :html
def edit
#profile = Profile.find(params[:id])
respond_with #profile
end
def update
#profile = Profile.find(params[:id])
if #profile.update_attributes(params)
flash[:success] = "Profile sucessfully updated"
redirect_to root_path
else
flash[:error] = "Profile failed to update"
render 'edit'
end
end
end
profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
attr_accessible :name, :company, :location, :professional_bio
end
In your controller you should use
if #profile.update_attributes(params[:profile])
This will filter only the attributes which are under "profile" key on params.
You may want to consider using :without_protection - It will skip mass-assignment security.
Ie:
User.new({ :first_name => 'Jamie', :is_admin => true }, :without_protection => true)
re: http://apidock.com/rails/ActiveRecord/Base/new/class