Render Teil aus einem anderen Modell
-
21-09-2019 - |
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
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