Rails: How to create a user that has a `belongs_to` association - ruby-on-rails

I am brand new to the world of rails so please forgive my ignorance with this question :)
I am currently setting up a new app that has two models:
Account
User
My seed file looks like this:
account = Account.create!(name: 'Account Name')
account.users.create!(
first_name: 'Test',
last_name: 'Test',
email: 'test#test.com,
password: 'test',
owner: true
)
And the users model is:
class User < ApplicationRecord
belongs_to :account
...
end
I have created a custom Devise registrations controller to let new users sign up:
class Users::RegistrationsController < Devise::RegistrationsController
# GET /sign_up
def new
render inertia: 'Auth/Register', props: {}
end
# POST
def create # rubocop:disable Lint/UselessMethodDefinition
super
end
def sign_up_params
params.require(:user).permit( :email, :password, :first_name, :last_name)
end
end
BUT! I need to pre-create an account for a user before I actually create the user here and this is something I have been stuck on for a few days with no luck (to the point I've considered changing the association's).
The error is:
Account must exist
Which makes sense because we don't have an account when we create a new user which is what i need to do before the user is registered.
My best guess was I needed to do something like:
# POST
def create
account = Account.create!(name: 'Test')
account.users.create!(sign_up_params)
end
to mimic the logic of the seeds file but this seems distinctly wrong to me and doesn't work.
So my question is, is it possible and how can I pre-create an Account model for a user and then associate it to the user in the registrations create method before the user is persisted to the database?
In my final production code, the goal would be to create an Account type that will be created and associated with a user on registration but for now just getting a very basic MVC up and running is the goal :)
Thank you so much in advance for any help!

First off, I think the account is supposed to belong to the user, not the opposite.
The user model User.rb should look like this:
has_one :account
And the account model Account.rb should look like this:
belongs_to :user
And to create an account once the user is created, you can simply add this line to your user model:
after_create :create_account
and the account will be created automatically.

What about using?
user = User.new(sign_up_params)
user.build_account(name: 'Test')
user.save!

The problem is the line belongs_to :account in User model.
I would suggest you break your User model in two models
User
UserDetails
You can then add belongs_to :account in UserDetails model.
This will help in independent creation of users, will not be affected by account.
Something like below.
class User < ApplicationRecord
has_one :user_detail
...
end
class UserDetails < ApplicationRecord
belongs_to :user
belongs_to :account
...
end
class Account < ApplicationRecord
has_many :user_details
...
end

Related

Rails 4 + Devise: After create user, create XYZ

I have a User model that gets created through Devise, and after it's creation, I would like to automatically create a new Client (another model in my app). The new Client's atrribute, :user_id, should be equal to the :id of the User that was just created. I believe I need to use something like:
class Users::RegistrationsController < Devise::RegistrationsController
after_create :create_client
def create_client
Client.create(:user_id, :id) # Not sure what should go here
end
end
Is this the correct way to accomplish this? Also, if associations are important Client belongs_to :user and User has_one :client
You can add an after_create callback in User model(user.rb), check here for more information on how to create has_one associations.
class User < ActiveRecord::Base
after_save :add_client
def add_client
self.create_client(client_attribute1: value, client_attribute2: value)
end
end

Creating a one-to-one relation

class User
has_one :super_admin
end
class SuperAdmin
belongs_to :user
end
How would I create a SuperAdmin instance associating a certain user, from withing the User model?
I'm looking for something like this (in the User model), but it's not working:
def promote_to_super
self.super_admin.create!
end
You can use create_association(attributes = {}):
def promote_to_super
self.create_super_admin
end
See more here.

Rails - Signup code validity check

So, I'm new at this and trying to learn by jumping right in.
I have a slightly odd login in my rails app that works like this:
Admins generate a code and specify an upper limit
Users log in by entering this code and some details which are saved
Models:
class Code < ActiveRecord::Base
has_many :users, dependent: :destroy
attr_accessible :code, :maxusers
end
class User < ActiveRecord::Base
belongs_to :code
attr_accessible :name, :email, :code_id
end
Users controller:
class UsersController < ApplicationController
def create
#user = User.new(params[:user])
if #user.save
redirect_to "/welcome"
end
end
end
So for example the code is 123456 with a limit of 5
The first 5 users can sign up with their Name, Email and 123456
So the question is: How do I check that the code is valid before saving? It must exist and have less than 5 users already assigned.
It seems really simple but I can't figure out the syntax, I was playing with a before_filter in the controller or before save in the model but I'm stuck.
before_filter is a bad idea: models have to bothered about their integrity, not controllers.
You can try something like:
# in your respective model
validate :at_least_five_codes
def at_least_five_codes
errors.add(:base, 'Try another code') unless User.where(code: code).count < 5
end
And you'll be unable to save your model if current code was used for 5 times.

Rails 3 and Devise: How to register an account and user in the registration page?

I need a registration page to record a new account that has user as a nested attribute. For example:
MODELS
class User < ActiveRecord::Base
belongs_to :account
validates :account_id, :presence => true
...
class Account < ActiveRecord::Base
has_many :users, :dependent => :destroy
accepts_nested_attributes_for :users
...
TABLES
accounts
id: 5
users
id: 32
email: someuser#gmail.com
account_id: 5
I know to override the registrations controller I have to do something like this...
class RegistrationsController < Devise::RegistrationsController
def new
super
end
def create
super
end
end
I have the Devise default registration page. But how can I register an account and a user that belongs to that account?
As it seems that your Devise resource is user, maybe you want to use nested attributes on users, instead of account.
Then, you will be able to do the registration using nested attributes and then assign an account with it.

How do I set ActiveRecord model attribute when using .build method with Rails 3.2 (many-to-many)

I'm working on a sort of project management app with Rails (my Rails skills is kinda rusty). I have two model objects, in this case User and Account, which have a many-to-many relationship (Company could maybe be a better name for Account). When a user signs up a new Account is created (with .build) with help form a nested form. The Account model have two fields name and account_admin. When the the initial user creates it's Account I want to set account_admin to the users id. But I can't get this to work.
The models is set up like this:
class Account < ActiveRecord::Base
attr_accessible :name, :account_admin
validates_presence_of :name
has_many :projects, dependent: :destroy
has_many :collaborators
has_many :users, through: :collaborators
end
class User < ActiveRecord::Base
has_secure_password
attr_accessible :email, :name, :password, :password_confirmation, :accounts_attributes
has_many :collaborators
has_many :accounts, through: :collaborators
accepts_nested_attributes_for :accounts
[...]
The UserController looks like this:
def new
if signed_in?
redirect_to root_path
else
#user = User.new
# Here I'm currently trying to set the account_admin value, but it seems to be nil.
account = #user.accounts.build(:account_admin => #user.id)
end
end
I have also tried to move account = #user.accounts.build(:account_admin => #user.id) to the create action, but the the field disappears from the form.
What would be the appropriate way to accomplish what I want (set account_admin to the users id when it is getting created)? Or is there a better approach to find out which user created the account (ie. do something with the relationship table)?
Update
With help from #joelparkerhenderson I think I got it to work. I made a method in my User model that looks like this:
def set_account_admin
account = self.accounts.last
if account.account_admin == nil
account.account_admin = self.id
account.save
end
end
Which I call with after_create :set_account_admin. This works, but is there a more "Rails way" to do the same?
Thanks.
When you call #new, the user doesn't have an id yet (it is nil).
When you #save the user, Rails automatically gives the user a new id.
You can then use the after_create Active Record callback to set the new Account's account_admin

Resources