FactoryGirl polymorphic associations - ruby-on-rails

I can't create a valid comment factory using factory girl. My comment model belongs to commentable and is polymorphic. I've tried a whole bunch of different things, but at the moment, most of my tests are failing with this error:
ActiveRecord::RecordInvalid:
Validation failed: User can't be blank, Outlet can't be blank
I'm not sure why it isn't passing validation, especially because my comment model validates the presence of user_id and outlet_id, not User and Outlet
Here is my factory:
factory :comment do
body "This is a comment"
association :outlet_id, factory: :outlet
association :user_id, factory: :user
#outlet_id factory: :outlet
association :commentable, factory: :outlet
end
class CommentsController < ApplicationController
def new
#comment = Comment.new
end
def create
#outlet = Outlet.find(params[:outlet_id])
#comment = #outlet.comments.build(comment_params)
#comment.user_id = User.find(params[:user_id]).id
if #comment.save
redirect_to(#outlet)
end
end
def edit
#comment = Comment.find(params[:id])
end
def update
#comment = Comment.find(params[:id])
if #comment.update(comment_params)
redirect_to #comment.outlet
end
end
def destroy
#comment = Comment.find(params[:id])
if #comment.destroy
redirect_to #comment.outlet
end
end
private
def comment_params
params.require(:comment).permit(:body, :outlet_id, :user_id)
end
end
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
validates :body, :user_id, :outlet_id, presence: true
validates :body, length: { in: 1..1000 }
end

Is there a particular reason for using association :user_id?
You probably want something more like:
factory :comment do
body "This is a comment"
association :outlet, factory: :outlet
association :user, factory: :user
association :commentable, factory: :outlet
end
Which incidentally can simplify to:
factory :comment do
body "This is a comment"
outlet
user
association :commentable, factory: :outlet
end

Related

Ruby on Rails assign company_id and job_id in models

Have three models: Company, Job and JobApplications. When submitting the job form, the company_id and job_id are showing up as nil in the rails console. What's the best way to assign both company_id and job_id values for each job created by a company?
I've added the company_id and job_id to the companies and jobs tables. Within the create method of my jobs model, I've assigned #company_id to the job params and company_id and job_id are still showing as nil after creating a job.
Controller Actions
class CompaniesController < ApplicationController
def new
#company = current_user.build_company
end
def create
#job = Job.new
#company = Company.new(company_params)
end
private
def set_company
#company = Company.find(params[:id])
end
def company_params
params.require(:company).permit(:avatar, :name, :website, :about)
end
class JobsController < ApplicationController
def new
#job = Job.new(:company_id => params[:id])
#company_id = params[:job][:company_id]
end
def create
# #job = current_user.jobs.build(job_params)
#job = Job.find(params[:job_id])
# #company = #job.company
#job = Job.create(job_params.merge(user: current_user, company_id: current_user, job_id: #job))
#company_id = params[:job][:company_id]
end
private
def set_job
#job = Job.find_by(id: params[:id])
if #job.nil?
redirect_to jobs_path
end
end
def job_params
params.require(:job).permit(:company_name, :company_website, :company_description, :company_avatar, :title, :location, :salary, :job_author, :remote_role, :job_type, :rounds_of_interviews, :start_date, :qualifications, :description, :benefits, :job_id)
end
class JobApplicationsController < ApplicationController
def create
#job_application = JobApplication.new(job_application_params)
#job_application.user_id = current_user.id
end
private
def set_job
#job = Job.find(params[:job_id])
# self.job_id
end
def job_application_params
params.permit(:first_name, :last_name, :email, :phone, :attachment, :work_for_any_employer, :require_visa_sponsorship)
end
Models
class Company < ApplicationRecord
has_many :conversations
has_many :jobs
has_many :job_applications, through: :jobs
end
class Job < ApplicationRecord
belongs_to :user
belongs_to :company, optional: true
has_many :job_applications, dependent: :destroy
end
class JobApplication < ApplicationRecord
belongs_to :user
belongs_to :job
validates_uniqueness_of :user_id, scope: :job_id
end

RoR: Save information from 3 models at same time

I am trying to make it so that when I save an answer, I also save the prop_id that is associated with that answer.
I have a nested route relationship so that each prop (stands for proposition or bet) has a an associated answer like this: http://localhost:3000/props/1/answers/new.
Right now, when I save an answer, I save the answer choice and the user_id who created the answer. I need to save also the prop that is associated with the answer.
Answers Controller:
class AnswersController < ApplicationController
attr_accessor :user, :answer
def index
end
def new
#prop = Prop.find(params[:prop_id])
#user = User.find(session[:user_id])
#answer = Answer.new
end
def create
#prop = Prop.find(params[:prop_id])
#user = User.find(session[:user_id])
#answer = #user.answers.create(answer_params)
if #answer.save
redirect_to root_path
else
render 'new'
end
end
def show
#answer = Answer.find params[:id]
end
end
private
def answer_params
params.require(:answer).permit(:choice, :id, :prop_id)
end
Answer Model
class Answer < ActiveRecord::Base
belongs_to :prop
belongs_to :created_by, :class_name => "User", :foreign_key => "created_by"
has_many :users
end
Prop Model
class Prop < ActiveRecord::Base
belongs_to :user
has_many :comments
has_many :answers
end
User Model
class User < ActiveRecord::Base
has_many :props
has_many :answers
has_many :created_answers, :class_name => "Answer", :foreign_key => "created_by"
before_save { self.email = email.downcase }
validates :username, presence: true, uniqueness: {case_sensitive: false}, length: {minimum: 3, maximum: 25}
has_secure_password
end
Just modify your code a little bit, and it will work:
def create
#user = User.find(session[:user_id])
#prop = #user.props.find_by(id: params[:prop_id])
#answer = #user.answers.build(answer_params)
#answer.prop = #prop
# Modify #user, #prop or #answer here
# This will save #user, #prop & #answer
if #user.save
redirect_to root_path
else
render 'new'
end
end

rails multiple belongs_to assignments with nested attributes

My problem is that how to assign multiple belongs_to associations with nested attributes?
I want to build a issue system. When I create a issue, I also want to create the first comment as the issue body.
So, I have following Models:
class Issue < ActiveRecord::Base
has_many :comments, as: :commentable
validates :title, presence: true
accepts_nested_attributes_for :comments
end
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :commentable, polymorphic: true
validates :content, :user, presence: true
end
and I have the IssuesController as follow:
class IssuesController < ApplicationController
before_action :authenticate_user! #devise authentication
def new
#issue = Issue.new
#issue.comments.build
end
def create
#issue = Issue.new(issue_params)
#issue.save
end
private
def issue_params
params.require(:issue).permit(:title, comments_attributes: [:content])
end
end
and the following is my form (using slim template with simple_form and nested_form gems):
= simple_nested_form_for #issue do |f|
= f.input :title
= f.fields_for :comments do |cf|
= cf.input :content
= f.button :submit
In this case, I don't know how to assign current_user to the comment created by nested attributes.
Any suggestions or other approaches? Thanks!
As I wrote in the comments, there's two ways of doing this.
The first way is to add a hidden field in your subform to set the current user:
= simple_nested_form_for(#issue) do |f|
= f.input :title
= f.fields_for(:comments) do |cf|
= cf.input(:content)
= cf.hidden(:user, current_user)
= f.submit
If you do not trust this approach in fear of your users fiddling with the fields in the browser, you can also do this in your controller.
class IssuesController < ApplicationController
before_action :authenticate_user! #devise authentication
def new
#issue = Issue.new
#issue.comments.build
end
def create
#issue = Issue.new(issue_params)
#issue.comments.first.user = current_user
#issue.save
end
private
def issue_params
params.require(:issue).permit(:title, comments_attributes: [:content])
end
end
This way you take the first comment that is created through the form and just manually assign the user to it. Then you know for the sure that the first created comment belongs to your current user.
You could also add user_id as current_user.id when you use params
class IssuesController < ApplicationController
before_action :authenticate_user! #devise authentication
def new
#issue = Issue.new
#issue.comments.build
end
def create
#issue = Issue.new(issue_params)
#issue.save
end
private
def issue_params
params[:issue][:comment][:user_id] = current_user.id
params.require(:issue).permit(:title, comments_attributes: [:content, :user_id])
end
end

Foreign key is still nil after relation was built

I have problem while creating new user with address. I create record in Users and Addresses table, but foreign key to address in user is still nil.
class User < ActiveRecord::Base
belongs_to :address
accepts_nested_attributes_for :address
end
class Address < ActiveRecord::Base
has_one :user
end
def new
#user = User.new
#user.build_address
end
def create
#user = User.new(user_params)
if #user.save
flash[:notice] = "Your account has been created."
redirect_to signup_url
else
flash[:notice] = "There was a problem creating you."
render :action => :new
end
end
private
def user_params
params.require(:user).permit(
:first_name,
:last_name,
:email,
:password,
:password_confirmation,
address_attributes: [:id, :city]
)
end
end
Thank you.
You mixed up relation types.
Try this:
class User < ActiveRecord::Base
has_one :address
end
class Address < ActiveRecord::Base
belongs_to :user
end
Also your code is structured funny, two models and then some methods out of their context. I hope it's just a misprint. If not, put everything except Address model into User model.

Create factory for public_activity rspec

I am using the public_activity gem and I have a method which deletes an activity record when its trackable parent is deleted. As per below.
def destroy
#comment = Comment.find(params[:id])
if #comment.destroy
#activity = PublicActivity::Activity.where(trackable_type: "Comment", trackable_id: #comment.id).first
#activity.destroy
respond_to do |format|
format.js
end
end
end
I have tried quite a few different names to use for the public_activity factory however none seem to work and return trait not registered
How can i set up a public_activity factory with the correct name?
factories.rb
factory :activity do
trackable_id :answer
recipient_id :user
owner_id :user
end
Blind answer, try this:
factory :activity, class: 'PublicActivity::Activity' do
trackable_id :answer
recipient_id :user
owner_id :user
end
This works for FactoryBot:
FactoryBot.define do
factory :activity, class: 'PublicActivity::Activity' do
association :trackable, factory: :answer
association :recipient, factory: :user
association :owner, factory: :user
end
end

Resources