Rails create a user and a belongs_to model during sign up - ruby-on-rails

I want that when the user sign up (Devise) it create its first "Profile" account at the same time of registration form.
I tried with "fields_for" but it's not working. I can add an hidden_field in the registration form because the "user" is not created yet.
How can I do?
Model
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable,
:trackable
class Profile < ApplicationRecord
belongs_to :user #creator
Views (Sign up)
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.fields_for :profiles, resource.profiles.build do |s| %>
<%= s.text_field :name%>
<% end %>
<% end %>

You could have a call back in the model.
Like after_save and then create a profile.
You can look up callbacks here: https://guides.rubyonrails.org/active_record_callbacks.html#available-callbacks
And it could look like this:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable,
:trackable
after_save :create_profile
def create_profile
Profile.create(user: self,...)
end
end
Another option would be to generate a devise controller yourself. You can follow the steps from their readme: https://github.com/plataformatec/devise/wiki/Tool:-Generate-and-customize-controllers
And as they suggest, tweak the create method, by adding
Profile.new(...)
def create
super #inherits from devise controllers and create the user model
# now you can add your own code creating the Profile
Profile.new(user: resource, ...)
end

Related

How can i get separate tables for manager , owner , visitor as i am using rolify gem?

I am new to stackoverflow and i want to implement user with multiple roles .
I had started with rolify gem . I had generated 3 devise users manager , owner , user (visitor).
Association used for my application is
class Role < ApplicationRecord
has_and_belongs_to_many :users, :join_table => :users_roles
belongs_to :resource,
:polymorphic => true,
:optional => true
validates :resource_type,
:inclusion => { :in => Rolify.resource_types },
:allow_nil => true
scopify
end
class User < ApplicationRecord
rolify
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
after_create :assign_default_role
def assign_default_role
self.add_role(:visitor) if self.roles.blank?
end
end
class Owner < User
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
after_create :assign_default_role
def assign_default_role
self.add_role(:owner) if self.roles.blank?
end
end
class Manager < User
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
after_create :assign_default_role
def assign_default_role
self.add_role(:moderator) if self.roles.blank?
end
end
My concern is i am using rolify gem to assign role but i want to keep manager , owner , visitor table separate but if i didn't use Single table inheritance then how can i able to implement roles and keep table separate

Rails undefined method ReactJS

I am getting an error on my application undefined method 'preference' for #<User:0x007fb3cc1c3b80>. Following were my accounts controller:
class AccountsController < ApplicationController
before_action :authenticate_user!
def edit
#render html: 'Edit your account'
render component: 'AccountsEdit', props: {
preference: PreferenceSerializer.new(current_user.preference)
}, tag: 'div'
end
def update
#preference = current_user.preference
if #preference.update_attributes(preference_params)
render json: { data: 'SUCCESS!' }
else
render json: { data: 'FAIL!' }
end
end
private
def preference_params
params.require(:preference).permit(:display_name, :notify_on_answer, :daily_digest)
end
end
And my User and Preference model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
class Preference < ActiveRecord::Base
belongs_to :user
end
Seems all look alright, but i keep getting the same error. Am i missing something here? Thanks!!
Inside your User model add the relation to the Preference model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_a: :preference # Or has_many: :preferences
end

Create a customer from Devise User

How can I create a customer class I want to be a Devise User with a role = 1.
I have my User model:
class User < ActiveRecord::Base
enum role: [:user, :customer, :admin, :producer]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :user
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable, :registerable
devise :invitable, :database_authenticatable, :confirmable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
And my Customer model
class Customer < User
end
I can specify in the customersController what is a customer like this :
# GET /customers
def index
#customers = Customer.where(:role => 1).page(params[:page])
end
But How can I modify my Customer model to self know he is a User with role = 1 so I can only get my Customers like this :
#customers = Customer.all
if you exactly need Customer.all you should looking for STI(single table inheritance) which already resolve what you trying to do

Changing Model associations after running migration

I have a Devise User model with the following contents for which I did run migration.
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :token_authenticatable, :confirmable, :lockable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :role
# attr_accessible :title, :body
ROLES = ['admin', 'network/system admin', 'manager', 'programmer']
def role?(base_role)
ROLES.index(base_role.to_s) <= ROLES.index(role)
end
end
later on , I added the below two lines to the same model and run migration for Ticket, Projects and Assignments.
has_many :projects, :through => :assignments
has_many :tickets
Does the above update the association of user with the Tickets and Projects? Is there any problem in changing associations in model after running migration for the same? I want to know it as I am developing a Rails app now.
Thanks :)-
You should also have association...
has_many :assignments
in your user model.
no other updation is required.

Is it possible to load Devise in an external module?

I am using Devise in Rails 3, and have a User model in rails that is starting to get kinda crowded.. so I would like to put all of the login meethods inside of a module and include them from my model. I'm trying something like:
app/model/user.rb
class User < ActiveRecord::Base
include UserImageable
extend Loginable
has_one :profile, :dependent => :destroy
has_many :items, :dependent => :destroy
has_many :products, :through => :items
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :phone_number, :location, :photo, :profile_attributes, :access_token
delegate :first_name, :last_name, :phone_number, :phone_number=, :location, :location=, :photo, :to => :profile
accepts_nested_attributes_for :profile
end
and
lib/autoloads/loginable.rb
module Loginable
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable
def password_require?
new_record?
end
end
but the server doesn't seem to like that, as it loads with a NoMeethodError
loginable.rb:4:in `<module:Loginable>': undefined method `devise' for Loginable:Module (NoMethodError)
Is there a way to do what I'm shooting for, or not really?
Thanks
This is not the answer you are looking for but, here is my 2 cents: You shouldn't put all that stuff in the User model. devise models have a clear responsibility: signing.
But if you really want to put everything hooked in User.rb, you can split the model in extensions (partially enabling DCI):
Add that to your lib/models/{modelname}/devise_ext.rb
module Models
module User
module DeviseExt
extend ActiveSupport::Concern
included do
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable
end
module ClassMethods
end
module InstanceMethods
def password_require?
new_record?
end
end #InstanceMethods
end
end
end
Then, you just add it into your model:
include Models::User::DeviseExt
In the app we have in my company we actually have no code at all in models, we put everything in extensions.
I've not used Devise yet, but try this:
module Loginable
def self.included(base)
base.send :devise, :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable
end
def password_require?
new_record?
end
end
and in your model, include rather than extend:
class User < ActiveRecord::Base
include Loginable
end
This is an old question, but answers here didn't help me with Rails 4.2.
The problem is that when you define instance methods inside a module and include it into User model, they actually get defined on that instance.
But they don't override same methods in devise itself (like email_required?) defined inside devise method. So when you define email_required? on User model itself it works fine, but in included module they don't override devise's method.
But with Ruby 2 you can do this with prepend. Like this:
module User::AuthHelper
extend ActiveSupport::Concern
included do
prepend DeviseInstanceMethods
devise :database_authenticatable, :async, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, \
:omniauthable, omniauth_providers: [:facebook, :instagram], authentication_keys: [:username]
end
module DeviseInstanceMethods
def email_changed?
false
end
def email_required?
false
end
end
end
Now all methods in DeviseInstanceMethods will override devise's methods.
I don't know whether this is best solution, but it works for me. Hope it helps.

Resources