How to prevent polluting a rails object when using form_for and .new?

我们两清 提交于 2019-12-25 04:59:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!