Facing problems with association - ruby-on-rails

I have three models User, Blog and Comment.
User.rb
class User < ActiveRecord::Base
attr_accessible blah blah
has_many :blogs
has_many :comments
end
Blog.rb
class Blog < ActiveRecord::Base
attr_accessible :user_id, :title, :content
belongs_to :user
has_many :comments
end
Comment.rb
class Comment < ActiveRecord::Base
attr_accessible :user_id, :blog_id, :comment
belongs_to :blog
belongs_to :user
end
In create action of Comments Controller
def create
#blog = Blog.where('id=?', params[:blog_id])
#comment = #blog.comments.new(params[:comment])
#comment.save
end
Here how will I pass id of current_user in the :user_id field of comments table, I can make a hidden field for that but it's not safe. PLease help! Thanks in advance.

Would this do what you want?
def create
#blog = Blog.where('id=?', params[:blog_id])
#comment = #blog.comments.new(params[:comment])
#comment.user = current_user # force the user to be the logged-in user
#comment.save
end

Related

AssociationTypeMismatch nested attributes

I'm running into an issue with an associated model. I have a nested attributes for my user, to a reviewer. A user can essentially review another person, thus be a reviewer and be the person reviewed.
It's set up like this:
# User
has_many :reviewers
accepts_nested_attributes_for :reviewers
has_many :active_managements, class_name: 'Reviewer',
foreign_key: 'reviewer_id',
dependent: :destroy
class Reviewer < ActiveRecord::Base
belongs_to :user
belongs_to :reviewer_id, class_name: 'User'
end
now in my users controller I have:
class UsersController < ApplicationController
def edit
#user = User.find(params[:id])
#user.reviewers.build
redirect_to root_url && return unless #user.activated?
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
redirect_to edit_user_path(#user)
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:invitation_token, :first_name, :admin,
:last_name, :title, :email, :password,
reviewers_attributes: [:reviewer_id])
end
the error that I get is:
User(#70197180889680) expected, got String(#70197172430700)
happening on "user_params", so I assume it has to do with my attributes. Anybody know what's up?
The line belongs_to :reviewer_id, class_name: 'User' is incorrect. Try changing it to something like belongs_to :reviewing_user, class_name: 'User' (replacing reviewing_user with whatever name you want to use for this association :), not field name.
http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/belongs_to
The immediate fix is here:
#app/models/review.rb
class Reviewer < ActiveRecord::Base
belongs_to :reviewer
end
--
This is how I'd fix the systemic issue:
#config/routes.rb
resources :users do
resources :reviewers #-> url.com/users/:user_id/reviews/new
end
#app/controllers/reviewers_controller.rb
class ReviewersController < ApplicationController
def new
#user = User.find params[:user_id]
#review = user.reviewers.new
end
def create
#user = User.find params[:user_id]
#review = user.reviewers.new reviewer_params
end
private
def review_params
params.require(:reviewer).permit(:user_id, :reviewer_id)
end
end
Models
Apart from this, I think your main issue is the way your models are set up.
Ideally, you want to have reviewer and user as the same data-set (I presume they're both users), which makes your current setup really inefficient...
#app/models/user.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :reviewers,
class_name: "User",
join_table: :reviewers_users
foreign_key: :user_id,
association_foreign_key: :reviewer_id
end
What you're looking for is something called a self referrential association, which basically allows you to associate the same model in a many-to-many relationship.
In most cases, this will be used with a has_and_belongs_to_many relationship; you could also use a has_many :through although it's not as common.
The above will allow you to use the following:
#user = User.find params[:id]
#user.reviewers #-> collection of users who are reviewers of original user

How to save throught model with extra field?

I have three models Company, User and Division
User have many Division for different Companies
I need to determine in what company owns Divisions
So I build has_many :through association between Users and Divisions
Model UsersDivision have this fields id|user_id|division_id|company_id but when I update User model rails delete old records and create new without company_id field How i can update model UsersDivision and merge company_id ?
Callback?
class UsersDivision < ActiveRecord::Base
after_update :set_company
belongs_to :user
belongs_to :division
belongs_to :company
validates :user_id, :division_id, presence: true
private
def set_company(company)
self.company_id = company
end
end
or in the controller?
class UsersController < ApplicationController
def update
#company = Company.find(params[:company_id])
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to :back
end
end
end
How to merge company_id when create UsersDivision record?
So I build has_many :through association between Users and Divisions
I would expect there to be a table for Divisions, and then a table for CompanyDivisions, and then we can associate users to that.
Here's how I would have it set up:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :user_divisions
has_many :divisions, through: :user_divisions
has_many :company_divisions, through: :user_divisions
has_many :companies, through: :company_divisions
end
#app/models/user_division.rb
class UserDivision < ActiveRecord::Base
belongs_to :user
belongs_to :company_division
end
#app/models/company.rb
class Company < ActiveRecord::Base
has_many :company_divisions
has_many :divisions, through: :company_divisions
end
#app/models/company_division.rb
class CompanyDivision < ActiveRecord::Base
belongs_to :company
belongs_to :division
end
#app/models/division.rb
class Division < ActiveRecord::Base
has_many :company_divisions
has_many :companies, through: :company_divisions
end
This is very bloated, but should give you the ability to call:
#user.divisions
#user.divisions.each do |division|
division.companies.first
How to merge company_id when create UsersDivision record
This will depend on several factors:
params hash
How your associations are set up
I don't have your params hash, but I do have your current code:
class UsersController < ApplicationController
def update
#company = Company.find params[:company_id]
#user = User.find params[:id]
redirect_to :back if #user.update user_params
end
private
def user_params
params.require(___).permit(___).merge(company_id: #company.id)
end
end

Model creation and association of STI subclass

I have an Event model that has one Payoption which can be of different types using STI subclasses like this:
class Event < ActiveRecord::Base
has_one :payoption, dependent: :destroy
accepts_nested_attributes_for :payoption
end
class Payoption < ActiveRecord::Base
belongs_to :event, :polymorphic => true
PAY_OPTION = ["BankPayoption", "CashPayoption"]
end
class BankPayoption < Payoption
belongs_to :event
end
class CashPayoption < Payoption
belongs_to :event
end
I'm creating an Event and a Cash/BankPayoption in the same controller like this, still some hardcoding and missing functionally while developing:
def new
#event = Event.new
#event.build_payoption
end
def create
#event = Event.new(event_params)
#event.user_id = current_user.id
if params[:event][:payoption_attributes][:type] == "BankPayoption"
#payoption = BankPayoption.new
#payoption.phone = "0734176395"
#payoption.event = #event
#payoption.save
#event.payoption = #payoption
end
#event.save
redirect_to #event
end
Both the Event and BankPayoption gets created and BankPayoption gets the corrent Event ID however the Event doesn't get any Payoption ID at all and remains nil. Figured there's issues with the STI/polymorphism but can't figure out how to solve it.
Thanks in advance
I am not sure if this is your problem. But you are missing as: :event, in your has_one association.
class Event < ActiveRecord::Base
has_one :payoption, as: :event, dependent: :destroy
accepts_nested_attributes_for :payoption
end

Rails has_many through validation got skipped

I'm feeling a little bit dumb to ask this, but I've been Googling my a*# off.
Well I have the following models:
class Company < ActiveRecord::Base
has_many :employments
has_many :users, through: :employments
validates_presence_of :name
validates_presence_of :description
validates_numericality_of :zip, only_integer: true
validates_presence_of :email
validates_presence_of :street
validates_presence_of :city
validates_presence_of :country
validates_presence_of :telephone
end
class Employment < ActiveRecord::Base
belongs_to :user
belongs_to :company
end
class User < ActiveRecord::Base
has_many :employments
has_many :companies, through: :employments
end
Important here is the company-Model which has some validations.
Now, I have the following Controller to create a new Company:
class CompaniesController < ApplicationController
def create
#company = Company.new(company_params) # The params were set with a private Method
#employment = #company.employments.build(user: current_user, is_admin: true)
if #employment.save
redirect_to :back, flash: { success: 'Success' }
else
#title = 'Create a new company'
render :new
end
end
end
The Problem is, that when I leave the companies-Fields blank, the company gets not created, but the employment-Model gets persistet in the Database.
I believe It has something to do with the Company.new()-Call I have to check, if the #company-Model gets created first, before the #employment-Model gets created.
How can I achieve that the validation gets tested first?
Thank you very much!
To validate associated object you need to use validates_associated. Please note the "Warning" and "Note" in the linked api document.
Try:
class Employment < ActiveRecord::Base
belongs_to :user
belongs_to :company
validates_associated :company
end
in addition to vinodadhikary's answer, you can also try saving the company. so instead of #employment.save, use #company.save. That should also save #employment when #company passes validations.

Ruby on Rails: railscasts comment system: inserting username into comment database?

I was following RyanB's polymorphic association video which shows examples of implementing a comment system.
http://railscasts.com/episodes/154-polymorphic-association-revised?autoplay=true
I was wondering how do I add a username into the database of the person that is creating the new comment? This way I can display username in the view pages,
Thanks
Too many ways to do it
Solution 1
If you will using authentication for comment system you should add one model user for authentication (suggest to use devise)
class User < ActiveRecord::Base
attr_accessible :email, :password, :username
has_many :comments
end
class Comment < ActiveRecord::Base
attr_accessible :content, :user_id
belongs_to :commentable, polymorphic: true
belongs_to :user
end
and on controller (take from repository of 154-polymorphic-association-revised )
def create
#comment = #commentable.comments.new(params[:comment])
#comment.user_id = current_user.id
if #comment.save
redirect_to #commentable, notice: "Comment created."
else
render :new
end
end
OR Solution 2
You just add one attribute to comment model (without authentication)
class Comment < ActiveRecord::Base
attr_accessible :content, :username
belongs_to :commentable, polymorphic: true
end

Resources