accepts_nested_attributes with 2 nested tables - ruby-on-rails

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.

Related

NameError uninitialized constant Model::Object

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

Rails has_many through

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

Undefined method `each' for #<User:

Rails 4.1
Ruby 2.0
Credential.rb
class Credential < ActiveRecord::Base
belongs_to :category
has_many :user
validates :name, :login, :password, presence: true
attr_accessor :encryption_key
attr_encrypted :login, key: :encryption_key
attr_encrypted :password, key: :encryption_key
end
User.rb
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 :credentials
def you
"You are <b>#{email}</b>"
end
end
CredentialsController.rb
class CredentialsController < ApplicationController
before_filter :authenticate_user!
def create
#credential = current_user.credentials.new
#credential.encryption_key = session[:master_key]
#credential.update(credential_params)
if #credential.save
redirect_to credential_path(#credential), notice: "Password entry created successfully."
else
render "new"
end
end
The line:
#credential.update(credential_params)
throws an exception
undefined method 'each' for #<User:0x4de4f58>
You need to edit your associations. You have credentials that has_many :user and users that has_many :credentials. The one with the foreign key should be a belongs_to not has_many. If you're attempting to make a many-to-many relationship, then either use has_many_and_belongs_to or a join table. Further, it should be has_many :users and not has_many :user. That should resolve your error.

How to establish association between a Devise model and a model I have made?

How do you use User(devise which store email and password) to belong_to Profile and Profile has_one User? When I looked up the database profile_int is still nil hmmm... not sure where did I do wrong?
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :profile_id
# attr_accessible :title, :body
belongs_to :profile
end
class Profile < ActiveRecord::Base
attr_accessible :dob, :firstName, :lastName, :school_id, :schYear, :user_attributes
belongs_to :school
has_one :user
accepts_nested_attributes_for :user
end
I know usually I should do something like this Profile.create(.......) but I am not sure where to do this if I am doing it with a devise
Should :schoolstrong text be ':schoolstrong_text'? Did you run rake db:migrate ?
Also, checking your schema could be helpful too.
A common practice in associating a Devise User with a Profile model is making the profile the child of the user:
# app/models/user.rb
class User < ActiveRecord::Base
has_one :profile
end
# app/models/profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
end
Then, within your User model, you'd create an after_create hook to create a new Profile model and associate it with the newly created user:
# app/models/user.rb
after_create :create_profile
def create_profile
profile = Profile.create
self.profile = profile
self.save
end

Rails Devise polymorphic

I am using devise and I want create a polymorphic relationship, I added the columns to table users 'usersable_type' and 'usersable_id'
This is my code
Model >> User
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
# attr_accessible :title, :body
attr_accessible :email, :password, :password_confirmation, :remember_me
#usarsable
belongs_to :usersable, :polymorphic => true, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :usersable
end
Model >> Medic
class Medic < ActiveRecord::Base
attr_accessible :license_number, :specialty
has_one :user, as: :usersable, dependent: :destroy
has_and_belongs_to_many :patients
end
Model >> Patient
class Patient < ActiveRecord::Base
belongs_to :socialsecurity
attr_accessible :birthday, :blood_type
has_one :user, as: :usersable, dependent: :destroy
has_many :contacts
has_and_belongs_to_many :medics
end
Override Devise Controller
class RegistrationsController < Devise::RegistrationsController
def new
super
#user.build_usersable # I had problem in this line
end
def create
end
def update
super
end
end
Those are all the models I have for the moment, but I still have the same problem, I dont know how create and save the polymorphic object.
The error still is the same
ERROR: undefined method `build_usersable' for "<#User:"
Is anyone can help me I would be grateful
Regards and thanks in advance
Juli.
Based on the conversation in the comments this is the kind of scheme i think you need.
I am going to use the concept of Aspect, that is a user can have many aspects, the aspect might be a medic, a content detail etc; an Aspect can have only one user.
First you need a UserAspect model which has a user_id and a aspect_type and aspect_id
class UserAspect < ActiveRecord::Base
belongs_to :user
belongs_to :aspect, :polymorphic => true
end
Now your user model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
# attr_accessible :title, :body
attr_accessible :email, :password, :password_confirmation, :remember_me
#aspects
has_many :user_aspects
has_many :aspects, :through => :user_aspects
end
And now your medic
class Medic < ActiveRecord::Base
attr_accessible :license_number, :specialty
has_one :user_aspect, as: :aspect, dependent: :destroy
has_one :user, :through => :user_aspect
end
Now you can do things like
user.aspects
medic.user
etc

Resources