Good afternoon, beautiful community, I have the following query: I have this error even though the method is well defined, if someone can give me a hand.
I want when a user registers to automatically create a profile for said user
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :patients, dependent: :destroy
has_one :profile, dependent: :destroy
after_create :set_profile
def set_profile
self.profile = Profile.create()
end
end
class Profile < ApplicationRecord
before_action :set_profile
belongs_to :user
private
def set_profile
#profile = (current_user.profile ||= Profile.create)
end
end
class ProfilesController < ApplicationController
before_action :set_profile
def show
end
def edit
end
def update
end
private
def set_profile
#profile = (current_user.profile ||= Profile.create)
end
end
The error occurs because you're mixing up the model callbacks and the before_action that belongs in the controller in your Profile class. It should not be before_action but before_save or something like that.
See a list of available callbacks for the models here: https://guides.rubyonrails.org/active_record_callbacks.html#available-callbacks
If you're goal is to just create a profile after creating a user the code in your User class is sufficient. No need to add another callback in the Profile class (but of course you can if you want to deal with other stuff there).
Related
I have two models that have a has_many association to the same object. I have a User, an Admin, and Visits.
Users has_many Visits
Admins has_many Visits
Every time I create a Visit with a User it works, but when I do it with an Admin it gives me an error:
ActiveRecord::AssociationTypeMismatch.
The full error is this:
User(#70282715553200) expected, got #<Admin id: 2, email: "admin#gmail.com", created_at: "2019-02-07 12:08:40", updated_at: "2019-02-07 12:08:40"> which is an instance of Admin(#70282709528720)
def create
#visit = #service.visits.new(visit_params)
if user_signed_in?
#visit.user = current_user
else
#visit.user = current_admin
end
if #visit.save
redirect_to service_visits_path(#service)
else
redirect_to #services
end
end
==============================
class Admin < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and
# :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :visits, dependent: :destroy
end
==============================
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and
# :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :visits, dependent: :destroy
end
==============================
class Visit < ApplicationRecord
belongs_to :user
belongs_to :admin
belongs_to :service
end
Unless you've got some kind of polymorphism going on, which isn't documented, I'd try and change this:
if user_signed_in?
#visit.user = current_user
else
#visit.user = current_admin
end
To this:
if user_signed_in?
#visit.user = current_user
else
#visit.admin = current_admin # this line
end
Your Visit model says a visit has both one User, and one Admin, so you have to assign the current_admin to the #visit.admin, not #visit.user.
If you're using Rails 5, you'll also need to update your model as below:
class Visit < ApplicationRecord
belongs_to :user, optional: true
belongs_to :admin, optional: true
belongs_to :service
end
As I note in my comment below, the suggestion from #bo-oz should be given considerable consideration. I haven't seen User and Admin tables typically split out as you've done in production applications. The concept of 'admin' is typically handled as a separate Role model (the rolify gem is good for this), or more simply as a boolean on the User model.
I think what you are trying to do us just plain wrong. An Admin is a User as well. You should remove the Admin model entirely. If you need to assign additional capabilities / rights to someone, you should either create an additional attribute (admin boolean yes/no), or create some kind of Role Based model. Have a look at Rolify gem.
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and
:omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :visits, dependent: :destroy
def is_admin?
// return true if user is admin
end
end
class Visit < ApplicationRecord
belongs_to :user
belongs_to :service
end
def create
#visit = #service.visits.new(visit_params)
if user_signed_in?
#visit.user = current_user
else
if #visit.save
redirect_to service_visits_path(#service)
else
redirect_to #services
end
One warning though.... the user is mandatory is this relationship, so this would break if someone is not logged in! Think about it... either don't create a Visit, or create an Anonynous visit.
I'm new to ruby on rails. Ihe error I have is
NameError in ReviewsController#create
uninitialized constant User::Review
Extracted source:
#review = current_user.reviews.build(review_params)
I read on other stack overflow questions that usually the error for wrong names or forgetting belongs_to or has_many but I believe I've set the relations correctly. I am using the gem devise to handle the user and sign in/sign up etc
Reviews.rb
class Reviews < ActiveRecord::Base
belongs_to :user
belongs_to :renters
end
User.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :reviews
end
Reviews_Controller.rb
class ReviewsController < ApplicationController
before_action :set_renter
before_action :authenticate_user!
def new
#review = Reviews.new(renters: #renter)
end
def create
#review = current_user.reviews.build(review_params)
#review.renter = #renter
#review.save
redirect_to #renter
end
private
def set_renter
#renter = Renters.find(params[:renter_id])
end
def review_params
params.require(:reviews).permit(:comment, :rating)
end
end
The Renters model is working fine and similar code I have to make a new Renter is working so I am not sure what is wrong.
ActiveRecord::Base classes are usually named in singular.
That means your class should be named Review and it should be stored in a file named models/review.rb (but still store its entries in a reviews database table).
If you do not want to follow this convention than you have to explicitly tell Rails that the class is named differently in the definition of the belongs_to and has_many association.
your model class for your reviews table should be Review in the file: app/models/review.rb
class Review < ActiveRecord::Base
belongs_to :user
belongs_to :renters
end
and your User model representing users table should be in the file: app/models/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :reviews
end
NOTE: for this association to work, your reviews table must have a column user_id as the foreign key for performing activerecord operations on associated models (for example: User.find(1).reviews to get all records of reviews table whose user_id is 1)
This occours by convention of Rails. You can force with function class_name the class Reviews
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :reviews, class_name: "Reviews"
end
A user can create organization and then he can make other users as moderators to his organization. Below method shows how the organization is created.
def create
#organization = current_user.organizations.build(organization_params)
# Confirm organization is valid and save or return error
if #organization.save!
# New organization is saved
respond_with(#organization) do |format|
format.json { render :json => #organization.as_json }
end
else
render 'new', notice: "Unable to create new organization."
end
end
How should I create moderators for the organization. I tried using has_many through but it failed. Can somebody help me?
Update
Organization Model
class Organization < ActiveRecord::Base
has_many :moderators
has_many :users, :through => :moderators
end
UserModel
class User < ActiveRecord::Base
enum role: [:user, :moderator, :organization, :admin]
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
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :moderators
has_many :organizations, :through => :moderators
end
Moderator Model
class Moderator < ActiveRecord::Base
belongs_to :user
belongs_to :organization
end
When I create new organization my organization user_id is nil?
Take look at has and belongs to many relation http://apidock.com/rails/v4.2.1/ActiveRecord/Associations/ClassMethods/has_and_belongs_to_many since one user can be moderator for many organization and organization can have many moderators. Also instead of calling #organization.save! you should call #organization.save because now it will throw error if save would be unsuccessful. You want to have boolean as result of save so your condition works properly
I am currently enrolled in a online course in ruby on rails and im learning everything from scratch so pardon me if Im not clear in my questions. Here is my delima, I am trying to create a LINK between two Models in the rails application and here is what I have so far. However when I try to access localhost3000/business/new it returns the error mentioned it the title. I have come to the conclusion that it is because of me using a "has_one :model" type of association, rather than the "has_many :model". I hope someone can point me in the right direction here as I have spent hours searching to no solutions.
class BusinessesController < ApplicationController
before_action :set_business, only: [:show, :edit, :update, :destroy]
//edited for clarity
def new
#business = current_user.business.build //The line that returns a undefined method for nil class
end
def edit
end
def create
#business = current_user.business.build(business_params)
if #business.save
redirect_to #business, notice: 'Business was successfully created.'
else
render "new"
end
end
Devise User 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_many :buzzs, dependent: :destroy
has_one :business, dependent: :destroy
end
Business Model
class Business < ActiveRecord::Base
belongs_to :user
end
Take a look at this http://guides.rubyonrails.org/association_basics.html#has-one-association-reference.
You should use build_business instead of business.build
4.2.1 Methods Added by has_one
When you declare a has_one association, the declaring class automatically gains five methods related to the association:
association(force_reload = false)
association=(associate)
build_association(attributes = {})
create_association(attributes = {})
create_association!(attributes = {})
One to One Association:
class User < ActiveRecord::Base
has_one :business
end
current_user.build_business
Or if One to Many:
class User < ActiveRecord::Base
has_many :businesses
end
current_user.businesses.build
I am new to Ruby on rails and I am creating simple website. I found out the rails 3 uses attr_accessible while rails 4 uses strong parameters. I am currently working with rails 4. I am not quite sure how to set up the accepts_nested_attributes_for.
This is what I have
User model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:rememberable, :validatable
has_many :expense_pictures
has_many :income_pictures
accepts_nested_attributes_for: ExpensePicture ?
accepts_nested_attributes_for: IncomePicture ?
end
ExpensePicture model:
class ExpensePicture < ActiveRecord::Base
belongs_to :user
mount_uploader :image, ImageUploader
end
ExpenseText model:
class ExpenseText < ActiveRecord::Base
belongs_to :expense_pictures
end
IncomePicture model:
class IncomePicture < ActiveRecord::Base
belongs_to :user
mount_uploader :image, ImageUploader
end
IncomeText model:
class IncomeText < ActiveRecord::Base
belongs_to :income_pictures
end
My User controller
class UserController < ApplicationController
def create
User.create(user_params)
accepts_nested_attributes_for :IncomePicture ?
accepts_nested_attributes_for :ExpensePicture ?
end
private
def user_params
# required input for params
# permit - returns a version of the params hash with ony the permitted attributes
params.require(:user).permit(:name, :email, :password, :password_confirmation, ...not sure...)
end
end
Using accepts_nested_attributes_for for has_many relation with your models,your User model should look like this
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:rememberable, :validatable
has_many :expense_pictures
has_many :income_pictures
accepts_nested_attributes_for :expense_pictures
accepts_nested_attributes_for :income_pictures
end
Your new and create methods of usercontroller should look like this
def new
#user = User.new
#user.expense_pictures.build
#user.income_pictures.build
end
def create
#user = User.new(user_params)
if #user.save
redirect_to #user
else
render 'new'
end
end
And your user_params method should look something like this
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation, expense_pictures_attributes: [:your_attr1,:your_attr2,..],income_pictures_attributes: [:your_attr1,:your_attr2,..])
end
Feel free to ask if you want any more information regarding to this.