【问题标题】:How do I pass a single object, a collection &/or an ActiveRecord Collection Object to a class initialization method?如何将单个对象、集合和/或 ActiveRecord 集合对象传递给类初始化方法?
【发布时间】:2017-03-10 08:52:58
【问题描述】:

我有一个如下所示的课程:

class ExtractDiffLineInfo

  def initialize(*diffs)
    @diffs = diffs
  end

  def all_line_num_starts
    result = []
    @diffs.each do |diff|
      diff.body.lines.each do |diff_line|
        if (m = diff_line.match(/\A@@\s+\-(\d+),(\d+)\s+\+(\d+),(\d+)\s+@@/))
          a_start = m[1].to_i
          result << a_start + 3
        end
      end
    end
    result
  end

当我尝试传递 ActiveRecord Collection 对象时,我收到 ActiveRecord Collection Proxy 错误。

我正在尝试传递以下@diffs AR Collection:

> @diffs
=> [#<Diff:0x007fc064000510
  id: 13645,
  body:
   "@@ -1856,7 +1856,7 @@ def destroy_associations\n             hm_options[k] = options[k] if options.key? k\n           end\n \n-          has_many name, scope, hm_options, &extension\n+          ActiveSupport::Deprecation.silence { has_many name, scope, hm_options, &extension }\n           _reflections[name.to_s].parent_reflection = habtm_reflection\n         end\n       end",
  commit_id: 1,
  author: "Ryuta Kamizono",
  author_gh_profile: "https://github.com/kamipo",
  author_gh_avatar: "https://avatars.githubusercontent.com/u/12642?v=3",
  commit_url: "https://github.com/rails/rails/commit/3cd4c7c0ffc3e00004a238304e903a140fcbcd67",
  commit_msg:
   "Suppress deprecation message to `has_and_belongs_to_many` only once\n\nPassing a class to `has_and_belongs_to_many` show deprecation message\nthree times. It is enough only once.",
  gh_sha: "3cd4c7c0ffc3e00004a238304e903a140fcbcd67",
  commit_date: Mon, 09 Jan 2017 20:00:53 UTC +00:00,
  created_at: Fri, 10 Mar 2017 08:33:38 UTC +00:00,
  updated_at: Fri, 10 Mar 2017 08:33:38 UTC +00:00,
  position: nil,
  num_additions: 2,
  num_deletions: 2,
  num_changes: 4,
  starting_line_num: 1859>,
 #<Diff:0x007fc063c2f648
  id: 13644,
  body:
   "@@ -1827,7 +1827,7 @@ def has_and_belongs_to_many(name, scope = nil, **options, &extension)\n \n           builder = Builder::HasAndBelongsToMany.new name, self, options\n \n-          join_model = builder.through_model\n+          join_model = ActiveSupport::Deprecation.silence { builder.through_model }\n \n           const_set join_model.name, join_model\n           private_constant join_model.name\n",
  commit_id: 1,
  author: "Ryuta Kamizono",
  author_gh_profile: "https://github.com/kamipo",
  author_gh_avatar: "https://avatars.githubusercontent.com/u/12642?v=3",
  commit_url: "https://github.com/rails/rails/commit/3cd4c7c0ffc3e00004a238304e903a140fcbcd67",
  commit_msg:
   "Suppress deprecation message to `has_and_belongs_to_many` only once\n\nPassing a class to `has_and_belongs_to_many` show deprecation message\nthree times. It is enough only once.",
  gh_sha: "3cd4c7c0ffc3e00004a238304e903a140fcbcd67",
  commit_date: Mon, 09 Jan 2017 20:00:53 UTC +00:00,
  created_at: Fri, 10 Mar 2017 08:33:30 UTC +00:00,
  updated_at: Fri, 10 Mar 2017 08:33:30 UTC +00:00,
  position: nil,
  num_additions: 2,
  num_deletions: 2,
  num_changes: 4,
  starting_line_num: 1830>]

这样传递:

@diff_line_nums = ExtractDiffLineInfo.new(@diffs).all_line_num_starts

这是我得到的错误:

