Ruby on rails 强参数-Can';t访问深度嵌套的属性

Ruby on rails 强参数-Can';t访问深度嵌套的属性,ruby-on-rails,ruby,strong-parameters,Ruby On Rails,Ruby,Strong Parameters,有一个问题问我需要什么,但自我回答并不能帮助我知道下一步该怎么做。这个问题()中所呈现的场景与我的情况基本相同,但我将发布我的缩写(仍然很长),希望有人——甚至可能是这篇文章的戴夫——能够提供帮助(我没有足够的声誉来评论和询问他)。关于嵌套强参数的链接我很少没有读过,我在许多控制器和API端点上也讨论过一些,但这是应用程序中最复杂的。(我举了一个很长的例子,这样你就可以看到全部的复杂性。) 这是在sales\u控制器上,我们无法获取的属性之一是时区名称,它位于sale下的选项属性中的运行属性中。

有一个问题问我需要什么,但自我回答并不能帮助我知道下一步该怎么做。这个问题()中所呈现的场景与我的情况基本相同,但我将发布我的缩写(仍然很长),希望有人——甚至可能是这篇文章的戴夫——能够提供帮助(我没有足够的声誉来评论和询问他)。关于嵌套强参数的链接我很少没有读过,我在许多控制器和API端点上也讨论过一些,但这是应用程序中最复杂的。(我举了一个很长的例子,这样你就可以看到全部的复杂性。)

这是在
sales\u控制器
上,我们无法获取的属性之一是
时区名称
,它位于
sale
下的
选项属性
中的
运行属性中。我尝试了几乎所有不同的语法方法来匹配大多数嵌套属性和StackOverflow上的强参数问题,但没有一种有效。我需要更多的课程吗?有魔术括号吗?我需要新的建议。求你了

需要注意的是,这是一个强大的gem和Rails 3.2.21参数,但是我想让应用程序为Rails 4做好准备,所以我希望避免短期的解决方案

对不起,时间太长了:

 Parameters:
    "sale"=>{
      "cloned_from"=>"",
      "type"=>"Localsale",
      "primary_contact_attributes"=>{
          "primary"=>"true",
          "first_name"=>"Fred",
          "id"=>"1712"
        },
      "contract_signed_on"=>"March 20, 2015",
      "billing_addresses_attributes"=>{
          "0"=>{
              "billing"=>"1",
              "city"=>"San Diego",
              "id"=>"29076"
            }
        },
      "other_contacts_attributes"=>{
          "0"=>{
              "first_name"=>"Fred",
              "_destroy"=>"false",
              "id"=>"170914"
            },
          "1"=>{
              "first_name"=>"Fred",
              "last_name"=>"Smith",
              "_destroy"=>"false",
              "id"=>"1798"
            }
        },
      "opportunity_detail_attributes"=>{
          "original_salesperson_id"=>"",
          "id"=>"10130"
        },
      "production_editor"=>"1868097",
      "event_sale_attributes"=>{
          "0"=>{
              "name"=>"is_super_sale",
              "value"=>"0",
              "id"=>"15326"
            },
          "1"=>{
              "name"=>"super_show_code",
              "value"=>""
            },
        },
      "scheduling_note"=>"",
      "category_ids"=>["2", "364"],
      "options_attributes"=>{
          "0"=>{
              "title"=>"T-Shirt and Bag Check",
              "event_starts_at(1i)"=>"2015",
              "event_starts_at(2i)"=>"6",
              "event_doors_open_at_attributes"=>{
                  "option_id"=>"8682604",
                  "doors_time(1i)"=>"",
                  "id"=>"278382"
                },
              "event_option_attributes"=>{
                  "0"=>{
                      "name"=>"event_duration",
                      "value"=>""
                    },
                  "1"=>{
                      "name"=>"send_pre_event_email",
                      "value"=>"1",
                      "id"=>"632546"
                    }
                },
              "language_id"=>"1",
              "run_spans_attributes"=>{
                  "0"=>{
                      "timezone_name"=>"Eastern Time (US & Canada)",
                      "_destroy"=>"false",
                      "id"=>"560878"
                    },
                  "1429320288130"=>{
                      "timezone_name"=>"Eastern Time (US & Canada)",
                      "_destroy"=>"false"
                    }
                },
              "_destroy"=>"false",
              "id"=>"8682604"
              }#ends 0 option
          },#ends options
      "coupons_per_redemption"=>"1",
      "methods_attributes"=>{
          "0"=>{
              "redemption_code"=>"0",
              "_destroy"=>"0",
              "id"=>"9797012"
            },
          "1"=>{
              "redemption_code"=>"4",
              "_destroy"=>"1",
              "vendor_provided_promo_code"=>"0",
              "promo_code"=>""
            }
        }, #ends redemption methods
      "addresses_attributes"=>{
          "0"=>{
              "street_address_1"=>"2400 Cat St",
              "primary"=>"0",
              "id"=>"2931074",
              "_destroy"=>"false"
            }
        },
      "zoom"=>"",
      "video_attributes"=>{
          "youtube_id"=>"",
        },
      "updated_from"=>"edit"
      }
帮我把这个做好?顺便说一下,各种
.tap do | whitelisted |
方法都失败了

 private
 def_sale_strong_params
    params.require(:sale).permit(:how, :the, :heck, :do, :the_attributes =>
       [:make, themselves => [:known, :outside => [:of, :these => [:darn,
        :parentheses], :and], :brackets]])
 end

1。在控制台中验证您的进度

要配置强参数,它可以帮助在Rails控制台中工作。您可以将参数设置为
ActiveSupport::HashWithInferenceTaccess
对象,然后开始测试从
ActionController::parameters
返回的内容

例如,假设我们从以下内容开始:

