【问题标题】:Ruby on Rails sort array of multiple active recordRuby on Rails 排序多个活动记录的数组
【发布时间】:2018-03-09 02:25:47
【问题描述】:

我有 2 种活动记录(对象):

1.项目

<Project:0x007fd1b3ef3c10
id: 1,
min_price: 1000,
max_price: 2000>

2。属性

<Property:0x007fd1b3ef3c15
id: 1,
price: 1000>

它们位于数组 [项目、属性、项目等]
我需要按price 对它们进行排序,但如果是项目类型,那么我应该使用min_price。我可以在 Rails 中这样做吗?
我尝试使用sort_by,但不起作用。

例子

[
  <project  id:1, min_price:1, max:price:100>,
  <property id:2,     price:5>,
  <project  id:3, min_price:3, max:price:100>,
]

我希望它返回:

[
  <project  id:1, min_price:1, max:price:100>,
  <project  id:3, min_price:3, max:price:100>,
  <property id:2,     price:5>,

]

【问题讨论】:

    标签: ruby-on-rails arrays sorting activerecord


    【解决方案1】:

    您有多种选择:为这两种模型定义一个通用方法,或者仅使用 sort_by 和一个动态决定使用哪种方法进行排序的块。看看这个 sn-p:

    class Project
      attr_accessor :min_price
    
      alias_method :sort_price, :min_price
    
      def initialize(min_price)
        @min_price = min_price
      end
    end
    
    class Property
      attr_accessor :price
    
      alias_method :sort_price, :price
    
      def initialize(price)
        @price = price
      end
    end
    
    collection = [Project.new(10), Property.new(20), Project.new(5), Property.new(7)]
    puts collection.sort_by(&:sort_price).inspect
    
    puts(collection.sort_by do |record|
      record.is_a?(Project) ? record.min_price : record.price
    end.inspect)
    

    我个人更喜欢使用通用方法的解决方案,因为它更面向对象(遵循多态性)。如果你不想污染你的模型,你可以做一个装饰器来进行排序:

    class SortingItem
      attr_reader :object
    
      def initialize(object)
        @object = object
      end
    
      def sort_price
        case @object
        when Project
          @object.min_price
        when Property
          @object.price
        else
          fail ArgumentError, "unknown sorting item - #{object.class}"
        end
      end
    end
    
    class Project
      attr_accessor :min_price
    
      def initialize(min_price)
        @min_price = min_price
      end
    end
    
    class Property
      attr_accessor :price
    
      def initialize(price)
        @price = price
      end
    end
    
    def decorate(object)
      SortingItem.new(object)
    end
    
    collection = [decorate(Project.new(10)), decorate(Property.new(20)), decorate(Project.new(5)), decorate(Property.new(7))]
    puts collection.sort_by(&:sort_price).map(&:object).inspect
    

    【讨论】:

      猜你喜欢
      • 2016-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 1970-01-01
      • 2012-04-18
      • 2013-03-26
      相关资源
      最近更新 更多