【问题标题】:rails 4 nested form fields_for are not displayedrails 4嵌套表单fields_for不显示
【发布时间】:2015-03-29 14:32:27
【问题描述】:

我刚开始学习 Rails 4.2。 问题是表单中的一个字段没有显示出来。

我有餐厅、类别和一道菜。在创建菜品时,类别和餐厅也将通过 /dishes/new 输入。

预期行为:显示菜肴、类别和餐厅字段。

实际行为:仅显示 Dish 和 Category 字段。

这是我的模型

models/restaurant.rb

class Restaurant < ActiveRecord::Base
  has_many :categories
  has_many :dishes, :through => :categories
end

models/category.rb

class Category < ActiveRecord::Base
  belongs_to :restaurant
  has_many :dishes
end

models/dish.rb

class Dish < ActiveRecord::Base
  belongs_to :category
  validates :name, :price, :category, :restaurant, :presence => true
  accepts_nested_attributes_for :restaurant, :category
end

菜控制器

  def new
    # I think this is where
    # I am making a mistake
    @dish = Dish.new
    category = @dish.build_category
    restaurant = category.build_restaurant
  end

  def create
    @dish = Dish.new(dish_params)

    respond_to do |format|
      if @dish.save
        .... # default stuff #
      end
    end
  end

# strong params
  def dish_params
      params.require(:dish).permit(:name, :description, :price, restaurant_attributes: [:name], category_attributes: [:name])
  end

菜肴视图/菜肴/_form.html.erb

    <%= form_for(@dish) do |f| %>
      <% if @dish.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@dish.errors.count, "error") %> prohibited this dish from being saved:</h2>

          <ul>
          <% @dish.errors.full_messages.each do |message| %>
            <li><%= message %></li>
          <% end %>
          </ul>
        </div>
      <% end %>

      <div class="field">
        <%= f.label :nameWoW %><br>
        <%= f.text_area :name %>
      </div>
      <div class="field">
        <%= f.label :description %><br>
        <%= f.text_area :description %>
      </div>
      <div class="field">
        <%= f.label :price %><br>
        <%= f.number_field :price %>
      </div>

  *** The restaurant name field is not being displayed **
      <%= f.fields_for :restaurant do |restaurant| %>
        <div class="field">
          <%= restaurant.label :Restname %><br>
          <%= restaurant.text_area :name %>
        </div>
      <% end %>

      <%= f.fields_for :category do |category| %>
        <div class="field">
          <%= category.label :Catname %><br>
          <%= category.text_area :name %>
        </div>
      <% end %>

      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>

我已经按照 Rails 指南中的步骤进行操作,浏览了有关 stackoverflow 的问题并阅读了一些博客文章,但无法找出问题所在。一些微观层面的错误阻碍了我:(。有谁知道出了什么问题?

提前致谢。

更新:

嘿,我找到了解决方案。

 def new
    @dish = Dish.new
    @dish.build_category
    @dish.category.build_restaurant
  end

这很好用。但这只是实际解决方案的一部分。我还必须做很多 /dish/create 控制器修改。我认为整个解决方案必须放在博客文章中。否则它没有任何意义。我很快就会在这里发布和更新它。

【问题讨论】:

  • 你写过那篇博文吗?

标签: ruby-on-rails ruby ruby-on-rails-4 erb


【解决方案1】:

你可以在你的dish.rb中添加这个

class Dish
  delegate :restaurant, to: :category
end

或者你可以这样做

  <%= f.fields_for :restaurant, @dish.category.restaurant do |restaurant| %>
    <div class="field">
      <%= restaurant.label :Restname %><br>
      <%= restaurant.text_area :name %>
    </div>
  <% end %>

【讨论】:

  • 这些方法不能开箱即用。在第一次进近后,该字段仍然丢失。在dish#new控制器中,我修改为这个def new@dish = Dish.new category = @dish.build_category restaurant = @dish.build_restaurant end 2nd Approach,破坏了很多东西
  • restaurant = @dish.build_restaurant 不会这样工作,你仍然需要这样做@dish = Dish.new category = @dish.build_category restaurant = category.build_restaurant
  • 我真的不认为restaurant = category.build_restaurant 对@dish 对象有任何作用。之前没用。
【解决方案2】:

我认为你不见了:

class Dish
  belongs_to :restaurant, through: :category
end

你有它在另一边(很多)但不在那里。您可以通过尝试在表单上输出 @dish.restaurant 来测试这一点(应该为空,但不能为零)。

【讨论】:

  • 嘿,我尝试了您的解决方案,但它不起作用,因为 belongs_to through 无效。我在一开始就从 Rails 指南中检查了这一点。
  • 如果我只是在 Dish 模型中添加 belongs_to :restaurant ,我被要求为从 Dish 到 Restaurant 的外键创建迁移,这违背了 Category 模型作为直通表的目的。是的,添加 add belongs_to :restaurant 并创建迁移工作正常,但从数据库模式的角度来看并不优雅。不确定我是否期望太优雅。
【解决方案3】:
def new
  # I think this is where
  # I am making a mistake
  @dish = Dish.new
  category = @dish.category.build
  restaurant = category.restuarant.build
end

【讨论】:

  • category**.build** 和 category.restaurant**.build** 给了我这个错误NoMethodError: undefined method `build' for nil:NilClass
  • 在你的控制器中尝试 restaurant = category.restaurants.new
  • 嘿,我找到了解决方案。 @dish.build_category,然后是 @dish.category.build_restaurant。这很好用。
猜你喜欢
  • 2013-06-15
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
  • 2018-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多