2015-11-07 4 views
1

Я работаю над разработкой веб-приложений с использованием рубинов на рельсах. Я хочу, чтобы пользователи могли загружать изображения для своей любимой еды. У меня есть модель food_item и модель food_image. В модели food_item:Как реализовать метод контроллера обновления

has_many :food_images 
has_many :food_portions #this is the work done by another teammate 

Я также определить в контроллере food_item:

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 
+1

Почему вы сохраняете, ничего не меняя? вы только что спросили его, найдя. –

+0

@AmitBadhekaPykihStaff этот метод отображает форму для загрузки пользователем изображения, если пользователь нажимает кнопку «Сохранить», то изображение будет сохранено в базе данных. Я определил в show.html.haml, чтобы представить изображение на веб-странице. –

+0

напишите ваше мнение и ваши «рейк-маршруты», пожалуйста, – dthal

ответ

0

Как Badheka сказал: «почему вы запрашивая и просто спасение @food_item

В любом случае, уведомление что, когда вы пытаетесь создать food_images, вы сделали:

food_item_params[:food_image]['avatar'].each do |a| 
    @food_image = @food_item.food_images.create!(:avatar=>a) 
end 

Вы прошли через avatar в food_image атрибуты food_item_params

Однако, если вы проверяете food_item_params, у вас есть:

def food_item_params 
    params.require(:food_items).permit(food_images_attributes: [:id, :food_item_id, :avatar]) 
end 

С этим, по всей возможности, структура данных, что Params ожидает будет что-то вроде:

{ 
    food_items: 
    { 
     food_images_attributes: 
     { 
      id: "", 
      food_item_id: "", 
      avatar: "" 
     } 
    } 
} 

а то, что возвращается ваш food_item_params будет следующим:

{ 
     food_images_attributes: 
     { 
      id: "", 
      food_item_id: "", 
      avatar: "" 
     } 
    } 

Есть целый ряд вопросов с этим:

1) Ошибка вы получаете: param is missing or the value is empty: food_items это говорит о том, что пары, что приходит в не в формате, указанном выше. родительский атрибут food_items отсутствует, так что это первая часть вашего кода, которую необходимо исправить изнутри, где вы отправляете аватар, или совместите свой метод food_item_params с тем, чтобы соответствовать структуре того, что входит в параметры.

2) Существует не food_item_params[:food_image]['avatar'], чтобы зациклиться, так как в ваших параметрах нет food_image. У вас есть food_image_attributes, поэтому ваша петля будет на food_item_params[:food_image_attributes][:avatar]

3) Цикл через food_item_params[:food_image_attributes][:avatar] предполагает, что это массив. Если да, то то, как вы это допускаете, неверно. Вы должны указать, что это массив из внутри метода food_item_params как следующие:

def food_item_params 
    params.require(:food_items).permit(food_images_attributes: [:id, :food_item_id, avatar: []]) 
end 

Если же, как я подозреваю, что приходит через пары выглядят следующим образом:

food_images_attributes: 
     { 
      id: "", 
      food_item_id: "", 
      avatar: [] 
     } 

Тогда ваш метод food_item_params должен выглядеть следующим образом:

def food_item_params 
    params.require(:food_images_attributes).permit(:id, :food_item_id, avatar: []) 
end 

Я советую вам проверить Params и вставить то, что он выглядит как здесь.

И как последнее слово, проверьте, что вы отправляете из представления, и соответствующим образом установите ваш контроллер или проверьте, что вы хотите, чтобы контроллер ожидал, и отправьте его с точки зрения.

+0

Я уже принял ваш совет. Когда я определяю 'food_item_params' как –

+0

Привет @SunnyK, я уже принял ваш совет. Я петлю на 'food_item_params [: food_image_attributes] [avatar]'. Однако, когда я определил 'food_item_params', как вы делали это в последний раз, я получил ошибку' param отсутствует или значение пустое: food_images_attributes' при запуске огурца. Когда я сохранял то же самое и использовал 'avatar: []', я получил ту же ошибку 'param отсутствует или значение пусто: food_items' снова. –

+0

Можете ли вы показать мне, что происходит через ваши параметры? [Вы можете использовать pry] (https://rubygems.org/gems/pry/versions/0.10.3) или скопировать его непосредственно с консольного терминала вашего сервера –

0

Вам нужно изменить food_item_params метод:

От:

def food_item_params 
    params.require(:food_items).permit(food_images_attributes: [:id, :food_item_id, :avatar]) 
end 

To:

def food_item_params 
    params.require(:food_item).permit(food_images_attributes: [:id, :food_item_id, :avatar]) 
end 

Кроме того, вы можете улучшить свой код:

Добавить accepts_nested_attributes_for: food_images в food_item, затем внесите изменения в метод контроллера

def add_image 
    @food_item = FoodItem.find(params[:id]) 
    respond_to do |format| 
     if @food_item.update_attributes(food_item_params) 
      format.html { redirect_to @food_item, notice: 'Images uploaded successfully' } 
     else 
     format.html { redirect_to add_image_food_item_path} 
    end 
    end 
end 
+0

Я пробовал, что вы сделали, но меняя: food_items к единственному будет разрушать другие функции. Также в методе add_image он не создает объекты изображения для хранения файла, который я загрузил через форму. –

+0

Вы добавили accepts_nested_attributes_for в модель? – user3506853

1

Есть два вопроса:

  1. Вы должны сохранить ваш обновленный объект
  2. Вы должны делать это в рамках ресурсов (хотя и не обязательно)

Resourceful

Первым шагом является обеспечение вы используете это с правильными маршрутами и т.д.

Вы не должны иметь add_images метод в контроллере - вы могли бы добиться того, что вам нужно с 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 

Вы должны использовать следующие настройки контроллера:

#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 

Th это даст вам возможность загружать следующие:

#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 %> 

Это представит метод «обновления», который должен сохранить нужный объект для вас.

Вы должны загрузить только один файл за раз

Если вам нужно загрузить несколько файлов, вы должны будете использовать драгоценный камень, такой как cocoon, чтобы добавить их. Рельсы велики, но не волшебны - он должен построить один объект с каждым fields_for.

я могу объяснить подробнее об этом в случае необходимости.

-

Чтобы дать вам контекст о том, почему вы должны использовать методы edit/update для этого, вы должны смотреть вверх находчивый принцип объектно-ориентированное программирование.

enter image description here

Это строится по принципу «ресурсов», выдвинутый на inception of HTTP - стандартный набор технологий, которые позволяют браузерам отправлять и получать данные с серверов.

Короче говоря, это означает, что есть определенные conventions, которые вы должны соблюдать, чтобы ваше приложение расширялось.

Поскольку Ruby/Rails - это object orientated, все, что вы делаете в хорошо адаптированном приложении, должно вращаться вокруг объектов. Как и ресурсы, они позволяют создать систему, которая является гибкой и расширяемой. если сделано правильно.

Таким образом, с помощью кода, вы должны помнить, что вы пытаетесь добавить изображение к продуктов питания объектов. Таким образом, вы должны быть editing объект продуктов питания, обновление с дополнительным изображением; который вышеприведенный код поможет вам достичь.

+0

Привет @ Рич Пек, я последовал твоему ответу. Я удалил маршруты и метод контроллера для добавления изображений. Я помещаю форму в edit.html.haml, и это вызовет метод обновления для сохранения объекта. Тем не менее, метод обновления был реализован моими командами, и мне сложно добавить код к нему, чтобы избежать ломающихся текущих тестов. Я поставлю метод обновления в свой вопрос. –

+0

Хорошо с нетерпением жду этого! –

Смежные вопросы