【问题标题】:Rails - Pass collection to ActiveModel objectRails - 将集合传递给 ActiveModel 对象
【发布时间】:2014-03-11 09:37:36
【问题描述】:

我正在使用 Rails 制作一个使用 Ajax 分页的datatable,我正在关注railscast #340 这样做。

本集使用名为ProductsDatatable 或在我的情况下为OrdersDatatable 的普通ActiveModel 类来创建和配置表。我的问题与此类中的 ruby​​ 语法有关。我正在尝试将一组订单从控制器传递给OrdersDatatable 对象。我想在fetch_orders 方法中访问这个集合。

我在 order.rb 中这样创建表对象:

@datatable = OrdersDatatable.new(view_context)
@datatable.shop_id = @current_shop.id
@datatable.orders_list = @orders # which is Order.in_process

而我的OrdersDatatable 类看起来像这样:(可能需要更改的重要部分是initialize 中的第二行和fetch_orders 中的第一行)

class OrdersDatatable
  include Rails.application.routes.url_helpers
  include ActionView::Helpers::DateHelper
  include ActionView::Helpers::TagHelper

  delegate :params, :h, :link_to, :number_to_currency, to: :@view

  attr_accessor :shop_id, :orders_list

  def initialize(view)
    @view = view
    @orders_list = self.orders_list
  end

  def current_shop
    Shop.find(shop_id)
  end

  def as_json(options = {})
    {
      sEcho: params[:sEcho].to_i,
      iTotalRecords: orders.count,
      iTotalDisplayRecords: orders.count,
      aaData: data
    }
  end

private


  def data
    orders.map do |order|
      [
        order.id,
        order.name,
        h(time_tag(order.date_placed.in_time_zone)),
        order.state,
        order.source,
        order.payment_status,
        h(order.delivered? ? 'shipped' : 'unshipped'),
        h(number_to_currency order.final_total, unit: order.currency.symbol),
        h(link_to 'details', edit_admin_shop_order_path(current_shop, order)),
        h(link_to 'delete', admin_shop_order_path(current_shop, order), method: :delete, data: { confirm: 'Are you sure?' } ),
      ]
    end
  end

  def orders
    @orders ||= fetch_orders
  end

  def fetch_orders
    orders = orders_list.order("#{sort_column} #{sort_direction}")
    orders = orders.page(page).per_page(per_page)
    if params[:sSearch].present?
      orders = orders.where("title like :search", search: "%#{params[:sSearch]}%")
    end
    orders
  end

  def page
    params[:iDisplayStart].to_i/per_page + 1
  end

  def per_page
    params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10
  end

  def sort_column
    columns = %w[id name date_placed state source payment_status delivered final_total]
    columns[params[:iSortCol_0].to_i]
  end

  def sort_direction
    params[:sSortDir_0] == "desc" ? "desc" : "asc"
  end
end

当我将fetch_orders 中的第一行更改为此

orders = Order.in_process.order("#{sort_column} #{sort_direction}")

这是硬编码的等价物,它确实有效。所以我只需要正确的语法

【问题讨论】:

    标签: ruby-on-rails ruby parameters datatables activemodel


    【解决方案1】:

    简短回答:如果您有一个数组,并且想要对其进行排序,请使用sort_by 方法:

    orders = orders_list.sort_by{|order| "#{order.sort_column} #{order.sort_direction}"}
    

    长答案:您的原始代码不起作用的原因是在这种情况下

    Order.in_process.order("#{sort_column} #{sort_direction}")
    

    您正在构建一个查询。 in_process 是一个命名范围(在某些条件下传递),.order 告诉 rails 查询的顺序。然后,当链式方法用完时,查询会执行(运行一些 sql)并从数据库中获取记录以构建对象集合。

    一旦你在处理一个对象集合,你就不能在它上面调用.order 方法,因为它只是用来组装一个sql 查询。您需要改用Array#sort_bysort_by 接受一个代码块,将集合中的每个对象传递到该代码块中(在我的示例中为 order,但您可以将其命名为任何名称,它只是一个变量名)。

    顺便说一句,如果你只是想对所有对象调用一个方法来对它们进行排序,你可以使用像.sort_by(&:methodname) 这样的“快捷语法”。这使用了一个名为 Symbol#to_proc (http://railscasts.com/episodes/6-shortcut-blocks-with-symbol-to-proc) 的 ruby​​ 小技巧。

    例如,如果 Order 中有这样的方法

    def sort_string
      "#{self.sort_column} #{self.sort_direction}"
    end
    

    然后您可以将代码更改为

    orders = orders_list.sort_by(&:sort_string)
    

    这很整洁。

    【讨论】:

    • 问题不是排序不正确,而是集合没有正确访问。
    • 我需要一种方法来实际访问 orders_list。查看我的编辑
    • 我刚刚告诉你如何对orders_list 数组进行排序。我不确定您所说的“访问”是什么意思。
    • “它不起作用”也含糊不清:你的意思是它爆炸了,还是它给了你一些与你预期不同的结果?如果是后者,请说出它给您带来的结果。
    【解决方案2】:

    如果你有一个数组,那么你可以这样排序。

       orders = orders_list.sort! {|a,b| a.sort_column <=> b.sort_direction}
    

    【讨论】:

      猜你喜欢
      • 2012-10-14
      • 2014-11-04
      • 1970-01-01
      • 2011-01-04
      • 2012-08-28
      • 1970-01-01
      • 2010-10-09
      • 1970-01-01
      • 2012-09-28
      相关资源
      最近更新 更多