【问题标题】:accepts_nested_attributes_for not saving nested attributesAccepts_nested_attributes_for 不保存嵌套属性
【发布时间】:2012-12-28 04:32:39
【问题描述】:

我已经被这个问题困扰了好几天了。这是我的第一个 Rails 应用程序,我快要完成了,只是被它大大拖慢了。

我读到使用 Accepts_nested_attributes_for 是解决我在配方中嵌套成分以用于表单的问题的最佳解决方案,但到目前为止我还没有运气。我已经阅读了有关该主题的所有内容。 API 说该模型现在有一个(在我的情况下)成分_attributes= 方法,我还没有看到。我尝试在控制台中使用带有哈希的 update_attributes

recipe.update_attrubutes {:ingredients_attributes=>[{:name=>"Test Ingredient"}]}

返回 true,但显示配方对象没有变化。

我尝试了很多方法,我的第一个方法是在我的视图中使用 forms_for 内部的 fields_for。由于这不起作用并且我测试代码无济于事,我开始深入研究,问题肯定比视图更深。

任何帮助将不胜感激。我的代码如下

配方模型

对于 db 样式名称和显示样式名称之间的混淆转换,我们深表歉意。到目前为止,这是我维护它们的最佳解决方案。

class Recipe < ActiveRecord::Base

  DISH_TYPES={""=>"", "Breakfast"=>"breakfast", "Lunch"=>"lunch", "Soup"=>"soup", "Entree"=>"entree", "Desert"=>"desert"}
  SEASONS={"Any Season"=>"any", "Fall"=>"fall", "Winter"=>"winter", "Spring"=>"spring", "Summer"=>"summer"}
  DIETS={""=>"", "Vegan"=>"vegan", "Vegetarian"=>"vegetarian", "Omnivore"=>"omnivore"}

  DISH_TYPES_R={""=>"", "breakfast"=>"Breakfast", "lunch"=>"Lunch", "soup"=>"Soup", "entree"=>"Entree", "desert"=>"Desert"}
  SEASONS_R={"any"=>"Any Season", "fall"=>"Fall", "winter"=>"Winter", "spring"=>"Spring", "summer"=>"Summer"}
  DIETS_R={""=>"", "vegan"=>"Vegan", "vegetarian"=>"Vegetarian", "omnivore"=>"Omnivore"}

  attr_protected :user_id
  # Do NOT include user_id in the attr_accessible method, to avoid
  # the possibility of it being changed externally.
  belongs_to :user
  validates_presence_of :user  
  has_many :ingredients, dependent: :destroy # , inverse_of: :recipe

  # Allows for forms to write attributes down the hierarchy.
  accepts_nested_attributes_for :ingredients, allow_destroy: true , reject_if: lambda { |a| a[:content].blank? }

  before_save do
    # Lowercase and convert to strings all of the attributes
    # that require a specific format, namely the values in the
    # constant hashes above.
    STRING_ATTRIBUTES.each do |s|
      self.send("#{s}=".to_sym, self.send(s).downcase.to_s)
    end
  end

  validates :user_id, presence: true
  validates :name,  presence: true,
                    length: { maximum: 64 } #,uniqueness: true
  validates :dish_type, inclusion: { in: DISH_TYPES.values }
  validates :season, inclusion: { in: SEASONS.values }
  validates :diet, inclusion: { in: DIETS.values}
  validates :directions,  presence: true,
                          length: { maximum: 8192 }

  validates_associated :ingredients


  default_scope order: "recipes.created_at DESC"


  def method_missing (method)
    method = method.to_s
    if method.slice!("display_")
      if STRING_ATTRIBUTES.include?(method.to_sym)
        hash_name = method.upcase + 'S_R'
        Recipe.const_get(hash_name)[self.send(method.to_sym)]
      else
        method
      end
    else 
      method.class
    end
  end

  private

    STRING_ATTRIBUTES = [:dish_type, :season, :diet]

end

成分模型

class Ingredient < ActiveRecord::Base

  attr_protected :id, :recipe_id
  belongs_to :recipe

  validates_presence_of :name
  #validates_presence_of :recipe
end

配方控制器

我了解到我不应该更改控制器中的任何内容。我只添加了一行,因此成分表显示在我的视图中

class RecipesController < ApplicationController
  before_filter :signed_in_user, only: [:create, :edit, :destroy]

  def index
    @recipes = Recipe.all
  end

  def new
    if signed_in?
      @recipe = current_user.recipes.build 
      @recipe.ingredients.build
    else
      flash[:error] = "First you have to register! Sign up here and start adding recipes ASAP."
      redirect_to signup_path
    end
  end

  def create
    @new_recipe = current_user.recipes.build(params[:recipe])
    if @new_recipe.save
      flash[:success] = "You've successfully added #{@new_recipe.name}!"
      redirect_to @new_recipe
    else
      redirect_to 'new'
    end
  end

  def edit
    @recipe = Recipe.find(params[:id])
  end

  def show
    @recipe = Recipe.find(params[:id].to_i)
  end

end

配料控制器

我认为成分控制器没有任何用处,因为成分(目前)只能通过其父配方访问。

我会根据要求包含这些观点,但正如我之前所说,我不相信它是高层次的。

【问题讨论】:

    标签: ruby-on-rails nested-forms nested-attributes


    【解决方案1】:
    1. 您需要为Recipe 模型设置attr_accessible 并添加:ingredients_attributes
    2. 正如我在您的配置中看到的,您有 reject_if: lambda { |a| a[:content].blank? } 用于 ingrediens_attributes 并且您仅使用名称进行设置

    【讨论】:

    • 不敢相信我错过了。我在网上找到的,但我认为 :content 指的是整个属性内容。我之前已将其注释掉以查看是否导致问题,但我仍然有它。它现在看起来正在工作!你所说的attributes_acceptable是什么意思?我没有看到对该方法的任何引用。
    • 这是一个错误的输入 - 我的意思是attr_accessible
    • 这是有道理的。根据我最近对该主题的阅读,我的attr_protected :user_id 行与attr_accessible 方法相反,因为它创建了对除:user_id 之外的所有内容的访问。所以我相信现在这很好。你同意吗?
    猜你喜欢
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-09
    • 1970-01-01
    相关资源
    最近更新 更多