【问题标题】:How to show Rails ActiveRecord fields alphabetically in console如何在控制台中按字母顺序显示 Rails ActiveRecord 字段
【发布时间】:2018-10-11 22:47:01
【问题描述】:

找不到这个的配置或设置(已经用谷歌搜索了好几次)。在 Rails 控制台中检查某些模型对象时,为什么有时模型字段按字母顺序显示,而在其他部署中大多数时候却没有?

例子:

### FIELDS NOT SORTED
#rails console
(main)> l = Loan.find '123' 
 => #<Loan:0x000000066722e8
 id: "8f196106c00e",
 user_id: "f90084a53972",
 borrower_id: "043bb77b3aac",
 parent_id: nil,
 score_id: "f00c39e74570",
 number: 11231321,
 scoring_tag: nil,
 .....

但在其他部署中,当我进入 rails 控制台时

 # FIELDS SORTED ALPHABETICALLY
 (main)> l = Loan.find '123'
  => #<Loan:0x007fca8b45a468
  active_servicer_id: nil,
  amortization: nil,
  amount: 150000.0 (BigDecimal),
  application_fee: nil,
  borrower_id: "asdasdajdjasd",
  borrower_requested_closing_attorney: nil,
  channel: nil,
  closed_date: nil,
  commitment_end_at: nil,

如何使 Rails 控制台显示模型的输出排序?这在比较两条记录时有时是必要的。

【问题讨论】:

  • 我认为不存在这样的配置选项,您可能需要检查ActiveRecord::Base的检查方法。您是否尝试过将记录转换为哈希并按字母顺序排序?
  • 是的,我可以这样做,但我想看看是否有什么东西,这样我就不必每次登录到不同的服务器时都这样做。
  • 为什么这是您想要/需要做的事情?
  • 旁注,我的同事本周向我的团队展示了这颗宝石。您可能会发现它很有帮助。 github.com/awesome-print/awesome_print/blob/master/README.md

标签: ruby-on-rails ruby activerecord


【解决方案1】:

如果你只是想打印出属性,你可以更明确地这样做:

Loan.find(123).attributes.sort_by(&amp;:first).to_h

如果您真的希望控制台打印执行此操作,您可能需要覆盖 inspect 方法。至少对于 irb 和其他一些控制台,这是确定打印内容的方法。如果您有控制台正在使用的其他插件或 gem,您可能需要查看文档以找到合适的方法。

类似的东西(如你所愿修改,例如更好地模仿默认的inspect,显示object_id等)

class Loan ...
  def inspect
    (self.class.name + ": " + attributes.sort_by(&:first).to_h).to_s
  end
end

【讨论】:

【解决方案2】:

在 Ruby 的 Hash 中,其元素的顺序是任意的。当它是 inspect-ed 时(如在 rails 控制台的输出中),方法 inspect 只使用 each_pair 或类似的东西,因此顺序可以是任意的。在实践中,Hash#each_pair 的顺序通常似乎遵循每个 Hash 元素的创建顺序;但是不能保证!此外,Rails(或 ActiveRecord)如何创建这些实例是另一个问题(我猜您看到的字母顺序源于 Rails 如何创建它们;它可能与它们在数据库中的存储方式有关)。无论如何,底线是您无法控制它们的存储方式,只要使用哈希即可。但是您可以调整它们的 inspect-ed 方式。

以下策略是为它的任何子类重新定义ApplicationRecord#inspect,这样任何模型的inspect 方法都会被修改,但不会修改任何其他类。

将以下代码放入您的app/ 目录中的任何文件中(例如,一个明显的文件名是/app/models/application_record.rb):

class ApplicationRecord
  alias_method :inspect_orig, :inspect if ! self.method_defined?(:inspect_orig)
  def inspect
    klass = self.class 
    if klass == ApplicationRecord
      return inspect_orig
    end
    attr_list = attribute_names.sort.map { |name| "#{name}: "+attributes[name].inspect }.join ', '
    sprintf('<%s:0x%s %s>', klass.name, object_id.to_s(16), attr_list)
  end
end

或者,如果您只想在会话期间临时激活它,则可以在每次打开 rails console 时运行它。

注意ApplicationRecord的父类名称可以添加如下(在Rails 5.2的情况下;但我不认为包含父类是强制性的,因为应该定义类ApplicationRecord在读取文件之前)。

class ApplicationRecord < ActiveRecord::Base

我注意到您的 Rails 控制台输出看起来与我的 Rails 5.2.1 略有不同,可能是由于版本不同(?)。在上面的代码 sn-p 中,我试图模仿你似乎得到的输出。无论如何调整它到你的喜好;现在你可以完全控制它了!

EDIT1
上面的描述适用于 Rails 5。在 Rails 4 中,类名应该是

class ActiveRecord::Base

EDIT2
在上面的代码 sn-p 中,它显示了#object_idn.b.,它在 Rails 5.2 中不显示)。但是,#inspect 显示的对象实例与#object_id 不同,如this answer 中详细说明的那样。如果你喜欢显示它,一个方法是这样(左边的值是sprintf的格式):

'0x%016x' % (object_id << 1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    相关资源
    最近更新 更多