【问题标题】:Prevent ruby/rails from printing results of assignment expressions防止 ruby​​/rails 打印赋值表达式的结果
【发布时间】:2019-03-12 18:25:24
【问题描述】:

当我在 Rails 中做这样的事情时:

irb(main):060:0> users = User.where(name: "Joe")

控制台将评估users 并将其打印出来(可能是inspectto_s,我不能100% 确定)。这会导致数百行我并不真正想要的输出。

我知道我可以做这样的事情来阻止特定行的输出:

irb(main):060:0> users = User.where(name: "Joe"); nil

因为nil 将被评估并打印出来,而不是users

我还可以通过以下方式关闭所有评估:

irb(main):060:0> conf.echo = false

第一个解决方案很烦人,因为您必须记住在要抑制输出的每一行上添加它。第二个很烦人,因为有时你确实想要输出。很多时候你只想输入一个变量的名字来打印它。

Python 似乎没有这个问题。如果我输入a = {1: 2},python shell 不会评估a,它只是再次显示提示。但如果我输入{1: 2} 或只是a,它会打印出值。

似乎 python 的控制台检查是否存在正在评估的语句的左侧以决定是否打印结果。

问题:

这样的事情可以在 ruby​​ 的控制台中完成吗?所以像a = {1 => 2} 这样的语句不会被评估,但是像a{1 => 2} 这样的语句是?

更新:

我将此合并请求推送到 irb 存储库,也许它会被接受,然后 会有办法:https://github.com/ruby/irb/pull/12

【问题讨论】:

  • Python 的行为是这样的,因为赋值是一个 statement(即没有值)。在 ruby​​ 中,赋值是一个表达式,包含它所需要的一切。
  • @SergioTulentsev 是的,我明白你在说什么。此外,如果 python 表达式返回 None 控制台不会打印任何内容。如果表达式是赋值,我只是有一种方法可以防止 irb 打印表达式的输出

标签: ruby-on-rails ruby irb


【解决方案1】:

编辑:

下面引用的 MR 版本已合并到 irb,但此后进行了几次调整。所以要获得你想要的行为取决于 irb 版本:

如果您至少有1.2.0,但少于1.2.6:默认行为是为赋值语句打印任何内容。如果您想要旧的行为(总是打印所有内容),则必须设置 IRB.conf[:ECHO_ON_ASSIGNMENT] = true

如果您有1.2.6,则ECHO_ON_ASSIGNMENT 的默认值更改为true,并添加了一个新的配置值:OMIT_ON_ASSIGNMENT,它将截断赋值语句的长输出,默认为true .因此,如果您不想为赋值语句打印任何内容,则必须设置 IRB.conf[:ECHO_ON_ASSIGNMENT] = false。如果您想要旧的行为(总是打印所有内容),则必须设置 IRB.conf[:OMIT_ON_ASSIGNMENT] = false

如果您有1.2.7 或更高版本,则删除OMIT_ON_ASSIGNMENT 以支持ECHO_ON_ASSIGNMENT 接受truefalse:truncate,默认值为:truncatetrue 的值将打印赋值语句的所有内容,false 将不打印任何内容,:truncate 将打印截断的版本(例如在 1.2.6 中将 OMIT_ON_ASSIGNMENT 设置为 true)。

请注意,irb gem 版本之上的版本,而不是 ruby​​ 版本(即使 irb 包含在 ruby​​ 的标准库中)。您可以通过查看IRB::VERSION 来检查您拥有的irb 的版本。非常旧的irb 版本没有设置这个常量,所以如果它丢失了,你肯定有一个低于1.2.0 的版本。

原答案:

在合并this pull request(或类似的)之前,您可以将以下内容放入您的~/.irbrc 文件中:

require 'ripper'
module IRB
  class Irb
    ASSIGNMENT_NODE_TYPES = [:assign, :opassign, :massign]
    def assignment_expression?(line)
      ASSIGNMENT_NODE_TYPES.include?(Ripper.sexp(line)&.dig(1,-1,0))
    end

    def output_value # :nodoc:
      return if assignment_expression?(@context.last_line)
      printf @context.return_format, @context.inspect_last_value
    end
  end

  class Context
    attr_accessor :last_line
    def evaluate(line, line_no, exception: nil) # :nodoc:
      @line_no = line_no
      @last_line = line
      if exception
        line = "begin ::Kernel.raise _; rescue _.class; #{line}; end"
        @workspace.local_variable_set(:_, exception)
      end
      set_last_value(@workspace.evaluate(self, line, irb_path, line_no))
    end
  end
end

请注意,由于此猴子补丁 IRB::IrbIRB::Context,因此无法保证它与未来版本兼容。

【讨论】:

    【解决方案2】:

    我猜这是因为在 Ruby 中赋值会自动返回分配的值,即

    a = 1
    #=> 1
    

    如果您深入研究conf.echo 的文档,您会发现它用于控制是否打印返回值。

    【讨论】:

      【解决方案3】:

      在您的 ~ 文件夹或当前文件夹中创建一个名为 .irbrc 的文件。在里面,添加:

      IRB.conf[:ECHO] = false
      

      这应该禁用回声。

      如果您puts IRB.conf,您会看到其他可以调整的设置。

      更多信息见irb documentation

      【讨论】:

      • 这不是相当被问到的。他们只想抑制分配的输出。
      • @SergioTulentsev 这是一个很好的区别,我在阅读时忽略了这一点。我认为 IRB 中没有这种行为的设置,但现在这可能已经足够了。当我想抑制输出时,我只是在语句(在撬)之后添加一个;
      猜你喜欢
      • 2015-12-29
      • 2018-01-21
      • 1970-01-01
      • 1970-01-01
      • 2020-03-25
      • 2013-05-10
      • 2016-11-04
      • 2019-10-20
      相关资源
      最近更新 更多