【问题标题】:How to get attributes of model in has_many :through association in Rails 5如何在 has_many 中获取模型的属性:通过 Rails 5 中的关联
【发布时间】:2018-03-02 02:34:07
【问题描述】:

所以我在 has_many :through 关联中有 2 个模型。这两个模型是膳食和食物。基本上,一顿饭可以有多个食物,一个食物可以是多餐的一部分。第三个连接模型称为meal_foods。 我进行了设置,这样当您创建新餐点时,您可以通过复选框选择餐点的所有食物。食品具有卡路里和蛋白质等属性,而膳食具有总卡路里和总蛋白质等属性。 我如何才能在制作新餐点时计算所有食物的所有属性(卡路里、蛋白质等)的值?

到目前为止,这是我的代码:

模型

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

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

class MealFood < ApplicationRecord
    belongs_to :meal
    belongs_to :food
end

膳食控制员

    def create
        @meal = Meal.new(meal_params)
        @meal.user_id = current_user.id

        @meal.total_calories = #Implement code here...

        if @meal.save
            redirect_to @meal
        else
            redirect_to root_path
        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 %>

谢谢,提前!

【问题讨论】:

    标签: ruby-on-rails database model-view-controller model has-many-through


    【解决方案1】:

    您可以使用sum 例如卡路里:

    class Meal < ApplicationRecord
        belongs_to :user, optional: true
        has_many :meal_foods
        has_many :foods, through: :meal_foods
    
        def total_calories
          foods.sum(:calories)
        end
    end
    

    Sum 适用于关联中的任何数字列。

    如果您需要将值存储在数据库中(例如,您将根据卡路里含量对餐食进行分类,并且更容易存储该值),那么您可以改为告诉餐食何时创建,它应该计算并存储卡路里,例如:

    class Meal < ApplicationRecord
        belongs_to :user, optional: true
        has_many :meal_foods
        has_many :foods, through: :meal_foods
    
        # Tells rails to run this method when each Meal is first created
        after_create :store_total_calories
    
        # actually calculates the number of calories for any given meal (can be used even after saving in the db eg if the calories changed)
        def calculate_total_calories
          foods.sum(:calories)
        end
    
        # calculates, then resaves the updated value   
        def store_total_calories
           update(total_calories: calculate_total_calories)
        end
    end
    

    注意:更多关于after_create callback here

    注意:对于所有 Just Work,无需在控制器中执行任何操作。

    【讨论】:

    • 这是否会仅计算它们所在餐点的食物卡路里总和?
    • 是的。它将为给定餐点的食物项的卡路里求和 - 因为它使用餐点本身的foods,它是一个实例方法。
    • 很好,但我不明白如何实现它。我添加方法然后呢?我在哪里使用这种方法?
    • 使用 @meal.total_calories 就像你在你的例子中一样:)
    • 您制作了新餐点吗?这个例子看起来很可靠,但只会在创建餐点时保留餐点的总卡路里。您还可以调用meal.store_total_calories 来设置现有膳食的卡路里或calculate_total_calories 来读取foods.calories 的总和。上面提供的链接中还有不同的回调,它们可以在其他时间点执行,例如当餐点更新为新食物时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多