grouped_collection_select - group_method从Rails 3更改为4

时间:2017-02-16 22:07:05

标签: ruby-on-rails ruby ruby-on-rails-4 ruby-on-rails-3.2

我们正在从Rails 3.2.13迁移到Rails 4.0.13。

我们使用Rails帮助器grouped_collection_select来嵌套<optgroup> s。

我注意到从Rails 3.2.13到4.0.2有源更改。

http://apidock.com/rails/v4.0.2/ActionView/Helpers/FormOptionsHelper/grouped_collection_select

我们目前无法使用该方法。

这里是我们的代码:

<%= f.grouped_collection_select :location_id, @participating_businesses, :"active_locations(#{current_user.id})", :name, :id, :name, {prompt: t('.prompt_select_location')}, class: 'location-selector form-control' %>

这是错误:

ActionView::Template::Error (undefined method `active_locations(7)' for #<ParticipatingBusiness:0x005583478f1f90>):

现在很清楚,他们已经改变了方法的发送方式。

我猜测他们目前正抓住group_method选项并将其直接放入send(:group_method),这解释了上述错误。

但是,如何将参数传递给依赖于Session(又名current_user)的group_method

从源头上看,我认为这很不可能。

http://www.rubydoc.info/docs/rails/4.1.7/ActionView/Helpers/Tags/GroupedCollectionSelect#initialize-instance_method

我是否应该考虑重写这个以实现我们的目标,没有帮助者或者更多手册?

有没有人遇到同样的问题?

1 个答案:

答案 0 :(得分:1)

这令人沮丧。

我已经挖掘了4.1.13的Rails源代码和问题option_groups_from_collection_for_select中的函数。

  def option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)
    collection.map do |group|
      option_tags = options_from_collection_for_select(
        group.send(group_method), option_key_method, option_value_method, selected_key)

      content_tag("optgroup".freeze, option_tags, label: group.send(group_label_method))
    end.join.html_safe
  end

https://github.com/rails/rails/blob/92703a9ea5d8b96f30e0b706b801c9185ef14f0e/actionview/lib/action_view/helpers/form_options_helper.rb#L455

method_group直接发送至send

正如Taryn East所建议的那样,我已经尝试将group_method作为符号数组和该方法的参数。

然而,这会引发TypeError - [:accessible_locations, 15] is not a symbol

send引发,因为此数组需要在send调用中使用splat运算符作为方法参数。

现在这提出了一个重要的问题,就是我们如何回答最初的问题。

之前是如何运作的?

在Github上查看旧Rails版本的源代码没有显示出任何差异,所以我使用了代码并发现了这个:

421: def option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)
422:   collection.map do |group|
423:     group_label_string = eval("group.#{group_label_method}")
424:     "<optgroup label=\"#{ERB::Util.html_escape(group_label_string)}\">" +
425:       options_from_collection_for_select(eval("group.#{group_method}"), option_key_method, option_value_method, selected_key) +
426:       '</optgroup>'
427:   end.join.html_safe
428: end

之前它是如何运作的。

由于eval整个group.group_method方法代码是undefined method - method_name(args),因此不会提升grouped_options_for_select

所以答案是,是的,重写是必要的。

我通过使用{{1}}帮助程序并构建数组来解决这个问题。

http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/grouped_options_for_select