阻止 ruby/rails 打印赋值表达式的结果

Prevent ruby/rails from printing results of assignment expressions

当我在 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 .

我猜这是因为在 Ruby 赋值 return 中自动赋值,即

a = 1
#=> 1

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

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

IRB.conf[:ECHO] = false

那应该禁用回显。

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

可在 irb documentation

中找到更多信息

编辑:

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

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

如果您有 1.2.6ECHO_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 将打印截断的版本(例如将 OMIT_ON_ASSIGNMENT 设置为 true 1.2.6).

请注意,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,因此无法保证它与未来的版本兼容。