具有 has_many 的模型中的属性总和:通过关联在 Rails 5 中不起作用

Sum of attributes in model with has_many :through association not working in Rails 5

所以我有 2 个模型。膳食和食品。一顿饭可以有多种食物,一种食物可以是多餐的一部分。基本上是一个多对多的关联。我用 has_many :through 做到了这一点,加入模型称为 MealsFood。创建新餐时,您可以通过复选框选择要添加的食物。 foods table 有一个名为 "calories" 的列,而 meals table 有一个名为 "total_calories" 的列,它计算膳食中所有食品的总和。 问题是它不工作。

这是我目前所拥有的...

型号

class Meal < ApplicationRecord
    belongs_to :user, optional: true
    has_many :meal_foods
    has_many :foods, through: :meal_foods

    def calc_total_calories
        self.foods.sum(:calories)
    end
end

class MealFood < ApplicationRecord
  belongs_to :meal
  belongs_to :food
end

class Food < ApplicationRecord
    has_many :meal_foods
    has_many :meals, through: :meal_foods
end

膳食控制器

class MealsController < ApplicationController
    def index
    end

    def new
        @meal = Meal.new
    end

    def create
        @meal = Meal.new(meal_params)
        @meal.calc_total_calories

        if @meal.save
            redirect_to @meal
        else
            redirect_to root_path
        end
    end

    private

    def meal_params
        params.require(:meal).permit(:user_id, :meal_type, :date, 
  :total_calories, :total_carbohydrates, :total_fat, food_ids:[])
    end
end

查看(用餐新动作)

            <%= form_for(@meal) do |f| %>
                <div class="field">
                    <%= f.label :meal_type %>
                    <%= f.select :meal_type, ["Breakfast", "Lunch", "Dinner", "Morning Snack", "Afternoon Snack, Evening Snack"] %>
                </div>

                <div class="field">
                    <% Food.all.each do |food| %>
                        <%= check_box_tag "meal[food_ids][]", food.id %>
                        <%= food.name %>
                    <% end %>
                </div>

                <div class="field">
                    <%= f.submit class: "button button-highlight button-block" %>
                </div>
            <% end %>

注意膳食模型中的 def calc_total_calories。这是我用来计算卡路里的方法,但它不起作用。我在 Meals 控制器的创建方法中使用它。 请帮忙!提前致谢:)

看起来你实际上并没有用 calc_total_calories 做任何事情 - 它没有分配给控制器中的任何东西,也没有分配给 中的任何东西型号。

您可能希望模型方法将其分配给某些东西,如下所示:

def calc_total_calories
    self.total_calories = self.foods.sum(:calories)
end

假定您的 meal 模型中有一列名为 total_calories

这看起来像您要找的东西吗?如果您有任何问题,请告诉我。

我在想,也许你想做这样的事情:

class MealsController < ApplicationController

  def index
  end

  def new
      @meal = Meal.new
  end

  def create
    @meal = Meal.new(meal_params)

    if @meal.save
      @meal.update(total_calories: @meal.calc_total_calories)
      redirect_to @meal
    else
      redirect_to root_path
    end
  end

  private

  def meal_params
    params.require(:meal).permit(:user_id, :meal_type, :date, :total_calories, :total_carbohydrates, :total_fat, food_ids:[])
  end

end

在您的原始代码中,您没有在 @meal 上设置 total_calories 属性,只是调用 calc_total_calories 方法(这可能正确计算了总卡路里)。

在 SRack 提供的答案中,您正在设置,但从未保存 total_calories 属性。

update 将同时设置和保存属性。

顺便说一句,您一定要考虑如何处理与 meal 关联的 foods 的更改,否则您的 total_calories 可能会变得陈旧和不正确。

您可以在保存后在回调中更新总卡路里。

after_save :update_calories

def update_calories
  update_attributes(total_calories: calc_total_calories)
  return true
end