Rails - ActionController::Parameters include controller value with form values - ruby-on-rails

I have a session variable (user_id) that I'd like to include as a foreign key on a record the user is inserting. I have the form values all coming through the form submit to my controller's entity.update(params) method without a problem using the default params definition. That code looks like
def brand_params
#brand_params = params.require(:brand).permit(:name, :brand_type, :profile_id)
end
The update method looks like
if #brand.update(brand_params)
format.html { redirect_to #brand, notice: 'Widget was successfully updated.' }
format.json { render :show, status: :ok, location: #brand }
else
format.html { render :edit }
format.json { render json: #brand.errors, status: :unprocessable_entity }
end
Now I'd like to append the :profile_id session variable to the #brand_params and following other threads here, I've tried a setter method:
def set_brand_params(key, val)
if #brand_params != nil
#brand_params[key] = val
end
end
However, calling this, #brand_params is always nil. Trying to directly add to the brand_params hash doesn't work because it's a better method. If there's a better way to meet this (I'd assume common) use case, I'm all ears! Otherwise, I'd like to know why the var is always nil though in this context, at least the brand_params method sees it as defined and with value. I got this solution in Adding a value to ActionController::Parameters on the server side
Here is the update method as requested:
def update
puts "update"
set_brand_params("profile_id", session[:prof])
respond_to do |format|
if #brand.update(brand_params)
format.html { redirect_to #brand, notice: 'Widget was successfully updated.' }
format.json { render :show, status: :ok, location: #brand }
else
format.html { render :edit }
format.json { render json: #brand.errors, status: :unprocessable_entity }
end
end
end

I'm not agree with merge your data with the params. Because you must permit only the fields you expect your user update. In this case you don't want the user update profile_id on brands, and that is a security best practice.
Then brand_params must be:
def brand_params
#brand_params = params.require(:brand).permit(:name, :brand_type)
end
Your method update may look by this:
def update
#brand = Brand.find(params[:id])
#brand.assign_attributes(profile_id: session[:prof])
respond_to do |format|
if #barnd.update(brand_params)
format.html { redirect_to #brand, notice: 'Widget was successfully updated.'}
format.json { render :show, status: :ok, location: #brand }
else
format.html { render :edit }
format.json { render json: #brand.errors, status: :unprocessable_entity }
end
end
end
You don't need the method set_brand_params at all.
If this don't do the trick, please publish the entry controller, and I hope we find the issue.
edit: add respond_to.

Related

Passing current user parameters into nested model

I am trying to pass through a devise user id from my Agent model (current_agent.id) into my Nested AgentActivity model whenever I update the parameters on my Submission model. How would I go about achieving this?
Currently my code on Submission controller (doesn't throw an error but doesn't do anything):
#submission.agent_activities.first.agent_id = current_agent.id
respond_to do |format|
if #submission.update(submission_params)
format.html { redirect_to #submission, notice: 'Submission was successfully updated.' }
format.json { render :show, status: :ok, location: #submission }
else
format.html { render :edit }
format.json { render json: #submission.errors, status: :unprocessable_entity }
end
end
Yes, you're just assigning agent_id, but don't saving it. Should be:
#submission.agent_activities.first.update(agent_id: current_agent.id)
And this line should go after if #submission.update(submission_params)

Rails update model from another controller

So I have this 2 models, Folder and Event. Folder have_one Event and Event belongs to Folder.
I want to be able to update a folder's event with new attributes at the same time as the folder. Something like this.
def update
respond_to do |format|
if #folder.update(folder_params)
#folder.event.update_attributes(status: #folder.status)
format.html { redirect_to #folder, notice: 'Folder was successfully updated.' }
format.json { render :show, status: :ok, location: #folder }
else
format.html { :edit }
format.json { render json: #folder.errors, status: :unprocessable_entity }
end
end
end
But I understand this is not very MVC compliant and also does not work. So any idea on how I can make this work ?
Thanks in advance
You can do something like:
class Folder < ActiveRecord::Base
after_save :update_event_status, on: update #Or after_update :update_event_status
def update_event_status
event.update_attributes(status: status)
end
end
write method in Model and call it in controller method. like below code.
class Folder < ActiveRecord::Base
def update_event_status(event,status)
event.update_attributes(status: status)
end
end
def update
respond_to do |format|
if #folder.update(folder_params)
update_event_status(#folder.event,#folder.status) #call methode here
format.html { redirect_to #folder, notice: 'Folder was successfully updated.' }
format.json { render :show, status: :ok, location: #folder }
else
format.html { :edit }
format.json { render json: #folder.errors, status: :unprocessable_entity }
end
end
end
Try this.

In a rails controller, how do I address the current object within the create method?

I'd like the creation of a Window to generate a number of Timeslots that belong to it. It's pretty easy to take an integer from a form object and create that many timeslots, but I can't figure out how to grab the window ID to tell the timeslots who they belong to.
def create
#window = Window.new(window_params)
#window.capacity.times do
if Timeslot.last
then
#newID = Timeslot.last.id += 1
else
#newID = 1
end
#timeslot = Timeslot.new({id: #newID})
#timeslot.created_at = Time.now
#timeslot.window_id = #window.id
#timeslot.save
end
respond_to do |format|
if #window.save
format.html { redirect_to #window, notice: 'Window was successfully created.' }
format.json { render :show, status: :created, location: #window }
else
format.html { render :new }
format.json { render json: #window.errors, status: :unprocessable_entity }
end
end
end
If anyone can point me to a more elegant way to find a new Timeslot ID, I'd appreciate it too.
#window will not have an ID until after it is saved to the database. Therfore, create timeslots after the record is saved. I extracted timeslot creation to its own private method that gets called after save.
def create
#window = Window.new(window_params)
respond_to do |format|
if #window.save
create_timeslots # <-- timeslot creation performed after save
format.html { redirect_to #window, notice: 'Window was successfully created.' }
format.json { render :show, status: :created, location: #window }
else
format.html { render :new }
format.json { render json: #window.errors, status: :unprocessable_entity }
end
end
end
private
def create_timeslots
#window.capacity.times do
Timeslot.create({window_id: #window.id})
end
end
I removed the code which sets timeslot ID and creation time because ActiveRecord does it already. No need to reinvent the wheel.

param is missing or the value is empty: user

I'm using Postman to test my API and I'm getting the error param is missing or the value is empty: user when making a call to http://localhost:3000/users.json to create a new user. All the parameters seem to be ok.
I set this in my application controller:
protect_from_forgery with: :null_session
My controller method is the basic scaffold generated method:
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
What am I doing wrong?
EDIT:
Here's a screenshot of what I'm doing in Postman.
The issue was that my parameters weren't wrapped up as a user object. For instance, in my case, I would have to change the parameter:
username
For:
user[username]
Doing that for all parameters made the test work.

too few arguments with scaffold code

The join method below in the teams_controller.rb is sent the following data through submission of a form using EmberJs
{"id"=>"3", "user_id"=>"42", "action"=>"join", "controller"=>"teams"}
The record is getting created with the join method below (according to the console), but the code for what happens after the save is throwing an error
ArgumentError (too few arguments):
app/controllers/teams_controller.rb:145:in `format'
app/controllers/teams_controller.rb:145:in `join'
I copied the code following the #team.save method from the Rails scaffold generator, so I'm a little surprised. The hope is that it will respond with the json, but I left in the html format just because (maybe there's a graceful degradation benefit). Can you tell me why that error's being thrown and/or how I could avoid it?
Rails method
def join
#team = Team.find(params[:id])
id = params[:user_id]
#team.user_ids = #team.user_ids.push(id)
if #team.save
format.html { redirect_to #team, notice: 'Joined Team' }
format.json { render json: #team, status: :created, location: #team }
else
format.html { render action: 'new' }
format.json { render json: #team.errors, status: :unprocessable_entity }
end
end
Update,
I should also note that, based on the line number of the error message, the method seems to be treating the format as html, however, I wanted it to be treated as json
I forgot to put respond_to do |format| around the code.
respond_to do |format|
if #team.save
format.html { redirect_to #team, notice: 'Joined Team' }
format.json { render json: #team, status: :created, location: #team }
else
format.html { render action: 'new' }
format.json { render json: #team.errors, status: :unprocessable_entity }
end
end

Resources