【问题标题】:Access form field value in controller (Ruby on rails)访问控制器中的表单字段值(Ruby on rails)
【发布时间】:2019-08-14 08:38:35
【问题描述】:

所以,我有两种形式,一种用于创建,另一种用于编辑。在新表单中,我将每个输入存储在模型中的变量中,例如:name,所以稍后,在编辑表单中,它已经填充了这些字段。

现在,在新表单中,我添加了一些动态字段,它们不会映射到模型中的任何变量。让我给你看代码。首先我是这样做的:

<%= f.input :oid, label: 'SNMP OID', as: :search, required: false, novalidate: true, input_html: {data: { autocomplete_source: get_oids_path }} %>

如您所见,我将值存储在 :oid 中。

但现在我创建了这些不同的字段:

<input type='text' name='var_1' id='var_1' class='string search optional form-control snmp_variable'>

现在,没有属性来存储值,因为我是动态创建字段的。我唯一拥有的是该字段的名称。

在控制器中,我有这样的东西来填充编辑表单:

def edit_monitor_category
    if @monitor_category.technology == "snmp"
      @monitor_category.oid = value_from_method()
    end
end

但现在我不能这样做,因为现在我没有类似 .oid 的东西可以使用,我只有我创建的字段的名称,但我不知道如何从这个视图中获取值。我在新形式的 javascript 中有一个变量,其中包含我创建的这些字段的所有值的数组,但我不能在 ruby​​ 中使用这个变量,因为 javascript 是服务器端和 ruby​​ 客户端,所以我有点迷路了。

我听说过一些关于 before_action 的信息,但读到它我不知道如何使用它来做到这一点。

new_form:

<div class="modal-header">
  <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  <h3 class="modal-title">Create New Monitor Category</h3>
</div>
<%= simple_form_for(:monitor_category, url: create_monitor_category_path, :html => { :method => :post, :id => :form_monitor_category }) do |f| %>
  <div class="modal-body">
    <%= f.input :name, input_html: { type: "text" } %>
    <%= f.input :description, input_html: { type: "text" } %>
    <div class="row">
      <div class="col-md-6">
        <%= select_chosen('monitor_category[category]', @categories.invert, label: 'Tab', required: true, multiple: false) %>
      </div>
      <div class="col-md-6">
        <%= select_chosen('monitor_category[technology]', @technologies, label: 'Technology', required: true, multiple: false) %>
      </div>
    </div>
    <div class="row">
      <div class="col-md-6">
        <%= f.input :custom_tab_name, disabled: true, input_html: { type: "text" } %>
      </div>
      <div class="col-md-6">
        <%= f.input :custom_tab_unit, disabled: true, required: false, input_html: { type: "text"  } %>
      </div>
    </div>
    <div class="row" id="snmp">
      <div class="col-md-12">
        <%= f.input :oid, label: 'SNMP OID', as: :search, required: false, novalidate: true, input_html: {data: { autocomplete_source: get_oids_path }} %>
      </div>
    </div>
    <div class="row hidden" id="snmp_op">
      <div id="snmp_op_variables">
        <div class="col-md-12">
          <%= label_tag 'SNMP OID (VAR1)' %>
          <input type='text' name='var_1' id='var_1' pattern="(\.\d)" class='string search optional form-control snmp_variable'>
        </div>
      </div>
      <div class="col-md-6">
          <%= f.hidden_field :snmp_vars, :value => "1" %>
          <%= link_to "Add new variable", "#", :class => "btn btn-success btn-add-snmp-variable", :style =>"width:auto !important;", :id => "add_snmp_variable" %>
      </div>
      <div class="col-md-6"></div>
      <div class="col-md-12">
        <%= f.input :snmp_oper, label: 'OIDs Operation', as: :search, hint: 'Do operations with previous outputs.', placeholder: 'Ex: (var1 * var2) / 100', required: false, novalidate: true %>
      </div>
    </div>
    <div class="row hidden" id="redfish">
      <div class="col-md-12">
        <%= select_chosen('monitor_category[redfish]', @redfish, label: 'Redfish Commands', required: false, multiple: false) %>
      </div>
    </div>
    <div class="row hidden" id="ipmi">
      <div class="col-md-12">
        <%= select_chosen('monitor_category[ipmi]', @ipmi, label: 'IPMI Commands', required: false, multiple: false) %>
      </div>
    </div>
    <%#= f.input :custom_tab_unit, disabled: true, input_html: { type: "text", pattern: '[a-zA-Z]+' } %>

    <div class="row">
      <div class="col-md-6">
        <%= f.label "Default" %>
        <%= f.check_box :default %>
      </div>
    </div>
  </div>
  <div class="modal-footer">
    <%= f.submit "Create", :class => "btn btn-success", :style =>"width:auto !important;" %>
    <%= link_to "Cancel", monitor_categories_list_path, :class => "btn btn-secondary", :style =>"width:auto !important;", :'data-dismiss' => "modal" %>
  </div>
