问题
I have a model:
class Activity < ActiveRecord::Base
has_many :activity_states
end
I want to render options for new activity states and render existing activity states. However when I use this form_for:
<%= form_for activity.activity_states.new, :remote => true do |f| %>
<%= f.hidden_field :state_type, :value => activity_state_type %>
<%= f.hidden_field :activity_id %>
<%= f.submit submit_label, :disable_with => 'sending...' %>
<% end %>
for creating new temporary activity_state models to use as the basis for new activity_states it pollutes the activity object with nil
activity states so instead of Activity having the activity states:
[#<ActivityState id: 7353, activity_id: 2033, state_type: 0, created_at: "2012-05-31 11:06:50">,
#<ActivityState id: 7354, activity_id: 2033, state_type: 1, created_at: "2012-05-31 11:06:53">,
#<ActivityState id: 7355, activity_id: 2033, state_type: 2, created_at: "2012-05-31 11:06:59">]
It also has several these nil
activity_state objects appended mid render because of the .new
:
#<ActivityState id: nil, activity_id: 2033, state_type: nil, created_at: nil>
resulting in:
[#<ActivityState id: 7353, activity_id: 2033, state_type: 0, created_at: "2012-05-31 11:06:50">,
#<ActivityState id: 7354, activity_id: 2033, state_type: 1, created_at: "2012-05-31 11:06:53">,
#<ActivityState id: 7355, activity_id: 2033, state_type: 2, created_at: "2012-05-31 11:06:59">,
#<ActivityState id: nil, activity_id: 2033, state_type: nil, created_at: nil>,
#<ActivityState id: nil, activity_id: 2033, state_type: nil, created_at: nil>]
Which then messes things up when I loop over the activity_states for the activity and render them. I tried a hacky way of getting around this using: <% activity.activity_states.pop %>
after each form_for but this doesn't work when in production on Heroku as it complains about trying to modify a frozen array.
Any ideas on the "right" way of doing this please? I know I'm failing to understand something pretty fundamental here and also know I've opened up a hole by inserting a hidden field for the id field (which can then be manipulated by malicious users).
回答1:
I have one solution so far, in the show
method of the activity controller
, include:
@new_activity_state = @activity.activity_states.new
@activity.activity_states.pop
and in the view partial (which I pass @activity
as the local variable activity
):
<% new_activity_state = @new_activity_state || activity.activity_states.new %>
<%= form_for new_activity_state, :remote => true do |f| %>
<%= f.hidden_field :state_type, :value => activity_state_type %>
<%= f.hidden_field :activity_id %>
<%= f.submit submit_label, :disable_with => 'sending...' %>
<% end %>
Heroku's production environment doesn't object to the .pop now which is great :D But is there a better way?
来源:https://stackoverflow.com/questions/10832748/how-to-prevent-polluting-a-rails-object-when-using-form-for-and-new