How to implement update controller method
There are two issues:
- You need to save your updated object
- You should be doing this within the bounds of resources (although not essential)
The first step is to ensure you're using this with the correct routes etc.
You shouldn't have an add_images
method in your controller - you could achieve what you need with edit
/update
:
#config/routes.rb
resources :food_items do
resources :images #-> if necessary, this should be its own controller rather than adding needless methods to your other controller
end
You should use the following controller setup:
#app/models/food_item.rb
class FoodItem < ActiveRecord::Base
accepts_nested_attributes_for :food_images
end
#app/controllers/food_items_controller.rb
class FoodItemsController < ApplicationController
def edit
@food_item = FoodItem.find params[:id]
@food_item.food_images.build
end
def update
@food_item = FootItem.find params[:id]
respond_to do |format|
if @food_item.update food_item_params
...
end
end
end
private
def food_item_params
params.require(:food_items).permit(:name, :category, :description, food_images_attributes: [:id, :food_item_id, :avatar]) #-> this is enough (no need to "whitelist")
end
end
This will give you the ability to load the following:
#url.com/food_items/:id/edit
#app/views/food_items/edit.html.erb
<%= form_for @food_item do |f| %>
= form_for @food_item, html: { :multipart => true } do |f|
= f.label :title
= f.text_field :title
= f.fields_for :food_images do |p|
= p.label :avatar
= p.file_field :avatar
.actions
= f.submit
<% end %>
This will submit to the "update" method, which should save the required object for you.
You should only upload one file at a time
If you need to upload multiple files, you'll need to use a gem such as cocoon
to add them. Rails is great but not magical -- it has to build a single object with each fields_for
.
I can explain more about this if required.
--
To give you context on why you should be using the edit
/ update
methods for this, you need to look up the resourceful principle for object orientated programming.
This is built on the "resources" principle put forward at the inception of HTTP -- a standardized set of technologies which allow browsers to send and retrieve data from servers.
In short, it means there are certain conventions you should abide by to keep your app extensible.
Because Ruby/Rails is object orientated, everything you do in a well-tailored application should revolve around objects. Like resources, these allow you to create a system which is both flexible and extensible if done properly.
Thus, with your code, you have to remember that you're trying to add an image to the food items object. You should therefore be editing
the food items object, updating it with the extra image; which the above code will help you achieve.
![Dengke Liu](https://lh6.googleusercontent.com/-VECbFmlRb-k/AAAAAAAAAAI/AAAAAAAAAUA/-foFxAKZwoo/photo.jpg?sz=256)
Dengke Liu
Updated on June 04, 2022Comments
-
Dengke Liu about 2 years
I am working on web app development using ruby on rails. I want to enable users to upload images for their favorite food. I have food_item model and a food_image model. In the food_item model:
has_many :food_images has_many :food_portions #this is the work done by another teammate
I also define in the food_item controller:
def food_item_params params.require(:food_items).permit(:name, :category, :description, food_images_attributes: [:id, :food_item_id, :avatar]).tap do |whitelisted| whitelisted[:portion] = params[:food_items][:portion] whitelisted[:price] = params[:food_items][:price] end