简体   繁体   English

无法循环遍历 rails 哈希

[英]Cannot loop through a rails hash

I'm working on a legacy app and I'm refactoring the settings, we have a strange db structure but it can't be changed due to existing data.我正在开发一个遗留应用程序,我正在重构设置,我们有一个奇怪的数据库结构,但由于现有数据而无法更改。

The issue I'm having is the following, the settings are created using a db:seed which is fine, however, I cannot then go into the form and update them.我遇到的问题如下,设置是使用db:seed创建的,这很好,但是,我无法进入表单并更新它们。

Here's what I have so far (files cut down for length)这是我到目前为止所拥有的(文件长度减少了)

The form is on the index so I've moved everything over to that method and I've commented out all of the legacy code表单在索引上,所以我已经把所有的东西都移到了那个方法上,并且我已经注释掉了所有的遗留代码

controller控制器

class SettingsController < ApplicationController
  load_and_authorize_resource
  before_action :authenticate_user!
  respond_to :json, :html

  def index
    # all_params_permitted
    # strip_list = [
    #   'company_main_mail',
    #   'company_accounts_mail',
    #   'company_web_site',
    #   'company_vat_number'
    # ]
    # @errors = []
    # @error_list = []
    # @settings = params[:settings].each do |index, value|
    #   setting = Setting.find_by(name: index)
    #   if setting
    #     setting.value = value
    #   end
    #   setting.save
    # end
    # params[:settings].each do |index, value|
    #   setting = Setting.find_by(name: index)
    #   if setting
    #     if strip_list.include? setting.name
    #       setting.value = value.strip
    #     else
    #       setting.value = value
    #     end
    #     setting.save
    #     if setting.errors.present?
    #       @errors << setting
    #       @error_list << {name: setting.name , value: value}
    #     end
    #   end
    # end
    # check_boxes = [
    #   'company_incorporation_status',
    #   'company_vat_status',
    #   'is_vso',
    #   'is_efpm',
    #   'exclude_non-manufactured_from_wo_creation_from_so',
    #   'check_stock_levels',
    #   'show_vat_on_uninvoiced_sales',
    #   'hide_due_date_on_sales_quotes_and_orders',
    #   'hide_due_date_on_purchase_quotes_and_orders',
    #   'kpi_use_average_cos',
    #   'kpi_use_average_labour',
    #   'discounts_enabled',
    #   'remove_works_order_from_plan_after_edit',
    #   'user_change_own_password',
    #   'auto_populate_receive_invoice',
    #   'assume_supplier_has_vat_number_for_auto_populate_receive_invoice',
    #   'enable_comments_on_stock_components',
    #   'default_true_create_supply_orders',
    #   'sales_order_item_custom_info_1_enabled',
    #   'update_probability_on_opportunity_status_change',
    #   'no_supplier_serial_numbers',
    #   'enable_batch_number_generation',
    #   'include_sales_order_notes_on_picking_lists',
    #   'backorder_default',
    #   'consolidate_work_order',
    #   'over_delivery_default',
    #   'restrict_purchase_invoice_query_flag',
    #   'use_package_lines',
    #   'hightlight_below_order_quantity_on_grn',
    #   'show_poi_descriptions_on_order_lines',
    #   'intrastat_enable',
    #   'intrastat_enable_tod',
    #   'api_enabled',
    #   'wo_process_start_time',
    #   'negative_current_stock',
    #   'btp_enabled',
    #   'enable_custom_documents',
    #   'vat_adjustment_limit',
    #   'cash_accounting',
    #   'is_northern_ireland_protocol'
    # ]
    # check_boxes.each do |box|
    #   if !params[:settings][box]
    #     setting = Setting.find_by_name(box)
    #     if setting
    #       setting.value = 0
    #       setting.save
    #     end
    #   end
    # end
    # params[:large_settings].each do |index, value|
    #   setting = LargeSetting.find_by_name(index)
    #   if setting
    #     setting.value = value
    #     setting.save
    #   end
    # end
    # if params[:company_logo]
    #   @company_logo = Image.find_by_code('LOGO')
    #   @company_logo.update_attributes(params[:company_logo])
    # end
    # if params[:factoring_image]
    #   @factoring_image = Image.find_by_code('FACTORING')
    #   @factoring_image.update_attributes(params[:factoring_image])
    # end
    # if (@factoring_image && @factoring_image.errors && @factoring_image.errors.size > 0) || (@company_logo && @company_logo.errors && @company_logo.errors.size > 0) || (@errors.size > 0)
    #   @settings = get_settings(true)
    #   if @error_list.size > 0
    #     @error_list.each do |error|
    #       @settings[error[:name]] = error[:value]
    #     end
    #   end
    #   render settings_path
    # else
    #   redirect_to settings_path
    # end
  end

  private

  def setting_params
    params.require(:setting).permit(
      :name,
      :value,
      :value_type
    )
  end