params = ActiveSupport::HashWithIndifferentAccess.new(
  "sale"=>{
    "cloned_from"=>"",
    "type"=>"Localsale"}
)
我们可以运行以下程序:

ActionController::Parameters.new(params).require(:sale).permit(:cloned_from, :type)
我们将得到这个作为返回值,我们将知道我们已经成功地允许从
和类型中克隆了(u):

{"cloned_from"=>"", "type"=>"Localsale"}
您可以继续工作,直到考虑到所有参数。如果你在问题中包含了所有的参数

params = ActiveSupport::HashWithIndifferentAccess.new(
  "sale"=>{
    "cloned_from"=>"",
    "type"=>"Localsale",
    ...
    "options_attributes"=>{
      "0"=>{
        "title"=>"T-Shirt and Bag Check",
        ...
        "run_spans_attributes"=>{
          "0"=>{
            "timezone_name"=>"Eastern Time (US & Canada)",
            ...
)
…您可以使用如下结构进入
时区\u name

ActionController::Parameters.new(params).require(:sale).permit(:cloned_from, :type, options_attributes: [:title, run_spans_attributes: [:timezone_name]])
控制台中的返回值将为:

{"cloned_from"=>"", "type"=>"Localsale", "options_attributes"=>{"0"=>{"title"=>"T-Shirt and Bag Check", "run_spans_attributes"=>{"0"=>{"timezone_name"=>"Eastern Time (US & Canada)"}, "1429320288130"=>{"timezone_name"=>"Eastern Time (US & Canada)"}}}}}
2。将工作分成更小的部分

试图在一行中处理每个模型的所有允许属性可能会令人困惑。你可以把它分成几行,使事情更容易理解。从该结构开始,填写每个模型的附加属性:

video_attrs = []  # Fill in these empty arrays with the allowed parameters for each model
addresses_attrs = []
methods_attrs = []
run_spans_attrs = [:timezone_name]
event_option_attrs = []
options_attrs = [:title, event_option_attributes: event_option_attrs, run_spans_attributes: run_spans_attrs]
event_sale_attrs = []
opportunity_detail_attrs = []
other_contacts_attrs = []
billing_addresses_attrs = []
primary_contact_attrs = []
sales_attributes = [
  :cloned_from, 
  :type, 
  primary_contact_attributes: primary_contact_attrs, 
  billing_addresses_attributes: billing_addresses_attrs,
  other_contacts_attributes: other_contacts_attrs,
  options_attributes: options_attrs, 
  opportunity_detail_attributes: opportunity_detail_attrs,
  event_sale_attributes: event_sale_attrs,
  methods_attributes: methods_attrs,
  addresses_attributes: addresses_attrs,
  video_attributes: video_attrs
]
然后,您只需将
*sales\u属性
发送到允许的参数中即可。您可以在控制台中通过以下方式进行验证:

ActionController::Parameters.new(params).require(:sale).permit(*sales_attributes)
试试这个:

params.require(:sale).permit(:options_attributes => [:other_attributes, { :run_spans_attributes => [:timezone_name] }]

根据我在控制器中所做的工作,我认为以下是可行的:

params.require(:sale).permit(:cloned_form, ... billing_addresses_attributes: [:id, :city, :building] ...)

有效地,在属性“0”=>周围放上括号,不要忘记adf:id和:_销毁,就像我在回答中提到的那样,因为我最终创建了其他模型并使用了嵌套属性。

对于后代,我想让人们知道我们最终发现了什么:嗯,信息就在那里,事实上,我在Russ Olsen雄辩的Ruby中读到了它,在与一位更高级的开发人员进行调试时,我还记得这本书:“然而,随着Ruby 1.9的出现,哈希已经变得井然有序。”


为什么这么重要?我在控制器上按字母顺序排列了属性,由于
运行span\u属性
是如何设置的,它们需要
时区名称
在前面。如果不是的话,它就无法到达。你只能想象这是多么折磨我们。但至少我们现在知道:秩序很重要。所以,如果其他方法都失败了,请记住。

经过一些实验,我发现这个问题似乎只存在于整数字符串的散列键中

当我用非整数字符串替换整数字符串时,强参数接受散列

假设我们无法更改参数中的数据格式,一种解决方法是在遇到问题的级别(例如:run_span_attributes=>{})更改数据格式


如果您的表单用于修改模型,这将为使用任意散列打开的模型带来批量分配的风险——您需要记住这一点。

您失败的试验是什么?至少给一个!如果您可以将示例缩减到导致问题的位置,那将是非常好的—如果地址属性或其他联系人属性(例如)都可以,那么就不需要将它们包含在您的帖子中。如果您使用数组并为其提供键和值,那么当数组有子值时,您应该尝试用哈希替换数组。像这样
permit(:how,:the,:heck,:do,{u属性:{:make,它们自己:{:已知,外部:{:of,这些:[:darn,:圆括号],:和},:方括号}})
,当然像
:of
:和
这样的键理想情况下应该有值too@caesarsol,我在底部包含的格式失败,正如@Mohammad AbuShady所说的那样。在某一点上,@Frederick,代码无法访问某些属性,即使在
地址\属性
其他\合同\属性
中。我想我已经设法让他们看到了,但是在
运行span\u属性
起作用之前,我无法确定。我认为最好包括它们,以防它们仍然是一个问题。这是一个好主意。我在控制台中使用过一点,但只向下钻取了一次——直接从
options\u attributes
开始。一直到
:timezone\u name
,它都能正常工作,但在实践中却不起作用(因为它们太乱了)。只是提醒大家在控制台中“继续工作”(慢慢地),这是一个很好的建议。谢谢。我在我的回答中编辑并添加了第2节,建议如何通过将其分解为七个部分来组织