Ruby on rails new object properties - ruby-on-rails

i need to add to my user new objet some new properties that i will define when the form is submited by retrieve them from my database, but when i submited the new properties are nill and i dont know why
def create
plan = params[:user][:plan]
#plan_vars = Plan.find(plan)
#user = User.new(user_params, :plan_id => #plan_vars.id, :lessons => #plan_vars.lessons)
if #user.save
flash[:success] = "Usuario creado exitosamente"
redirect_to users_path
else
flash[:warning] = "Ooops... algo ha fallado :O #{#user.errors}"
redirect_to new_user_path
end
end
here is the user params
def user_params
params.require(:user).permit(:name, :email, :phone, :document, :password,
:password_confirmation)
end

Here is what to do?
Do this:
#user = User.new(user_params)
#user.plan_id = #plan_vars.id
#user.lessons = #plan_vars.lessons
#user.save
if nested form is used or #plan_vars returns array there results another type of error

You can merge plan params to user_params hash
def user_params
params.require(:user).permit(:name, :email, :phone, :document, :password,
:password_confirmation)
.merge(plan_id: #plan_vars.id, lessons: #plan_vars.lessons)
end
def create
plan = params[:user][:plan]
#plan_vars = Plan.find(plan)
#user = User.new(user_params)
end
Hope, that helps!

I prefer something similar to #Lavika's answer, but with merge on create action
def create
plan = params[:user][:plan]
#plan_vars = Plan.find(plan)
#user = User.new(user_params.merge(plan_id: #plan_vars.id, lessons: #plan_vars.lessons))
# ...
end
#pradeep sapkota's answer is also a good option

Related

Why am I getting an undefined method `deep_merge' for ActionController::Parameters error?

In my Rails 5 app I am trying to do this in a controller:
def create
company_params = params.require(:company).permit(
:name,
:email,
:people_attributes => [
:first_name,
:last_name
]
).deep_merge(
:creator_id => current_user.id,
:people_attributes => [
:creator_id => current_user.id
]
)
#company = current_account.companies.build(company_params)
if #company.save
flash[:success] = "Company created."
redirect_to companies_path
else
render :new
end
end
For some reason I am getting this error, though:
undefined method `deep_merge' for ActionController::Parameters:0x007fa24c39cfb0
What am I missing here?
What am I missing here?
That params is an instance of ActionController::Parameters. It is not a Hash. It has some merge methods, though.
params.methods.grep(/merge/)
=> [:reverse_merge!, :reverse_merge, :merge!, :merge]
If you want deep_merge, convert your params to a hash in some way.
Even though modifying params in the request cycle is not a good practice, but if you want to do that, there's always a .to_hash.deep_merge option for you to retrieve the hash back from params instance.
OK, I couldn't get deep_merge to work, so I ended up doing this:
def create
company_params = params.require(:company).permit(
:name,
:email,
:people_attributes => [
:first_name,
:last_name
]
)
#company = current_account.companies.build(company_params)
#company.creator = current_user
#person = #company.people.last
#person.account = current_account
#person.creator = current_user
if #company.save
flash[:success] = "Company created."
redirect_to companies_path
else
render :new
end
end
Not sure if this is good or bad practice. Feedback appreciated!

ActionController::ParameterMissing (param is missing or the value is empty: name):

While implementing what I thought was a simple signup/login system for a Ruby on Rails app, results haven't matched what tutorials have shown.
I'm trying to use bcrypt for authentication and PostgreSQL for the database.
I continually get 'ActionController::ParameterMissing (param is missing or the value is empty: name): ', even though it will show name as being input. '"users"=>{"name"=>"asdf", "password"=>"Qq!1asdfasdf", "password_confirmation"=>"Qq!1asdfasdf"}, "commit"=>"Submit"} (0.1ms)
output from the console when attempting to sign in
users controller
class UsersController < ApplicationController
def new
end
def create
user = User.new(
name: params[:name],
password: params[:password],
password_confirmation: params[:password_confirmation])
if user.save
session[:user_id] = user.id
redirect_to '/'
else
redirect_to '/signup'
end
end
private
end
The table
class UsersController < ApplicationController
def new
end
def create
user = User.new(
name: params[:name],
password: params[:password],
password_confirmation: params[:password_confirmation])
if user.save
session[:user_id] = user.id
redirect_to '/'
else
redirect_to '/signup'
end
end
private
end
and the signup form
class UsersController < ApplicationController
def new
end
def create
user = User.new(
name: params[:name],
password: params[:password],
password_confirmation: params[:password_confirmation])
if user.save
session[:user_id] = user.id
redirect_to '/'
else
redirect_to '/signup'
end
end
private
end
the user model
class User < ActiveRecord::Base
PASSWORD_FORMAT = /\A
(?=.{10,}) # Must contain 10 or more characters
(?=.*\d) # Must contain a digit
(?=.*[a-z]) # Must contain a lower case character
(?=.*[A-Z]) # Must contain an upper case character
(?=.*[[:^alnum:]]) # Must contain a symbol
/x
#formatting for password
USERNAME_FORMAT = /\A[a-z0-9A-Z\-_]{2,15}\z/ #Can contain lowercase and upercase letters, numbers, - and _, must be between 2 and 15 length
#username formatting
validates :name,
:presence => true,
:uniqueness => true,
:format => USERNAME_FORMAT
validates :password,
:presence => true,
:format => PASSWORD_FORMAT,
:confirmation => true,
:on => create
has_secure_password
end
I've tried troubleshooting, all similar questions haven't yielded an answer or fix.
EDIT: More clarity on issue
You need to use rails Strong Parameter like the following
class UsersController < ApplicationController
def new
end
def create
user = User.new(user_params)
if user.save
session[:user_id] = user.id
redirect_to root_path
else
redirect_to new_user_path
end
end
private
def user_params
params.require(:user).permit(:name, :password, :password_confirmation)
end
end
I think it's a problem of passing data between your form and your controller.
In your logs your parameters for user looks like: "users"=>{"name"=> ...} but it should be "user"
To pass data between your controller and your view, you need to use instance variable such as #user to make the new instance of User available in the view. (source)
In that way your controller should be:
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
redirect_to '/'
else
redirect_to '/signup'
end
end
private
def user_params
params.require(:user).permit(:name, :password, :password_confirmation)
end
(with strong parameters like #fool-dev explained)
Then in your view, use this #user to pass the parameters to the controller:
<%= form_for #user do |f| %>
//...the form
<% end %>

Limiting which user attributes can be updated

I do not want to allow the user to update their :name. I found this question for Rails version 3 but the answer does not work for me. I am using Rails 4. I might just have the wrong syntax. I couldn't get #user.update_attributes(params[:user]) to work. Only: #user.update_attributes(user_params). I am not including :name on my edit form, but my understanding (??) is that a user could still pass it through the browser themselves and with my current code they could change :name.
class UsersController < ApplicationController
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
#user.update_attributes(user_params)
if #user.save
flash[:success] = "Profile updated"
redirect_to #user
else
flash[:danger] = "Profile update Unsuccessful"
redirect_to 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :email_confirmation, :password, :password_confirmation)
end
There's more than one way to assure users won't tamper with your business rules.
As you're already using Rails 4, you can take advantage of strong parameters to deny access to the :name attribute.
You can have different sets of rules for each controller action:
def create_user_params
params.require(:user).permit(:name,:email, :email_confirmation, :password, :password_confirmation)
end
def update_user_params
params.require(:user).permit(:email, :email_confirmation, :password, :password_confirmation)
end
#user.create(create_user_params)
#user.update_attributes(update_user_params)
drying up:
def allowed_update_attrs
[:email, :email_confirmation, :password, :password_confirmation]
end
def allowed_create_attrs
allowed_update_attrs + [:name]
end
def user_params
params.require(:user)
end
#user.create user_params.permit(*allowed_create_attrs)
#user.update_attributes user_params.permit(*allowed_update_attrs)
There are other ways of accomplishing the same thing like tapping into already permitted attributes, but this way seemed simpler.

How to create new User with an Organization association

In my webapp my User Signup page has an Organization Name field. I have an Organization model that has_many :users, and my User model belongs_to :organization. When a new user is created, I'd like for the Organization Name value to be used to create a new organization record, and associate it with the user, such that user.organization_id = the new organization id.
This is my users_controller.rb code:
class UsersController < ApplicationController
def new
#user = User.new
end
def show
#user = User.find(params[:id])
#organization = Organization.find(#user.organization_id)
end
def create
#organization = Organization.new(organization_params)
#user = User.new(user_params)
if #user.save && #organization.save
sign_in #user
redirect_to #user
flash[:success] = "Welcome to the App!"
else
flash.now[:danger] = "Uh oh, there's been an error"
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
def organization_params
params.require(:organization).permit(:name)
end
end
Right now both the user record and organization record are being created when a user submits the signup form, but the association is not saved. The user.organization_id value is nil.
Can you comment on what's wrong, and if there's a good way to do what I'm going for -- maybe with .build?
Thanks!
Brennan
Yes! .build will work, but because its a single association back, you will be using the association name in your build command, ie build_organization
def create
#user = User.new(user_params)
#user.build_organization(organization_params)
if #user.save
blah blah blah
You only need to save the user (not #organization) if done this way because the association is taken care of.
At user_params permit :organization_id ;)
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation, :organization_id)
end
EDIT: You also need to set organization_id somewhere for user - if you're not doing it in form (like with select or some else field) you can use .build method.