NoMethodError at /rails/associations-rb/3cd4c7c0ffc3e00004a238304e903a140fcbcd67
undefined method `body' for #<Diff::ActiveRecord_Associations_CollectionProxy:0x007fc0628280c8>

当我检查正在调用 .bodydiff 对象时,我看到了这个:

>> diff
=> #<ActiveRecord::Associations::CollectionProxy [#<Diff id: 13645, body: "@@ -1856,7 +1856,7 @@ def destroy_associations\n   ...", commit_id: 1, author: "Ryuta Kamizono", author_gh_profile: "https://github.com/kamipo", author_gh_avatar: "https://avatars.githubusercontent.com/u/12642?v=3", commit_url: "https://github.com/rails/rails/commit/3cd4c7c0ffc3...", commit_msg: "Suppress deprecation message to `has_and_belongs_t...", gh_sha: "3cd4c7c0ffc3e00004a238304e903a140fcbcd67", commit_date: "2017-01-09 20:00:53", created_at: "2017-03-10 08:33:38", updated_at: "2017-03-10 08:33:38", position: nil, num_additions: 2, num_deletions: 2, num_changes: 4, starting_line_num: 1859>, #<Diff id: 13644, body: "@@ -1827,7 +1827,7 @@ def has_and_belongs_to_many(...", commit_id: 1, author: "Ryuta Kamizono", author_gh_profile: "https://github.com/kamipo", author_gh_avatar: "https://avatars.githubusercontent.com/u/12642?v=3", commit_url: "https://github.com/rails/rails/commit/3cd4c7c0ffc3...", commit_msg: "Suppress deprecation message to `has_and_belongs_t...", gh_sha: "3cd4c7c0ffc3e00004a238304e903a140fcbcd67", commit_date: "2017-01-09 20:00:53", created_at: "2017-03-10 08:33:30", updated_at: "2017-03-10 08:33:30", position: nil, num_additions: 2, num_deletions: 2, num_changes: 4, starting_line_num: 1830>]>

奇怪的是,如果我在运行时 binding.pry 进入 initialize 方法并检查传入的 diffs 参数,我会看到一个嵌套数组:

   4: def initialize(*diffs)
 => 5:   binding.pry
    6:   @diffs = diffs
    7: end

[1] pry(#<ExtractDiffLineInfo>)> diffs
=> [[#<Diff:0x007fc065d635a8
   id: 13645,
   body:
    "@@ -1856,7 +1856,7 @@ def destroy_associations\n             hm_options[k] = options[k] if options.key? k\n           end\n \n-          has_many name, scope, hm_options, &extension\n+          ActiveSupport::Deprecation.silence { has_many name, scope, hm_options, &extension }\n           _reflections[name.to_s].parent_reflection = habtm_reflection\n         end\n       end",
   commit_id: 1,
   author: "Ryuta Kamizono",
   author_gh_profile: "https://github.com/kamipo",
   author_gh_avatar: "https://avatars.githubusercontent.com/u/12642?v=3",
   commit_url: "https://github.com/rails/rails/commit/3cd4c7c0ffc3e00004a238304e903a140fcbcd67",
   commit_msg:
    "Suppress deprecation message to `has_and_belongs_to_many` only once\n\nPassing a class to `has_and_belongs_to_many` show deprecation message\nthree times. It is enough only once.",
   gh_sha: "3cd4c7c0ffc3e00004a238304e903a140fcbcd67",
   commit_date: Mon, 09 Jan 2017 20:00:53 UTC +00:00,
   created_at: Fri, 10 Mar 2017 08:33:38 UTC +00:00,
   updated_at: Fri, 10 Mar 2017 08:33:38 UTC +00:00,
   position: nil,
   num_additions: 2,
   num_deletions: 2,
   num_changes: 4,
   starting_line_num: 1859>,
  #<Diff:0x007fc05bf57c88
   id: 13644,
   body:
    "@@ -1827,7 +1827,7 @@ def has_and_belongs_to_many(name, scope = nil, **options, &extension)\n \n           builder = Builder::HasAndBelongsToMany.new name, self, options\n \n-          join_model = builder.through_model\n+          join_model = ActiveSupport::Deprecation.silence { builder.through_model }\n \n           const_set join_model.name, join_model\n           private_constant join_model.name\n",
   commit_id: 1,
   author: "Ryuta Kamizono",
   author_gh_profile: "https://github.com/kamipo",
   author_gh_avatar: "https://avatars.githubusercontent.com/u/12642?v=3",
   commit_url: "https://github.com/rails/rails/commit/3cd4c7c0ffc3e00004a238304e903a140fcbcd67",
   commit_msg:
    "Suppress deprecation message to `has_and_belongs_to_many` only once\n\nPassing a class to `has_and_belongs_to_many` show deprecation message\nthree times. It is enough only once.",
   gh_sha: "3cd4c7c0ffc3e00004a238304e903a140fcbcd67",
   commit_date: Mon, 09 Jan 2017 20:00:53 UTC +00:00,
   created_at: Fri, 10 Mar 2017 08:33:30 UTC +00:00,
   updated_at: Fri, 10 Mar 2017 08:33:30 UTC +00:00,
   position: nil,
   num_additions: 2,
   num_deletions: 2,
   num_changes: 4,
   starting_line_num: 1830>]]

这可能是什么原因造成的,我该如何解决?

【问题讨论】:

    标签: ruby-on-rails ruby activerecord ruby-on-rails-5


    【解决方案1】:

    这是因为你的口水

      def initialize(*diffs) # <- this one
        @diffs = diffs
      end
    

    您可以通过这样做来克服它,例如:

    ExtractDiffLineInfo.new(*@diffs.to_a).all_line_num_starts
    

    或者在初始化器中展开数组

    def initialize(*diffs)
      @diffs = @diffs.flatten # _should_ work on activerelations, didn't test.
    end
    

    如果我是你,我会放弃 splat 并放弃通过单个差异的能力。

    我需要能够轻松管理单个差异

    你可以有专门的工厂方法。像这样的:

    class ExtractDiffLineInfo
    
      def self.for_one_diff(diff)
        new([diff])
      end
    
      def self.for_many_diffs(diffs)
        new(diffs)
      end
    
      def initialize(*diffs)
        @diffs = diffs
      end
    end
    
    ExtractDiffLineInfo.for_one_diff(my_diff).all_line_num_starts
    ExtractDiffLineInfo.for_many_diffs(@diffs).all_line_num_starts
    

    【讨论】:

    • 我需要能够轻松管理单个差异。我找不到另一种方法来做到这一点。我有时确实需要处理一个差异,但我不想要太多重复的代码......我已经足够了:(
    • 好吧,那就按照我的回答去做吧。
    • 这是一个很棒的实现,唯一的问题是,我不知道传递给该方法的diffs是单数还是提前集合,因为有一个关联diffs是相关。如何将其修改为仅 1 个调用而不是两个不同的调用?
    • @marcamillion:之前的建议,放弃吧。
    猜你喜欢
    • 2010-09-25
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-04
    • 2018-10-05
    • 1970-01-01
    相关资源
    最近更新 更多