Frage

Ich habe eine Rails-Anwendung, dass die Modelle ein Haus. Es ist ein Haus-Modell, das viele Parameter und es has_many rooms hat. Ein Zimmer verfügt über einen house_id und einen Namen. Ich habe auch http://github.com/ryanb/complex-form-examples viele Lichter und small_appliances auf Raum hinzugefügt werden. Komplex-Form-Beispiel verwendet RJS und partials dies zu erreichen.

Es ist ein Controller-Rechner genannt, die ist, was die Benutzer auf die Anwendung zugreifen verwenden. Wenn die Senden-Schaltfläche auf Rechner gedrückt wird, leitet es an eine add_rooms Seite (in app/views/calculator/add_rooms.html.erb) Seite, wo der Benutzer in das Haus add rooms kann. Die add_rooms Seite verwendet eine teilweise von app/views/rooms/_room_form.html.erb. Ich habe nicht in der Lage, dies zu Anzeige zu bekommen, wie Schienen immer für die Dinge in der app / views / Rechner Ordner sucht.

Wie kann ich das Display bekommen? Beachten Sie auch, dass ich das Haus der id zu sparen, wenn das Zimmer zu speichern.

Hier alle relevanten Code (hoffe ich):

Update

Wenn ich die zwei add_child_link Kommentar aus. Die Seite macht. Allerdings, wenn ich klicken Sie auf Absenden ich eine neue Fehlermeldung:

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'

Wenn ich den small_application Teil entfernen, geschieht das Gleiche für Licht. Ich denke, es hat etwas mit accepts_nested_attributes_for in dem Raummodell zu tun. Ich habe den Code unten hinzugefügt. Ich habe auch den house.rb Code zu hinzugefügt.

app / models / room.rb

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 / Rechner / 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 / Zimmer / _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

Danke,
Ryan

War es hilfreich?

Lösung

Sehr seltsam - wenn Sie schreiben <%= render :partial => 'room_form' %> als Schienen davon aus, dass es app/views/calculator/_room_form.html.erb ist, aber im Fall von <% = render: partial => 'Zimmer / room_form' %> es wird davon ausgegangen, dass es app/views/rooms/_room_form.html.erb

Sehen Sie Ihre Log - dort werden Sie sehen, welche partials gemacht wurden

Andere Tipps

Ich weiß, diese Frage ist alt, aber ich lief in das gleiche Problem und schaffte es zu lösen.

Um genau zu sein auch ich folgenden ryan beizbrühen komplexe Formen Beispiele.

Meine Form war nicht mit dem gleichen Fehler zu machen:

undefined method `reflect_on_association' for NilClass:Class

Ich kommentierte den add_child_link Helfer und die gerenderte Form aber nach Vorlage Ich habe:

ChildModel expected, got Array

Nach viel headscratching machte ich eine einfache Änderung, dass Fest alles:

-- form_for :project
++ form_for @project

Das ist richtig, nur das Symbol für eine Instanz variable Schalt machte es Arbeit.

Hope dies hilft jemand anderes, stecken

bekommt

Das Problem ist, dass Sie nicht über ein room Objekt definiert ist, wenn Sie versuchen, ein Kind Link hinzuzufügen.

render :partial => 'rooms/room_form', :object => Room.new
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top