从另一个模型渲染部分 [英] Render partial from another model

查看:80
本文介绍了从另一个模型渲染部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可以模拟房屋的Rails应用程序.有一个房屋模型,其中有许多参数,并且它has_many rooms.一个房间有一个house_id和一个名称.我还使用了 http://github.com/ryanb/complex-form-examples允许将许多灯光和small_appliances添加到房间中. complex-form-example示例使用RJS和partials完成此操作.

I have a rails application that models a house. There is a house model that has many parameters and it has_many rooms. A room has a house_id and a name. I've also used http://github.com/ryanb/complex-form-examples to allow many lights and small_appliances to be added to room. complex-form-example uses RJS and partials to accomplish this.

有一个称为计算器的控制器,用户将使用该控制器来访问该应用程序.当按下计算器上的提交按钮时,它将重定向到add_rooms页(位于app/views/calculator/add_rooms.html.erb中)页面,用户可以在其中add rooms到房屋. add_rooms页面使用app/views/rooms/_room_form.html.erb中的部分内容.由于Rails总是在app/views/calculator文件夹中寻找内容,因此我无法显示此内容.

There is a controller called calculator that is what users will use to access the application. When the submit button on calculator is pressed, it redirects to an add_rooms page (located in app/views/calculator/add_rooms.html.erb) page where the user can add rooms to the house. The add_rooms page uses a partial from app/views/rooms/_room_form.html.erb. I haven't been able to get this to display, as rails is always looking for things in the app/views/calculator folder.

如何显示此内容?另请注意,保存房间时,我需要保存房子的ID.

How can I get this to display? Note also that I need to save the house's id when saving the room.

这里是所有相关代码(我希望如此):

Here is all of the relevant code (I hope):

如果我将两个add_child_link注释掉.页面呈现.但是,当我单击提交"时,会收到新的错误消息:

If I comment out the two add_child_link. The page renders. However, when I click submit I get a new error message:


ActiveRecord::AssociationTypeMismatch in CalculatorController#add_room

