"ActiveModel::ForbiddenAttributesError " on Rails App ( 5) with nested attributes - ruby-on-rails

I have a simple_form_for that creates an invoice. Through this form, I want the user to be able to create a client that will be associated with that before-mentionned invoice. The current process being to firstly create the client, then associate it to the invoice by selecting it from a collection of created clients when the user create an invoice.
My models :
class Client < ApplicationRecord
has_many :invoices
end
class Invoice < ApplicationRecord
belongs_to :client
accepts_nested_attributes_for :client, reject_if: :all_blank, allow_destroy: true
end
Invoice controller:
def new
#invoice = Invoice.new
#invoice.build_client
end
def create
#invoice = Invoice.new(invoice_params)
#client = #invoice.build_client(params[:invoice][:client_attributes])
#client.user = current_user
#client.save
end
And I made sure to update my strong params in Invoice Controller with :
params.require(:invoice).permit(:param1, :param2,client_attributes:[:param1, :param2, :param3, etc..],..)
That being said, when creating an invoice, I ran into an "ActiveModel :: ForbiddenAttributesError", which is set to appears when strong params are not correctly defined. Which, in my case, does not seem to be the case.
I found out that adding "params.permit!" in my #Create in the Invoice Controller, allowed me to avoid that error. But that's a trick. It should not be necessary since that's the jobs of the strong params. Has anyone ever came across a similar case, please?

Ok, so I figured this thing out. All that was needed to do was to - obviously- save my client before, my invoice. Rather simple, isn't it!
Here is my final Invoice #New #Create
def new
#invoice = Invoice.new
#invoice.build_client
end
def create
#invoice = Invoice.new(invoice_params)
#invoice.client.user = current_user
#invoice.client.save
if #invoice.save
redirect_to #invoice
else
render :new
end
end

Related

rails add record to has_many :through join table

