尝试从父对象控制器创建子类对象

时间:2013-04-06 02:37:17

标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.1 ruby-on-rails-3.2

我正在试图弄清楚如何抓住一个名为“meal”的对象的当前实例来创建一个属于它的食物对象。

它适用于控制台...它很简单,就像这样:

user = User.first
user.meal.first.meal_foods.create

用户可以吃很多餐,每餐可以有很多餐食。

对我来说,挑战在于食物控制者在创造我的饭食时的创造动作。

(我在这里使用STI因此是“食物”控制器和“meal_food”名称)

目前,创建操作如下所示:

 @food = current_user.meal.meal_foods.build 

我也试过这个,因为复制对象名称的工作原理

 @food = current_user.meal.meal_food.build 

这是两个

的错误
undefined method `meal_foods' for [#<Meal id: 17, user_id: 1, meal_name: "Meal">]:ActiveRecord::Relation

更新

我在这里特别提到的问题是选择正确的餐点来制作餐食。

在控制台中我可以选择第一个,这很好。但是在食物控制器中,我需要选择正确的膳食来创建一个meal_food。

写饭。首先要为该用户选择第一餐。如果我想从5中选择第3餐,我需要找到一种方法来获取该餐的ID。

我刚试过这个:

<%= link_to "new food", foods_path(id: meal.id), method: :create %>

传入meal.id作为可以在foods_controller中使用的参数。然后在food_controller中我做了:

@meal_food = current_user.meals.find_by_id(params[:id]).meal_foods.build 

看起来就像它正在提交一样,因为页面重新加载了成功消息,但是没有创建meal_food,所以它只是没有显示出来。

我检查了控制台,并没有为这个用户的第一餐创造新的食物。


好的,我意识到我上面写的link_to创建了这个网址:

foods?id=29

并且我用来检索此id的方法无效,因为params [:id]正在查找路径ID,而不是此url id。

提前致谢!


模特:

class Meal < ActiveRecord::Base
  before_save :sanitize
  has_and_belongs_to_many :meal_foods
  attr_accessible :meal_name

  def sanitize
    self.meal_name = "Meal"
  end
end 


class Food < ActiveRecord::Base
  attr_accessible :brand, :carbs, :fat, :name, :protien, :type

end   

class MealFood < Food
  has_and_belongs_to_many :meals
end 

class User < ActiveRecord::Base

  has_many :meal, dependent: :destroy
  has_many :custom_foods, dependent: :destroy 

控制器:

class FoodsController < ApplicationController
  #functions
  def create

    #this is where I need to grab the correct meal, and then create a meal_food for it...

    if @meal_food.save!
      flash[:success] = "Food created successfully!"
      redirect_to meal_path(current_user.id)
    else
      flash[:error] = "Food couldn't be created."
      redirect_to meal_path(current_user.id)
    end
 end
end 

局部模板:

这是重复显示每餐的膳食部分。它有link_to用于创建一顿餐,该餐将属于它的用餐。

<tr>
  <thead class=meal-thead>
   <td class=meal-thead-name> <%= meal.meal_name %> </td>
     <th> </th>
     <th> </th>
     <th> </th>
     <th> </th>
     <th> <%= link_to "x", meal_path(meal.id), method: :delete %> </th>
  </thead>

  <tbody class=meal-tbody>

  <%# get reference to current meal and its foods %>
  <%= render meal.meal_foods %>

  <td class=remove-td-center> <%= link_to "new food", foods_path, method: :create %> </td> 
 </tbody>    
</tr> 

2 个答案:

答案 0 :(得分:1)

有时你会说User.meal.meal_foods,有时你会说User.meal.first.meal_foods。 User.meal是一个Meals数组,因此从控制台User.meal.first.meal_foods起作用,并且在您的代码中User.meal.meal_foods不会给您任何方法错误。此外,你应该在你的代码中使用多餐,并用has_many饭换掉has_many饭。

答案 1 :(得分:1)

一些事情:

  1. “has_many:meal,dependent :: destroy”应该是“has_many:meal,dependent :: destroy” has_many关联名称是复数。如果您只想在这里使用一个,请改用has_one。
  2. 这一行是错的:@ food = current_user.meal.meal_food.build,因为饭是has_many,所以你需要一个“第一”。此外,它不会返回食物,而是食物,所以你应该这样说,否则你会让自己感到困惑:

    @meal_food = current_user.meal.first.meal_food.build

  3. 对我来说,对于MealFood =&gt;一个更好的名字是服务。然后你的饭菜可以吃多份,每份都可以吃。不是一个错误,只是更容易理解。然后你有以下代码。请注意,我没有看到STI中食物的重点 - 简单地将食物的数量放在食物表中就更有意义了,那么你根本就不需要STI。

      class Meal < ActiveRecord::Base
        before_save :sanitize
        has_many :servings
        has_many :foods, :through => :servings
        attr_accessible :meal_name
    
        def sanitize
          self.meal_name = "Meal"
        end
      end 
    
    
      class Food < ActiveRecord::Base
        attr_accessible :brand, :carbs, :fat, :name, :protein, :type
        has_many :servings, :inverse_of => :food
      end   
    
      class Serving < ActiveRecord::Base
        attr_accessible :amount
        has_many :foods
        has_many :meals
      end 
    
      class User < ActiveRecord::Base
        has_many :meals, dependent: :destroy
      end
    

    HTH