Odd way of using nested forms (Rails)
I'm writing a (text) messaging app with Rails. I'm using nested_forms to allow you to send a message to multiple people.
In the controller, I instantiate a new Message object, then for each Member, build a Recipient object (child of Message). In the form, I display a checkbox next to each recipient. I want it so that the new Message object only has the recipients that have checks next to them. This is not working.
So by the time the form is rendered, Recipient objects are instantiated for all members. In other words, by default, a message gets sent to each member, unless specified not to. But I want to use the form to allow the user to specify who he wants the messages sent to
Here are my models:
class Message < ActiveRecord::Base
has_many :recipients
accepts_nested_attributes_for :recipients
#columns: body:string, from:string, from_member_id:integer
end
class Member < ActiveRecord::Base
#columns phone:string, name:string
end
class Recipient < ActiveRecord::Base
belongs_to :message
belongs_to :member
#开发者_开发知识库columns: member_id:integer, message_id:integer
end
messages_controller.rb:
def new
@message = Message.new
@members = Member.all
@members.each do |member|
@message.recipients << Recipient.new(:member_id => member.id)
end
end
def create
@message = Message.new(params[:message])
redirect_to '/somewhere'
end
...
And here's my form for Message
(app/views/message/new/html.erb)
<%= form_for(@message) do |f| %>
<% if @message.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@message.errors.count, "error") %> prohibited this message from being saved:</h2>
<ul>
<% @message.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.fields_for :recipients do |builder| %>
<div class="field">
<input type="checkbox" value="<%= builder.object.member_id %>" name="recipients[id]" />
/*WHAT GOES ^^^HERE^^^? */
<%= builder.object.member.name %>
</div>
<% end %>
<div class="field">
<%= f.label :body %><br />
<%= f.text_field :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The commented line in the form is where I'm having trouble. Also, it seems I might need to modify some code in MessagesController#create, but I'm not sure where to start.
First, instead of writing your checkbox HTML by hand, you should use the Rails helpers for this. It'll save you a lot of work, particularly in redisplaying the form upon a validation failure.
To do this, you'll need to create an attribute on your Recipient class:
class Recipient
attr_accessor :selected
end
Then you can hook up that attribute to the checkbox:
<%= builder.check_box :selected %>
The next step is to make that attribute do something. You could try using the :reject_if
option for accepts_nested_attributes_for
. You could pass it a proc that returns true if the checkbox is not checked, e.g.:
accepts_nested_attributes_for :recipients, :reject_if => proc { |attributes| attributes['selected'] != '1' }
See these docs for details on :reject_if
:
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
精彩评论