class EventTeam < ActiveRecord::Base
belongs_to :event
belongs_to :team
end
class Event < ActiveRecord::Base
has_many :event_teams
has_many :teams, through: :event_teams
end
class Team < ActiveRecord::Base
has_many :event_teams
has_many :events, through: :event_teams
end
I am trying to add the :event_id and :team_id to the EventTeam join table when creating a new Event and can't seem to figure out how, despite an exhaustive search of similar questions such as: how to add records to has_many :through association in rails (I've tried all of these suggestions)
It seems that the following should work, though a NoMethodError is delivered: "undefined method `events' for #ActiveRecord::Relation []"
EventsController
def new
#event = Event.new(:team_id => params[:team_id])
end
def create
#team = Team.where(:id => params[:team_id])
#event = #team.events.create(event_params)
if #event.save
flash[:success] = "Event created!"
redirect_to #event
else
render 'new'
end
end
I have a similar situation in the same app with Users, Teams, and Memberships (join table). The following code automatically adds the :team_id and :user_id to the Memberships table when a user creates a new Team.
TeamsController
def new
#team = Team.new(:user_id => params[:user_id])
end
def create
#team = current_user.teams.create(team_params)
if #team.save
flash[:success] = "Team created!"
redirect_to #team
else
render 'new'
end
end
Any suggestions on how to accomplish this?
undefined method `events' for #ActiveRecord::Relation []
where returns an AR relation not a single instance, so #team.events won't work. Use find instead
#team = Team.find(params[:team_id])
#event = #team.events.create(event_params)
Update
could not find Team with 'id'=
You are getting team_id inside event hash, so params[:team_id] won't work. You need to use params[:event][:team_id]
#team = Team.find(params[:event][:team_id])
#event = #team.events.create(event_params)
Just specify first value of the relation, since you are searching by unique index with value id, so that should be well:
#team = Team.where(id: params[:team_id]).first
#event = #team.events.create(event_params)
That is because .where, unlike find_by or find(1) returning a Relation, not a first value in it.
However, in modern version of rails I saw recommendation to use exactly where.first pair, not a find.

Rails - can't tell create controller which item to create

I have several models:
User
Relationship
Project
Schedule
A user instance can be of type :student or :employer.
A schedule belongs_to a project and
a project has_one schedule
project belongs_to a student and a student has_many projects.
A relationship belongs_to Student and relationship also belongs_to Employer. Employer and Student both has_many relationships.
I am writing the controller to create a schedule and I can't figure out how to tell the controller which project the schedule belongs to. Here is what I have so far
def create
if current_user.type == 'Employer'
redirect_to employer_profile_path(current_user.profile_name)
else
#schedule = Schedule.find(params[:id])
if #schedule.save(schedule_params)
flash[:notice] = "Successfully created schedule."
redirect_to profile_path(current_user.profile_name) #change to project path later
else
render :action => 'new', :notice => 'Invalid Schedule'
end
end
end
private
def schedule_params
params.require(:schedule).permit(tasks_attributes: [:title, :content, :_destroy])
end
I am pretty sure I am defining #schedule incorrectly. The routes for schedule are:
resources :schedules
How do I tell the controller which Project the schedule belongs to?
Assuming you posted the create action for the SchedulesController there is no need for:
#schedule = Schedule.find(params[:id])
this will probably return nil, because there is no schedule (after all that is what you want to create here).
#schedule = Schedule.new(schedule_params)
if you want to assign a project to the schedule, you need to submit this information so you can access it in the params hash. Something like:
#schedule.project = Project.find(params[:project_id])

Changing Data from an other model

I am wondering what kind of query should I accept to allow my data to be updated. My models consists of client, interest, and a manager
Clients his has follow
id
name
email
password
Interest
id
description
manager
customer_id
interest_id
created_at
The goal of the manager his not to override old data in interest but just keep adding a new interest and refering to it.
The relationship his has follow
class Client < ActiveRecord::Base
has_many :music_interest_managers
has_many :music_interests, through => :music_interest_managers
end
class MusicInterest < ActiveRecord::Base
has_many :music_interest_managers
has_many :clients, through => :music_interest_managers
end
class MusicInterestManager < ActiveRecord::Base
belongs_to :music_interests
belongs_to :client
end
Now to update the data from the customer controller i am not sure how would i do this
This is what i am thinking about:
#client = Client.find(params[:id])
#manager = #client.manager.build(params[:manager])
#interest = #interest.manager.build(params[:interest])
Does this make sense? or i am dead wrong?
Update:
def update
#client = Client.find(params[:id])
#interest = #client.music_interests.build(params[:interest])
if #client.update_attributes(params[:client])
flash[:success] = "Profile updated"
#sign_in #client
redirect_to #client
else
render 'edit'
end
end
Or should i render a model view from interest to then apply the change?
#client = Client.find(params[:id])
#interest = #client.music_interests.build(params[:interest])
should work - try it out in the console!

Rails, using build to create a nested object, but it is not being saved

My app has three models:
Thread (has_many :thread_apps)
ThreadApp (belongs_to :thread, has_many :forms, :as => :appable)
Form (belongs_to :app)
ThreadApp Fields: thread_id, form_id, appable_id, appable_type
What I want to be able to do is when creating a form, ensure that a ThreadApp record is also created to make the association:
Here is what I have:
class FormsController < ApplicationController
def create
#thread = Thread.find(params[:thread_id])
#thread_app = #thread.thread_apps.new
#form = #thread_app.forms.build(params[:form].merge(:user_id => current_user.id))
#form.save
....
This is saving the form nicely, but the thread_app associated is not being made? Any ideas why?
Thank you
callings model.save does not save associations unless you tell it to
you can set autosave
class Form < ActiveRecord::Base
belongs_to :thread_app , :autosave => true
end
or call save on it in the controller
#thread_app.save
or you can take it out of the controller entirely
and do this with a callback
class Form < ActiveRecord::Base
before_create :create_thread_app
def create_thread_app
self.thread_app ||= ThreadApp.create(...)
end
end
or after_create, _before_validation_on_create, or any other call back would work
--UPDATE--
this might make a difference using create inse=tead of new, and appables that you specified as 'as'
class FormsController < ApplicationController
def create
#thread = Thread.find(params[:thread_id])
#thread_app = #thread.thread_apps.create
#form = #thread_app.appables.build(params[:form].merge(:user_id => current_user.id))
#form.save
....
Instead of:
#thread_app = #thread.thread_apps.new
You should have:
#thread_app = #thread.thread_apps.create

Rails, saving the foreign key in a `belongs_to` association

I think I'm having a really basic problem here but I can't seem to put my finger on what I'm doing wrong.
So the issue here is when I save an instance of a model the foreign_key for the models's belongs_to association (in this case the user_id is not being saved, so I'm forced to do this:
def new
#thing = Thing.new(:user_id => current_user.id)
end
def create
#thing = Thing.new(params[:thing])
#thing.user_id = current_user.id
if #thing.save
redirect_to #thing
else
render 'new'
end
end
Shouldn't the user_id get saved automatically if my model has this association?
class Thing < ActiveRecord::Base
belongs_to :user
end
The reason I'm having this issue in the first place is because the gem friendly_id has changed the way all of my ids work and now return the objects slug... pretty annoying in my opinion.
I would try #thing.user = User.find(current_user.id) instead in your controller. Have you also got the has_many :things association declared in your user model?

Resources