<% end %>
<% @index = 1 %>
<script type="text/javascript">
  var snmp_vars_index = 1;
  //Enable or disable the custom tab name and unit inputs
  $('#monitor_category_category').change(function(e) {
    var option = $('#monitor_category_category option:selected').val();
    if (option == "new_custom_tab") {
      $("#monitor_category_custom_tab_name").removeAttr('disabled');
      $("#monitor_category_custom_tab_unit").removeAttr('disabled');
    } else {
      $("#monitor_category_custom_tab_name").attr('disabled','disabled');
      $("#monitor_category_custom_tab_unit").attr('disabled','disabled');
    }
  });

  //Enable or disable the custom tab name and unit inputs
  $('#monitor_category_technology').change(function(e) {
    var option = $('#monitor_category_technology option:selected').val();
    console.log(option);
    switch(option) {
      case "redfish":
        $("#snmp").addClass('hidden');
        $("#ipmi").addClass('hidden');
        $("#operation").addClass('hidden');
        $("#snmp_op").addClass('hidden');
        $("#redfish").removeClass('hidden');
        break;
      case "ipmi":
        $("#redfish").addClass('hidden');
        $("#snmp").addClass('hidden');
        $("#operation").addClass('hidden');
        $("#snmp_op").addClass('hidden');
        $("#ipmi").removeClass('hidden');
        break;
      case "snmp_op":
        $("#redfish").addClass('hidden');
        $("#snmp").addClass('hidden');
        $("#operation").addClass('hidden');
        $("#ipmi").addClass('hidden');
        $("#snmp_op").removeClass('hidden');
        break;
      default: //snmp
        $("#redfish").addClass('hidden');
        $("#ipmi").addClass('hidden');
        $("#operation").addClass('hidden');
        $("#snmp_op").addClass('hidden');
        $("#snmp").removeClass('hidden');
        break;
    }

  });

  $('#monitor_category_category').autocomplete({
    source: $('#monitor_category_category').data('autocomplete-source'),
    open: function() {
      $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" );
    },
    close: function() {
      $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );
    }
  });

  $('#monitor_category_oid').autocomplete({
    source: $('#monitor_category_oid').data('autocomplete-source'),
    open: function() {
      $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" );
    },
    close: function() {
      $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );
    }
  });

  //When clicking add variable, create a new oid field
  $('#add_snmp_variable').click(function(event) {
    event.preventDefault();
    snmp_vars_index++;
    $("#snmp_op_variables").append("<div class='col-md-12'> <label for='SNMP_OID__VAR"+snmp_vars_index+"_'>Snmp oid (var"+snmp_vars_index+")</label> <input type='text' name='var_"+snmp_vars_index+"' id='var_"+snmp_vars_index+"' class='string search optional form-control snmp_variable'> </div>")
  });

  // Define your custom submit. Saves all oids into an array.
  $("#form_monitor_category").submit(function(event) {
    event.preventDefault();

    snmp_vars = [];
    for (i = 1; i <= snmp_vars_index; i++) {
        snmp_vars.push($("#var_"+i).val());
    };

    $("#monitor_category_snmp_vars").val(snmp_vars);
    console.log(snmp_vars);

    this.submit();
  });

</script>

edit_form

<div class="modal-header">
  <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  <h3 class="modal-title">Edit Monitor Category</h3>