end

form形式

<div class="l-12col" id="settings_form">
  <%= form_for @settings, method: :post, multipart: true do |f| %>
    <%# post_code %>
    <div class="tabs">
      <!-- start tab headings -->
      <div class="tab-headings">
        <a class="tab-button active" data-id="company_details">Company Details</a>
        <a class="tab-button" data-id="tax_payroll">Tax &amp; Payroll</a>
        <a class="tab-button" data-id="system_settings">System Settings</a>
        <a class="tab-button" data-id="trade_terms">Trade Terms</a>
        <a class="tab-button" data-id="factoring">Factoring</a>
        <a class="tab-button" data-id="document_storage">Document Storage</a>
        <% if Features.API? %>
          <a class="tab-button" data-id="web_api">Web API</a>
        <% end %>
      </div>
      <!-- end tab headings -->
      <div class="tab-contents">
        <!-- start of company_details tab -->
        <div class="tab-content active" id="company_details">
          <div class="l-row-block clearfix">
            <div class="l-06col l-ml-12col l-md-12col">
              <h2 class="txt-title-alt">
                Name &amp; Address
                <span data-tooltip title="Full legal name and address for this business as it should appear on business documentation.">
                  <span class="icon-help-with-circle" aria-hidden="true"></span>
                </span>
              </h2>
              <div class='field l-margin-sm'>
                <%= f.label :company_name %>
                <%= f.text_field :company_name %>
              </div>
              <div class='field l-margin-sm'>
                <%= f.label :company_system_display_name %>
                <%= f.text_field :company_system_display_name %>
              </div>
              <div class='field l-margin-sm'>
                <%= f.label :company_address_1, "Address Line 1" %>
                <%= f.text_field :company_address_1 %>
              </div>
              ...
            </div>
          </div>
        </div>
        <!-- end of company_details tab -->
        ...
      </div>
    </div>

    <div class="btns">
      <%= submit_tag "Update", id: 'company_settings_update_btn' %>
      <%= link_to "Cancel", root_path, class: "btn-medium" %>
    </div>
  <% end %>
</div>

Here is what the db table looks like这是 db 表的样子在此处输入图片说明

As a test here is what t I've tried.作为测试,这是我尝试过的。

I added @settings = Setting.new to the index which then gave me an undefined method error so in the model I added the following我将@settings = Setting.new添加到索引中,然后给了我一个未定义的方法错误,所以在模型中我添加了以下内容

def company_name
  Setting.find_by(name: :company_name).value
end

which rendered the page with the correct company name, however, there are 135 settings so I need a way to save all of them.它使用正确的公司名称呈现页面,但是,有 135 个设置,所以我需要一种方法来保存所有这些设置。

I would recommend you to add a class method on your model:我建议您在模型上添加一个类方法:

def self.value_for(setting)
  Setting.find_by(name: setting).try(:value)
end

And set the value attribute on your fields:并在您的字段上设置value属性:

f.text_field :company_name, value: Setting.value_for(:company_name)
f.number_field :quote_value, value: Setting.value_for(:quote_value)

It's not perfect but it's very clear and readable, which is important in legacy code它并不完美,但非常清晰易读,这在遗留代码中很重要

In the controller something like that should do the job:在控制器中应该做这样的工作:

def update
  # Do some checks if you want

  params[:settings].each do |setting, value|
    next if unallowed_setting(setting) # create unallowed_setting method if you need a filter, remove this line otherwise

    model = Setting.find_or_initialize_by(name: setting)
    model.value = value
    model.save!
  end

  redirect_to :index
end

EDIT编辑

Another possibility would be to keep you old code and set @settings to an OpenStruct instance so you won't have to set value in view, but I'm not 100% sure it will work:另一种可能性是保留旧代码并将 @settings 设置为 OpenStruct 实例,这样您就不必在视图中设置值,但我不能 100% 确定它会起作用:

def index
  settings = {
    id: nil # I think this would be needed
  }
  Setting.all.each do |setting|
    settings[setting.name] = setting.value
  end
  @settings = OpenStruct.new(settings)
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM