Ruby - 数组的未定义方法排序

时间:2013-06-11 03:45:15

标签: ruby-on-rails ruby

我很难过:

我试图在控制器中对数组进行排序,如下所示:

控制器

@sorted = sort_by_reviews(@search, "count")

模型

def self.sort_by_reviews(array, type)
if type == "count"
  array.sort! { |x, y| y.reviews.count <=> x.reviews.count }
else
  array.sort! { |x, y| y.reviews.average.to_f <=> x.reviews.average.to_f }
end

但是,我收到此错误:

undefined method `sort_by_reviews' for #<BuildingsController:0x007f80d89be320>

令人困惑的是,当我在我的控制器中执行此操作时:

@sorted = @search.sort! { |x, y| y.reviews.count <=> x.reviews.count }

工作正常。

我做错了什么?

---更新

我的完整控制器代码:

@search = Model.search_attributes(params[:search])
@sorted = @search.sort_by_reviews "count"

我的调整模型方法:

def sort_by_reviews(type)
if type == "count"
   self.sort! { |x, y| y.reviews.count <=> x.reviews.count }
 else
   self.sort! { |x, y| y.reviews.average.to_f <=> x.reviews.average.to_f }
 end
end

我仍然得到同样的错误:

undefined method `sort_by_reviews' for #<Array:0x007f80d423ee50>

3 个答案:

答案 0 :(得分:3)

您将sort_by_reviews定义为模型上的类方法,但将其作为控制器上的实例方法。我必须看到更多代码才能获得如何继续的建议,但可能会将模型更改为:

def sort_by_reviews(type)
  if type == "count"
    self.sort! { |x, y| y.reviews.count <=> x.reviews.count }
  else
    self.sort! { |x, y| y.reviews.average.to_f <=> x.reviews.average.to_f }
  end
end

和控制器

@sorted = @search.sort_by_reviews "count"

答案 1 :(得分:2)

控制器:

@sorted = sort_by_reviews(@search, "count")

型号:

def self.sort_by_reviews(array, type)
if type == "count"
  array.sort! { |x, y| y.reviews.count <=> x.reviews.count }
else
  array.sort! { |x, y| y.reviews.average.to_f <=> x.reviews.average.to_f }
end

在模型中,您使用的是类方法。所以,在控制器中你只需要这样称呼它:

@sorted = ModelName.sort_by_reviews(@search, "count")

例如,您的模型名称为Foo,表示:

@sorted = Foo.sort_by_reviews(@search, "count")

答案 2 :(得分:0)

虽然Rajendran的回答有效,但我真的不喜欢这种结构。您正在Model类上实现一个方法,该方法根据参数对数组进行排序。有趣且可重用的代码片段是获取Model类对象并对其进行比较的部分。应该提取该代码,以便可以在需要比较模型对象的任何地方使用它。

这样的事情:

class Model
  def self.compare_by_reviews_count_desc(x,y)  # Descending order of review count
    y.reviews.count <=> x.reviews.count
  end

  def self.compare_by_reviews_average_desc(x,y) # Descending order of review average
    y.reviews.average.to_f <=> x.reviews.average.to_f
  end

  # These functions return method objects for use in other functions
  def self.reviews_count_desc_sorter  
    method(:compare_by_reviews_count_desc)
  end

  def self.reviews_average_desc_sorter
    method(:compare_by_reviews_average_desc)
  end
end

然后在你的Controller中,@search是一个模型数组,而不是

@sorted = sort_by_reviews(@search, "count")

你会有

@sorted = @search.sort &Model.reviews_count_desc_sorter

然后,如果你想按平均评论排序,你就可以

@sorted = @search.sort &Model.reviews_average_desc_sorter

它有点冗长,但现在你有sortsort!的能力,并且你正在排序的集合的细节没有嵌入到模型中,而细节则如何进行比较仍然封装在模型中。