NoMethodError in Login#new

This is my controller for the app.
private
def app_params
params.require(:login).permit(:name, :surname, :username, :password, :email)
end
def new
#login = Login.new app_params
unless app_params.nil?
#login.save
end
end
def show
#post = Post.find(params[:id])
end
def create
#login = Login.new(params[:login])
if #login.save
flash[:success] = "Saved"
redirect_to root_path
else
render "new"
end
end
Code for the new_login_path is:
<%= form_for Login.new do |f| %>
so on..
The error message it shows is:
undefined method `logins_path' for #<#:0x007fba3824be28>
The logins_path method should be generated automatically by Rails based on the contents of your config/routes.rb file. Do you have a line like this?
resources :logins
After you fix your routing issue, you'll want to move your action methods above the private declaration as in Manoj Monga's answer.
You need to define the action above private. every method you define below private is treated as private method. while the controller actions need to be publicly accessible. So Define the action above the private keyword.
def new
#login = Login.new app_params
unless app_params.nil?
#login.save
end
end
def show
#post = Post.find(params[:id])
end
def create
#login = Login.new(params[:login])
if #login.save
flash[:success] = "Saved"
redirect_to root_path
else
render "new"
end
end
private
def app_params
params.require(:login).permit(:name, :surname, :username, :password, :email)
end

Resources