</div>
<%= simple_form_for(@monitor_category, url: update_monitor_category_path, :html => { :remote => true, :method => :patch }) do |f| %>
  <div class="modal-body">

      <%= f.input :name, input_html: { type: "text" } %>
      <%= f.input :description, input_html: { type: "text" } %>
      <div class="row">
        <div class="col-md-6">
          <%= select_chosen('monitor_category[category]', @categories.invert, label: 'Tab', required: true, multiple: false, selected: @monitor_category.category) %>
        </div>
        <div class="col-md-6">
          <%= select_chosen('monitor_category[technology]', @technologies, label: 'Technology', required: true, selected: [@monitor_category.technology], multiple: false) %>
        </div>
      </div>
      <div class="row">
        <div class="col-md-6">
          <%= f.input :custom_tab_name, disabled: true, input_html: { type: "text" } %>
        </div>
        <div class="col-md-6">
          <%= f.input :custom_tab_unit, disabled: true, required: false, input_html: { type: "text" } %>
        </div>
      </div>
      <div class="row <%="hidden" if @monitor_category.technology != "snmp"%>" id="snmp">
        <div class="col-md-12">
          <%= f.input :oid, label: 'SNMP OID', as: :search, required: false, novalidate: true, input_html: {data: { autocomplete_source: get_oids_path }} %>
        </div>
      </div>
      <div class="row <%="hidden" if @monitor_category.technology != "snmp_op"%>" id="snmp_op">
        <div class="col-md-12">
          <%= f.input :oid, label: 'SNMP OID', as: :search, hint: 'Output stored in var1.', required: false, novalidate: true, input_html: {data: { autocomplete_source: get_oids_path }} %>
        </div>
        <div class="col-md-12">
          <%= f.input :snmp_oper, label: 'OIDs Operation', as: :search, hint: 'Do operations with previous outputs.', placeholder: 'Ex: (var1 * var2) / 100', required: false, novalidate: true %>
        </div>
      </div>
      <div class="row <%="hidden" if @monitor_category.technology != "redfish"%>" id="redfish">
        <div class="col-md-12">
          <%= select_chosen('monitor_category[redfish]', @redfish, label: 'Redfish Commands', required: false, multiple: false, selected: @monitor_category.redfish) %>
        </div>
      </div>
      <div class="row <%="hidden" if @monitor_category.technology != "ipmi"%>" id="ipmi">
        <div class="col-md-12">
          <%= select_chosen('monitor_category[ipmi]', @ipmi, label: 'IPMI Commands', required: false, multiple: false, selected: @monitor_category.ipmi) %>
        </div>
      </div>


    <div class="row">
      <div class="col-md-6">
        <%= f.label "Default" %>
        <%= f.check_box :default %>
      </div>
    </div>
  </div>

  <div class="modal-footer">
    <%= f.submit "Update", :class => "btn btn-success" %>
    <%= link_to "Cancel", monitor_categories_list_path, :class => "btn btn-secondary", :'data-dismiss' => "modal" %>
  </div>
<% end %>


