How do I update attributes of a nested model? - ruby-on-rails

I have a company model, that accepts_nested_attributes_for :users and my controller looks like this:
def create
#company = Company.new(company_params)
if #company.save
redirect_to root_url
else
render 'new'
end
end
private
def company_params
params.require(:company).permit(:name, :company_size , users_attributes: [:id, :name])
end
what I'd like to do is set the admin boolean I have in user to true.
Essentially what I'm doing is making a user sign up by creating a company, and also registering their user, and thus making the person registering the company an admin.

You can simply alter the User object before it is saved.
def create
#company = Company.new(company_params)
#company.user.admin = true
if #company.save
redirect_to root_url
else
render 'new'
end
end
You could also do this as a a model callback. However your implementation might be a little to naive. What happens if a user belongs to several companies?

Related

Rails 4 Set Value of the logged in User by default before create

I have the following models
members (id, name, company_id..)
companies (id, name, ...)
campaigns (id, company_id, ...)
When creating a Campaign i have the following
def create
#campaign = Campaign.new(campaign_params)
if #campaign.save
redirect_to campaigns_path(#campaign)
else
render :new
end
end
i have a helper method from the AppController called current_company whose id i want to set to #campagin.company_id
which is the best way to set the default logged in users company.id to every campaign created?
can i traverse through current_company and build a query like this?
#campaign = current_company.campaign.new(campaign_params)
You can use before_create callback in model for your goal:
before_create :set_default
private
def set_default
self.campaign_id ||= your_default_id
end
Or you can do same thing it in your controller directly:
def create
campaign_params[:company_id] ||= default_company_id
#campaign = Campaign.new(campaign_params)
if #campaign.save
redirect_to campaigns_path(#campaign)
else
render :new
end
end

Nested form validation rails 3.2

I have a job and user(devise) form in the same view. When I am trying to submit with errors in the user fields it gives me an exception page with the validation messages. Submitting errors in the job fields works fine!
job_controller.rb
def new
#job = Job.new
if !current_user
#job.user = User.new
end
respond_to do |format|
format.html # new.html.erb
end
end
def create
#types = Type.all
#categories = Category.all
#job = Job.new(params[:job])
#if not logged in creates a user and sign in
if !current_user
#user = User.new(params[:job][:user_attributes])
else
#user = current_user
end
#job.user_id = #user.id
respond_to do |format|
if #job.save
if !current_user
sign_in(:user, #user)
end
format.html { redirect_to #job }
else
format.html { render action: "new" }
end
end
end
job.rb
attr_accessible :user_attributes, :description, :name ....
belongs_to :user
accepts_nested_attributes_for :user
Thanks!
That becuase you are calling, #user.save! which will generate an exception. Also doing it this way won't put the job in the same transaction as User. What you want are nested_attributes:
class Job < ActiveRecord::Base
accepts_nested_attributes_for :user
end
If the user is logged in, don't show that part of the form and filter those params.
See more in the Rails documentation here http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
EDIT:
Simplify your controller code, since you're using nested attributes you no longer need to manually create a user.
#if not logged in creates a user and sign in
if !current_user
#user = User.new(params[:job][:user_attributes]) # this is no longer needed
else
#user = current_user
end
#job.user_id = #user.id # this is redundant
To something more like:
# if logged in, manually assign the user (also you may want to reject any user attributes)
#job.user = current_user if current_user

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.

converting the methods for a has_many association to a has_one association

I have 2 models, users, and common_apps.
users has_one :common_app.
Before this, I wrote the code as the users has_many common_apps, however I'm not sure how to rewrite that for a has_one association. The main confusion is how to structure 'new' in common_app controller.
When I try, I get an undefined method error.
undefined method `new' for #<CommonApp:>
This is my code -->
def new
if current_user.common_app.any?
redirect_to current_user
else
#common_app = current_user.common_app.new
end
end
def create
#common_app = current_user.common_app.build(common_app_params)
if #common_app.save
flash[:success] = "Common App Created!"
redirect_to root_url
else
redirect_to 'common_apps/new'
end
end
def show
#common_apps = current_user.common_app
end
how would you restructure this, if this were to be a has_one association?
I think I know how the 'create' one should be -->
def create
#common_app = current_user.build_common_app(common_app_params)
if #common_app.save
flash[:success] = "Common App Created!"
redirect_to root_url
else
redirect_to 'common_apps/new'
end
end
Your new action should look like this:
def new
if current_user.common_app.present?
redirect_to current_user
else
#common_app = current_user.build_common_app
end
end
You can also call build_common_app without any parameters passed to it, which will initialize an empty CommonApp for current_user.

before_destroy in rails, little help need!

i have table called users, if i want to delete some user (User can add questions and add respondents (who will answer on his questions)), i need to delete him and get his id to people who deleted this person. So for example:
Sure.
def destroy_and_transfer_to(user)
transaction do
questions.each do |q|
q.update_attribute(:user_id => user)
end
respondents.each do |r|
r.update_attribute(:user_id => user)
end
destroy
end
end
Now use this method instead of the "destroy" method.
OR
you can stick to callbacks like this
before_destroy :transfer_to
attr_accessor :user_who_takes_over
private
def transfer_to
if user_who_takes_over
questions.each do |q|
q.update_attribute(:user_id => user_who_takes_over)
end
respondents.each do |r|
r.update_attribute(:user_id => user_who_takes_over)
end
end
end
Then you can :
#user.user_who_takes_over = current_user
#user.destroy
Just a couple of ideas! Good Luck!
Update: All the code i provided above belongs in your model.
In your controller you need to have a destroy method
in your controller
def destroy
user = User.find(params[:id])
user.user_who_takes_over = current_user
if user.destroy
flash[:notice] = "User destroyed, all stuff transferred"
else
Rails.logger.debug(user.errors.inspect)
flash[:error] = "Error destroying user"
end
redirect_to :back
end
Change to suite your need of course!

Resources