フォームの送信時にセッション ハッシュが消去されるという問題があり、その理由がわかりません。状況は次のとおりです。
アプリケーションにはいくつかのモデルがあり、そのうちの 1 つはPlanと呼ばれます。ユーザーは、プランを表示、編集、削除、または作成できます。ビュー以外のいずれかのアクションが呼び出されると、フォームが表示され、ユーザーは計画に動的に情報を追加し、最終的にフォームを送信して、データベースで計画を作成/更新できます。ユーザーの入力に基づいて出力も生成されます。この部分は正常に動作します。
この問題は、無効なフォームで作業しているときに発生します。ユーザーがクリックして既存のプランを表示すると、show アクションが呼び出されます。表示モードでは、フォームは基本的に読み取り専用なので、[送信] ボタンを除くフォームのすべての要素を無効にしました。もともと、フォームは読み取り専用ではありませんでした。そうでないときは、何の問題もありませんでした。ユーザーは計画を表示し、[送信] ボタンをクリックして正しい出力を取得できます。
ここで、無効化されたフォームを使用して、ユーザーは同じプロセスを実行できますが、フォームの情報を変更できないことは明らかです。ユーザーが同じ [送信] ボタンをクリックすると、フォームは処理されますが、出力はまったくレンダリングされません。
多くのトラブルシューティングを行った結果、何らかの理由でセッション ハッシュがクリアされ、一部のロジックが正しく機能していないことがわかりました。ユーザーがプランを表示するためにクリックすると show アクションが呼び出され、Submit ボタンがクリックされると、次にrender_planアクションが呼び出されます。render_planアクションの before_filters がありません。showアクションで、session[:accessType] を「View」に設定しました。ハッシュが実際に設定されることを確認しました。render_planアクションに移ると、セッション ハッシュを確認したところ、完全にクリアされています。私はその理由を理解できないようで、何時間も試みてきました.
繰り返しますが、フォームが無効になっていない場合、すべてが正常に機能します。フォームが読み取り専用モードで送信された場合、送信された情報ではなく、データベースに保存されているすべての情報を計画に使用するため、フォームからの情報は必要ありません。また、コードに構文/実行時エラーがないことを確認しました。
セッションハッシュがクリアされている理由について誰か考えがありますか? 私は決してそれを片付けていません。助けてくれてありがとう!
編集#1
フォームを含む「show」html.erb ファイルは以下のとおりです。
<% if session[:accessType] != "Create" %>
<% provide(:title, @savedPlan.name) %>
<h1 id="pagetitle"><%= session[:accessType] %>ing: <%= @savedPlan.name %></h1>
<% else %>
<% provide(:title, 'New Project Plan') %>
<h1 id="pagetitle">New Project Plan</h1>
<% end %>
<div id="form_errors">
<ul>
<li>Please correct the errors below:</li>
<li> </li>
</ul>
</div>
<h2 class="sectiontitle">Choose the project mode.</h2>
<%# Sets the correct project mode for the saved project plan %>
<% if !@savedPlan.nil? %>
<% if @savedPlan.projectMode == "variable" %>
<% varChecked = 'checked=checked' %>
<% else %>
<% fixedChecked = 'checked=checked' %>
<% end %>
<% else %>
<% varChecked = 'checked=checked' %>
<% end %>
<label class="radio inline radiolabel">
<input id="radVar" name="radMode" type="radio" value="Variable" tabindex="1" <%= if !varChecked.nil?; varChecked; end %>
onclick="OptionChoice();">
Variable
</label>
<label id="lblRadFixed" class="radio inline radiolabel">
<input id="radFixed" name="radMode" type="radio" value="Fixed" tabindex="2" <%= if !fixedChecked.nil?; fixedChecked; end %>
onclick="OptionChoice();">
Fixed
</label>
<div class="variable projectmode">
<%= form_tag({:controller => 'project_plans', :action => 'render_plan' },
{ :multipart => true, :id => 'frmvariableplan', :name => 'frmvariableplan', :class => 'form-inline' }) do %>
<input id="variable_project_mode" name="projectmode" value="variable" type="hidden">
<div class="row proj-start-end-date-div">
<div class="span4">
<%= label_tag :projname, "Project Name", :class => 'project_date_label biglbl biglbl-spacing' %>
<input class="proj-start-end-date input-spacing" name="projname" type="text" value="<%= if !@savedPlan.nil?; @savedPlan.name; end %>">
</div>
<div class="span4">
<%= label_tag :projstartdate, "Start Date", :class => 'project_date_label biglbl biglbl-spacing' %>
<input class="proj-start-end-date input-spacing datepicker read_only_input" name="projstartdate" type="text"
value="<%= if !@savedPlan.nil?; @savedPlan.startDate.strftime("%m/%d/%Y"); end %>" readonly="true">
</div>
<div class="span4">
<%= label_tag :projenddate, "End Date", :class => 'project_date_label biglbl biglbl-spacing' %>
<input class="proj-start-end-date" name="projenddate" type="text"
value="<%= if !@savedPlan.nil?; @savedPlan.endDate.strftime("%m/%d/%Y"); end %>" readonly="true">
</div>
</div>
<!-- Horizontal Rule to break the page up into sections -->
<hr />
<div>
<!-- Simple service type -->
<label name="lblServiceType_Simple" class="biglbl servicetypeheading">Service Type: Simple</label>
<div id="divServiceType_Simple" class="servicetypediv">
<%= render :partial => 'project_plans/display_services', :locals => { :type_service => 'simple' } %>
<%= render :partial => 'project_plans/add_service', :locals => { :service_type => 'simple' } %>
<% if !@savedPlan.nil? %>
<% service_array_length = (@all_services_array[0].count - 1) %>
<script type="text/javascript">
<% if (service_array_length >= 0) %>
CreateSlider("simple", "Total", 0, 144, <%= @all_services_array[0][0].totalHours %>);
CreateSlider("simple", "Design", 0, 64, <%= @all_services_array[0][0].designHours %>);
CreateSlider("simple", "Develop", 0, 80, <%= @all_services_array[0][0].developHours %>);
<% else %>
CreateSlider("simple", "Total", 0, 144, 144);
CreateSlider("simple", "Design", 0, 64, 64);
CreateSlider("simple", "Develop", 0, 80, 80);
<% end %>
</script>
<% (0..service_array_length).each do |i| %>
<% service = @all_services_array[0][i] %>
<%= render(:partial => 'project_plans/new_service',
:locals => { :type_service => 'simple', :type_count => (i + 1),
:service_name => service.name, :start_date => service.startDate.strftime("%m/%d/%Y"),
:end_date => service.endDate.strftime("%m/%d/%Y"),
:design_endDate => service.design_endDate.strftime("%m/%d/%Y"), :priority => service.priority,
:should_display_button => ((i != service_array_length) ? 'false' : 'true') }) %>
<% end %>
<% session[:simple] = @all_services_array[0].count %>
<% else %>
<script type="text/javascript">
CreateSlider("simple", "Total", 0, 144, 144);
CreateSlider("simple", "Design", 0, 64, 64);
CreateSlider("simple", "Develop", 0, 80, 80);
</script>
<% end %>
</div>
<!-- Horizontal Rule to break the page up into sections -->
<hr />
<!-- Medium service type -->
<label name="lblServiceType_Medium" class="biglbl servicetypeheading">Service Type: Medium</label>
<div id="divServiceType_Medium" class="servicetypediv">
<%= render :partial => 'project_plans/display_services', :locals => { :type_service => 'medium' } %>
<%= render :partial => 'project_plans/add_service', :locals => { :service_type => 'medium' } %>
<% if !@savedPlan.nil? %>
<% service_array_length = (@all_services_array[1].count - 1) %>
<script type="text/javascript">
<% if (service_array_length >= 0) %>
CreateSlider("medium", "Total", 145, 220, <%= @all_services_array[1][0].totalHours %>);
CreateSlider("medium", "Design", 0, 100, <%= @all_services_array[1][0].designHours %>);
CreateSlider("medium", "Develop", 0, 120, <%= @all_services_array[1][0].developHours %>);
<% else %>
CreateSlider("medium", "Total", 145, 220, 220);
CreateSlider("medium", "Design", 0, 100, 100);
CreateSlider("medium", "Develop", 0, 120, 120);
<% end %>
</script>
<% (0..service_array_length).each do |i| %>
<% service = @all_services_array[1][i] %>
<%= render(:partial => 'project_plans/new_service',
:locals => { :type_service => 'medium', :type_count => (i + 1),
:service_name => service.name, :start_date => service.startDate.strftime("%m/%d/%Y"),
:end_date => service.endDate.strftime("%m/%d/%Y"),
:design_endDate => service.design_endDate.strftime("%m/%d/%Y"), :priority => service.priority,
:should_display_button => ((i != service_array_length) ? 'false' : 'true') }) %>
<% end %>
<% session[:medium] = @all_services_array[1].count %>
<% else %>
<script type="text/javascript">
CreateSlider("medium", "Total", 145, 220, 220);
CreateSlider("medium", "Design", 0, 100, 100);
CreateSlider("medium", "Develop", 0, 120, 120);
</script>
<% end %>
</div>
<!-- Horizontal Rule to break the page up into sections -->
<hr />
<!-- Complex service type -->
<label name="lblServiceType_Complex" class="biglbl servicetypeheading">Service Type: Complex</label>
<div id="divServiceType_Complex" class="servicetypediv">
<%= render :partial => 'project_plans/display_services', :locals => { :type_service => 'complex' } %>
<%= render :partial => 'project_plans/add_service', :locals => { :service_type => 'complex' } %>
<% if !@savedPlan.nil? %>
<% service_array_length = (@all_services_array[2].count - 1) %>
<script type="text/javascript">
<% if (service_array_length >= 0) %>
CreateSlider("complex", "Total", 221, 295, <%= @all_services_array[2][0].totalHours %>);
CreateSlider("complex", "Design", 0, 135, <%= @all_services_array[2][0].designHours %>);
CreateSlider("complex", "Develop", 0, 160, <%= @all_services_array[2][0].developHours %>);
<% else %>
CreateSlider("complex", "Total", 221, 295, 295);
CreateSlider("complex", "Design", 0, 135, 135);
CreateSlider("complex", "Develop", 0, 160, 160);
<% end %>
</script>
<% (0..service_array_length).each do |i| %>
<% service = @all_services_array[2][i] %>
<%= render(:partial => 'project_plans/new_service',
:locals => { :type_service => 'complex', :type_count => (i + 1),
:service_name => service.name, :start_date => service.startDate.strftime("%m/%d/%Y"),
:end_date => service.endDate.strftime("%m/%d/%Y"),
:design_endDate => service.design_endDate.strftime("%m/%d/%Y"), :priority => service.priority,
:should_display_button => ((i != service_array_length) ? 'false' : 'true') }) %>
<% end %>
<% session[:complex] = @all_services_array[2].count %>
<% else %>
<script type="text/javascript">
CreateSlider("complex", "Total", 221, 295, 295);
CreateSlider("complex", "Design", 0, 135, 135);
CreateSlider("complex", "Develop", 0, 160, 160);
</script>
<% end %>
</div>
<!-- Horizontal Rule to break the page up into sections -->
<hr />
<!-- Incremental service type -->
<label name="lblServiceType_Incremental" class="biglbl servicetypeheading">Service Type: Incremental</label>
<div id="divServiceType_Incremental" class="servicetypediv">
<%= render :partial => 'project_plans/display_services', :locals => { :type_service => 'incremental' } %>
<%= render :partial => 'project_plans/add_service', :locals => { :service_type => 'incremental' } %>
<% if !@savedPlan.nil? %>
<% service_array_length = (@all_services_array[3].count - 1) %>
<script type="text/javascript">
<% if (service_array_length >= 0) %>
CreateSlider("incremental", "Total", 0, 40, <%= @all_services_array[3][0].totalHours %>);
CreateSlider("incremental", "Design", 0, 40, <%= @all_services_array[3][0].designHours %>);
CreateSlider("incremental", "Develop", 0, 40, <%= @all_services_array[3][0].developHours %>);
<% else %>
CreateSlider("incremental", "Total", 0, 40, 40);
CreateSlider("incremental", "Design", 0, 20, 20);
CreateSlider("incremental", "Develop", 0, 20, 20);
<% end %>
</script>
<% (0..service_array_length).each do |i| %>
<% service = @all_services_array[3][i] %>
<%= render(:partial => 'project_plans/new_service',
:locals => { :type_service => 'incremental', :type_count => (i + 1),
:service_name => service.name, :start_date => service.startDate.strftime("%m/%d/%Y"),
:end_date => service.endDate.strftime("%m/%d/%Y"),
:design_endDate => service.design_endDate.strftime("%m/%d/%Y"), :priority => service.priority,
:should_display_button => ((i != service_array_length) ? 'false' : 'true') }) %>
<% end %>
<% session[:incremental] = @all_services_array[3].count %>
<% else %>
<script type="text/javascript">
CreateSlider("incremental", "Total", 0, 40, 40);
CreateSlider("incremental", "Design", 0, 20, 20);
CreateSlider("incremental", "Develop", 0, 20, 20);
</script>
<% end %>
</div>
</div>
<!-- Horizontal Rule to break the page up into sections -->
<hr />
<!-- Resources section -->
<label name="lblResources" class="biglbl servicetypeheading">Resources</label>
<div id="resources" class="servicetypediv">
<%= render :partial => 'project_plans/add_resource' %>
<% if !@savedPlan.nil? %>
<% resource_array_length = (@all_resources_array.count - 1) %>
<% (0..resource_array_length).each do |i| %>
<% resource = @all_resources_array[i] %>
<%= render(:partial => 'project_plans/new_resource',
:locals => { :type_count => (i + 1), :resource_name => resource.name, :start_date => resource.startDate.strftime("%m/%d/%Y"),
:end_date => resource.endDate.strftime("%m/%d/%Y"), :resource_type => resource.resourceType,
:should_display_button => ((i != resource_array_length) ? 'false' : 'true') }) %>
<% end %>
<% session[:rescount] = @all_resources_array.count %>
<% end %>
</div>
<!-- Horizontal Rule to break the page up into sections -->
<hr />
<div>
<p class="biglbl">Notes:</p>
<textarea class="span6 textarea-spacing" name="txtNotes" rows="5"
placeholder="Enter any notes here"><%= if !@savedPlan.nil?; @savedPlan.notes; end %></textarea>
<input class="btn btn-primary btn-project-plan" value="<%= session[:accessType] %> Project Plan" type="button"
onclick="ValidateForm($('#frmvariableplan'))">
</div>
<div class="clearfix"></div>
<% end %>
</div>
<div class="fixed projectmode">
<%= form_tag({:controller => 'project_plans', :action => 'render_plan' },
{ :multipart => true, :id => 'frmfixedplan', :name => 'frmfixedplan', :class => 'form-inline' }) do %>
<input id="fixed_project_mode" name="projectmode" value="fixed" type="hidden">
<div class="row proj-start-end-date-div">
<div class="span4">
<%= label_tag :projname, "Project Name", :class => 'project_date_label biglbl biglbl-spacing' %>
<input class="proj-start-end-date input-spacing" name="projname" type="text">
</div>
<div class="span4">
<%= label_tag :projstartdate, "Start Date", :class => 'project_date_label biglbl biglbl-spacing' %>
<input class="proj-start-end-date input-spacing datepicker read_only_input" name="projstartdate" type="text" readonly="true">
</div>
<div class="span4">
<%= label_tag :projenddate, "End Date", :class => 'project_date_label biglbl biglbl-spacing' %>
<input class="proj-start-end-date" name="projenddate" type="text" readonly="true">
</div>
</div>
<% end %>
</div>
<% if session[:accessType] == "View" %>
<script type="text/javascript">
disableForm($('#frmvariableplan'));
</script>
<% end %>
* *答え* ***
私はついにそれを理解しました!
この問題は、通常は頭に浮かぶことのないものでした。それは、真正性トークンです。私の JavaScript 関数は基本的にフォーム上のすべての要素を無効にしたため、Rails がデフォルトで実装する信頼性チェックも無効になりました。これは、POST リクエスト時にそれらがサーバーに送信されず、Rails が正しくない/欠落している認証トークンを不正なリクエストとして解釈することを意味します。この状況では、アプリケーションを保護するためにセッション情報が消去されます。
ログインしたり、コンテンツを投稿したりできる Twitter や Facebook のような Web サイトを想像してみてください。ユーザーのログインはセッションとして保存されるため、不正な要求が行われた場合にのみ、セッション全体をクリアすることが理にかなっています。ユーザーをアウトします。
この問題を解決するために、フォームのすべての要素を無効にした後、JavaScript を使用して 2 つの認証入力ボックスを有効にしました。
$(document.getElementsByName("utf8")[0]).attr('disabled', false);
$(document.getElementsByName("authenticity_token")[0]).attr('disabled', false);
それはトリックをしました!