SmallAppliance(#49096610) expected, got Array(#1560620)

RAILS_ROOT: C:/Users/ryan/Downloads/react
Application Trace | Framework Trace | Full Trace

C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations/association_proxy.rb:263:in `raise_on_type_mismatch'
C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations/association_collection.rb:320:in `replace'
C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations/association_collection.rb:320:in `each'
C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations/association_collection.rb:320:in `replace'
C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations.rb:1322:in `small_appliances='
C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2744:in `send'
C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2744:in `attributes='
C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2740:in `each'
C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2740:in `attributes='
C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2438:in `initialize'
C:/Users/ryan/Downloads/react/app/controllers/calculator_controller.rb:31:in `new'
C:/Users/ryan/Downloads/react/app/controllers/calculator_controller.rb:31:in `add_room'

如果我删除了small_application部分,同样的事情也会发生.我认为这与房间模型中的accepts_nested_attributes_for有关.我在下面添加了代码.我还添加了house.rb代码.

If I remove the small_application part, the same thing happens for light. I think it has something to do with accepts_nested_attributes_for in the room model. I've added the code below. I've also added the house.rb code too.

class Room < ActiveRecord::Base
  belongs_to :house
  has_many :lights, :dependent => :destroy
  has_many :small_appliances, :dependent => :destroy
  validates_presence_of :name
  accepts_nested_attributes_for :lights, :reject_if => lambda { |a| a.values.all?(&:blank?) }, :allow_destroy => true
  accepts_nested_attributes_for :small_appliances, :reject_if => lambda { |a| a.values.all?(&:blank?) }, :allow_destroy => true         
end

app/models/house.rb

class House < ActiveRecord::Base
  has_many :rooms

  # validation code not included

  def add_room(room)
    rooms << room
  end

end

app/controllers/calculator_controller.rb

class CalculatorController < ApplicationController
  def index
  end

  def save_house
    @house = House.new(params[:house])
    respond_to do |format|
      if @house.save
        format.html { render :action => 'add_rooms', :id => @house }
        format.xml { render :xml => @house, :status => :created, :location => @house }
      else
        format.html { render :action => 'index' }
        format.xml  { render :xml => @house.errors, :status => :unprocessable_entity }
      end
    end
  end

  def add_rooms
    @house = House.find(params[:id])
    @rooms = Room.find_by_house_id(@house.id)

  rescue ActiveRecord::RecordNotFound
    logger.error("Attempt to access invalid house #{params[:id]}")
    flash[:notice] = "You must create a house before adding rooms"
    redirect_to :action => 'index'
  end

  def add_room
    @house = House.find(params[:id])
    @room = Room.new(params[:room])

    respond_to do |format|
      if @room.save
        @house.add_room(@room)
        @house.save
        flash[:notice] = "Room \"#...@room.name}\" was successfully added."
        format.html { render :action => 'add_rooms' }
        format.xml { render :xml => @room, :status => :created, :location => @room }
      else
        format.html { render :action => 'add_rooms' }
        format.xml  { render :xml => @room.errors, :status => :unprocessable_entity }
      end
    end
  rescue ActiveRecord::RecordNotFound
    logger.error("Attempt to access invalid house #{params[:id]}")
    flash[:notice] = "You must create a house before adding a room"
    redirect_to :action => 'index'
  end

  def report
    flash[:notice] = nil
    @house = House.find(params[:id])
    @rooms = Room.find_by_house_id(@house.id)
  rescue ActiveRecord::RecordNotFound
    logger.error("Attempt to access invalid house #{params[:id]}")
    flash[:notice] = "You must create a house before generating a report"
    redirect_to :action => 'index'
  end

end

app/views/calculator/add_rooms.html.erb

<div id="addRooms">
  <p>House id is <%= @house.id %></p>

  <h3>Your rooms:</h3>
  <% if @house.rooms %>
  <ul>
    <% for room in @house.rooms %>
    <li>
      <%= h room.name %> has <%= h room.number_of_bulbs %>
      <%= h room.wattage_of_bulbs %> watt bulbs, in use for
      <%= h room.usage_hours %> hours per day.
    </li>
    <% end %>
  </ul>
  <% else %>
  <p>You have not added any rooms yet</p>
  <% end %>

  <%= render :partial => 'rooms/room_form' %>

  <br />
  <%= button_to "Continue to report", :action => "report", :id => @house %>
</div>

app/views/rooms/_room_ form.html.erb

app/views/rooms/_room_form.html.erb

<% form_for :room, :url => { :action => :add_room, :id => @house } do |form| %>
  <%= form.error_messages %>
  <p>
    <%= form.label :name %><br />
    <%= form.text_field :name %>
  </p>

  <h3>Lights</h3>
  <% form.fields_for :lights do |light_form| %>
    <%= render :partial => 'rooms/light', :locals => { :form => light_form } %>
  <% end %>
  <p class="addLink"><%= add_child_link "[+] Add new light", form, :lights %></p>

  <h3>Small Appliances</h3>
  <% form.fields_for :small_appliances do |sm_appl_form| %>
    <%= render :partial => 'rooms/small_appliance', :locals => { :form => sm_appl_form } %>
  <% end %>
  <p class="addLink"><%= add_child_link "[+] Add new small appliance", form, :small_appliances %></p>

  <p><%= form.submit "Submit" %></p>
<% end %>

application_helper.rb

module ApplicationHelper
  def remove_child_link(name, form)
    form.hidden_field(:_delete) + link_to_function(name, "remove_fields(this)")
  end

  def add_child_link(name, form, method)
    fields = new_child_fields(form, method)
    link_to_function(name, h("insert_fields(this, \"#{method}\", \"#{escape_javascript(fields)}\")"))
  end

  def new_child_fields(form_builder, method, options = {})
    options[:object] ||= form_builder.object.class.reflect_on_association(method).klass.new
    options[:partial] ||= method.to_s.singularize
    options[:form_builder_local] ||= :form
    form_builder.fields_for(method, options[:object], :child_index => "new_#{method}") do |form|
      render(:partial => options[:partial], :locals => { options[:form_builder_local] => form })
    end
  end
end

谢谢,
瑞安

推荐答案

非常奇怪-如果您编写<%= render :partial => 'room_form' %>,那么rails会假定它是app/views/calculator/_room_form.html.erb,但在<%= render:partial =>的情况下'rooms/room_form'%>,它将假定它为app/views/rooms/_room_form.html.erb

Very strange — if you write <%= render :partial => 'room_form' %> than rails will assume that it is app/views/calculator/_room_form.html.erb, but in case of <%= render :partial => 'rooms/room_form' %> it will assume that it is app/views/rooms/_room_form.html.erb

观看您的日志-在那里您将看到呈现了哪些部分

Watch your log — there you will see which partials were rendered

这篇关于从另一个模型渲染部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