<script type="text/javascript">
  // Enable or disable the custom tab name and unit inputs
  $('#monitor_category_category').change(function(e) {
    var option = $('#monitor_category_category option:selected').val();
    if (option == "new_custom_tab") {
      $("#monitor_category_custom_tab_name").removeAttr('disabled');
      $("#monitor_category_custom_tab_unit").removeAttr('disabled');
    } else {
      $("#monitor_category_custom_tab_name").attr('disabled','disabled');
      $("#monitor_category_custom_tab_unit").attr('disabled','disabled');
    }
  });

  // Enable or disable the custom tab name and unit inputs
  $('#monitor_category_technology').change(function(e) {
    var option = $('#monitor_category_technology option:selected').val();
    switch(option) {
      case "redfish":
      $("#snmp").addClass('hidden');
      $("#ipmi").addClass('hidden');
      $("#operation").addClass('hidden');
      $("#snmp_op").addClass('hidden');
      $("#redfish").removeClass('hidden');
      break;
    case "ipmi":
      $("#redfish").addClass('hidden');
      $("#snmp").addClass('hidden');
      $("#operation").addClass('hidden');
      $("#snmp_op").addClass('hidden');
      $("#ipmi").removeClass('hidden');
      break;
    case "snmp_op":
      $("#redfish").addClass('hidden');
      $("#snmp").addClass('hidden');
      $("#operation").addClass('hidden');
      $("#ipmi").addClass('hidden');
      $("#snmp_op").removeClass('hidden');
      break;
    default: //snmp
      $("#redfish").addClass('hidden');
      $("#ipmi").addClass('hidden');
      $("#operation").addClass('hidden');
      $("#snmp_op").addClass('hidden');
      $("#snmp").removeClass('hidden');
      break;
    }

  });


  $('#monitor_category_category').autocomplete({
    source: $('#monitor_category_category').data('autocomplete-source'),
    open: function() {
      $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" );
    },
    close: function() {
      $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );
    }
  });

  $('#monitor_category_oid').autocomplete({
    source: $('#monitor_category_oid').data('autocomplete-source'),
    open: function() {
      $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" );
    },
    close: function() {
      $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );
    }
  });
</script>

如您所见,除了我创建的字段没有出现在那里,一切都很好,我不知道该怎么做。

非常感谢任何回答。

【问题讨论】:

    标签: ruby-on-rails forms edit


    【解决方案1】:

    您需要一些步骤来完成此功能

    1. 在模型中创建一个新的迁移,其中包含一个名为 extras 的字段或其他名称。这会将动态输入存储在您的表单中。此字段必须是 jsonb 类型。

    2. 在来自控制器的新操作中,您将收到 params 数组中的所有表单输入。请注意,如果您使用的是 Rails 4+,则需要处理强参数并可能允许所有参数。

    3. 收到动态输入字段后,创建一个存储所有不属于模型的值的方法,并将其分配给extras 字段。之后在创建操作中,只需将值添加到额外字段并将其保存为 json。

    4. 在编辑操作中,您需要从 extras 字段中读取,将它们传递给模型类的实例变量,然后将它们用于编辑视图。触发更新操作时,只需复制您在新建/创建逻辑中所做的相同操作。

    【讨论】:

      【解决方案2】:

      如果这些表单应该相同,为什么不在 _form.html.erb 文件中使用渲染来使它们相同?

      new.html.erb

      <h1> new </h1>
      <%= render "xxxx/form %> 
      

      edit.html.erb

      <h1> edit </h1> 
      <%= render "xxxx/form" %>
      

      然后,由于这些字段不是“持久的”,它们将出现在编辑中,但不会与新输入的数据一起出现,除非您再次“计算”它们。

      【讨论】:

      • 是的,这很理想,但它们并不完全相同,我可以考虑在未来重构它,但目前它必须保持这样。所以目前这不能成为解决方案,无论如何感谢您的四个答案。
      【解决方案3】:

      我认为您正在寻找的是“attr_accessor”的概念。不用是基字段,计算即可

      class MyModel < ActiveRecord::Base
      
         attr_accessor :my_attribute
      
      end
      

      然后您可以在编辑方法中修改/计算它

      @my_object.my_attribute = "xxx"
      

      或在您的表单中将其用作普通属性。

      <%= f.input :my_attribute %>
      

      【讨论】:

      • 因为我动态创建这些字段,我可以有 10 个字段,我认为创建 10 个属性以供以后使用不是很干,我考虑过,但因为我不知道我要去多少个字段创建我不知道这是否可以。
      • 哦,好吧!我认为 Javascript 将是根据其他字段“计算”字段值的解决方案。但是,对于它们没有出现在edit中,那肯定是edit.html.erb中的问题,但是我没看到也帮不上忙。
      • 我将表格添加到帖子中。不知道你会不会明白一些东西哈哈哈。我必须找到一种方法在编辑表单中显示我创建的所有字段,因为如果不是我无法显示之前输入的信息。但我不知道方法,如果我可以访问其中包含这些字段的所有值的变量,我可以在该数组上执行类似循环并为每个值构建一个 div 的操作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 1970-01-01
      • 2013-08-14
      • 2011-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多