Rubycop输出如下消息:
app/controllers/welcome_controller.rb:1:1: C: Missing top-level class documentation comment.
class WelcomeController < ApplicationController
^^^^^
Run Code Online (Sandbox Code Playgroud)
我想知道顶级类文档是什么样的.这不只是一个评论,是吗?它需要有一种特殊的格式,但哪一种?
是否可以使用块初始化对象,如下所示?
class Foo
attr_reader :bar,:baz
def initialize(bar,baz)
@bar, @baz = bar, baz
end
end
Foo.new do |bar, baz|
# some logic to be implemented
# @bar, @baz to be assigned
end
Run Code Online (Sandbox Code Playgroud) 我们可以轻松定义一个方法,并将其转换为带有一元&符号的块.
def my_method(arg)
puts arg*2
end
['foo', 'bar'].each(&method(:my_method))
# foofoo
# barbar
# or
my_method = ->(arg) { puts arg*2 }
['foo', 'bar'].each(&my_method)
# same output
Run Code Online (Sandbox Code Playgroud)
正如我们所看到的,当我们使用聚合时,第一个参数会自动传递.但是,如果我们需要传递2个甚至更多的参数呢?
my_method = ->(arg,num) { puts arg*num }
['foo', 'bar'].each(&my_method)
# ArgumentError: wrong number of arguments (1 for 2)
['foo', 'bar'].each(&my_method(3))
# NoMethodError: undefined method `foo' for main:Object
['foo','bar'].each do |i, &my_method|
yield i, 3
end
# LocalJumpError: no block given (yield)
Run Code Online (Sandbox Code Playgroud)
在将proc转换为块时,是否可以传递其他参数?
从模块返回类似proc的方法非常容易:
module Foo
def self.bar
# Method implementation
end
def self.baz
# Method implementation
end
def self.qux
# Method implemenatation
end
def self.zoo
# Method implementation
end
end
Foo.method(:bar) # Returns a proc object
Run Code Online (Sandbox Code Playgroud)
但是如果我想从同一个模块返回多个(但不是全部)方法呢?一种方法是:[:bar,:baz].inject([]) {|memo,i| memo << Foo.method(i)}
是否有更好,更灵活的方式来做同样的事情?
我正在寻找在方法中定义实例变量的更短initialize方法:
class MyClass
attr_accessor :foo, :bar, :baz, :qux
# Typing same stuff all the time is boring
def initialize(foo, bar, baz, qux)
@foo, @bar, @baz, @qux = foo, bar, baz, qux
end
end
Run Code Online (Sandbox Code Playgroud)
Ruby有没有任何内置功能可以避免这种猴子的工作?
# e. g.
class MyClass
attr_accessor :foo, :bar, :baz, :qux
# Typing same stuff all the time is boring
def initialize(foo, bar, baz, qux)
# Leveraging built-in language feature
# instance variables are defined automatically
end
end
Run Code Online (Sandbox Code Playgroud) 我想ActionDispatch request在我的规范中用helper方法设置重要的标题:
RSpec.describe API::V1::FoosController, type: :request do
describe 'GET #index' do
context 'common case' do
request.env.merge!({'HTTP_FOO': 'FOO'})
get api_foos_path, {}, {Accept: Mime::JSON}
end
end
end
Run Code Online (Sandbox Code Playgroud)
但是request当涉及到控制器时,这个标题(通常是任何标题集)都会消失:
class API::V1::FoosController < ApplicationController
respond_to :json, :xml
def index
request.env.has_key? 'HTTP_FOO' # false
respond_with serialize_models(Foo.all)
end
# ...
end
Run Code Online (Sandbox Code Playgroud)
为什么会发生这种情况?如何正确设置?设置标题request.header或@request.header使用相同的标题.
PS:我知道我可以将标题设置为Rack::Test::Methods助手的第三个参数,但我不想违反DRY - 我只想在那里定义Mime格式.
let并let!提供有用的功能。有时可能需要在不同的规范中包含相同的助手(DRY)。例如,一组 let 以某种方式包含在每个请求规范中。有办法做这样的事情吗?
如何从模型实例中获取多个属性,例如
Resource.first.attributes(:foo, :bar, :baz)
# or
Resource.where(foo: 1).fetch(:foo, :bar, :baz)
Run Code Online (Sandbox Code Playgroud)
而是返回所有属性并手动选择它们.
该Array#fill方法能够同时具有对象和块.为什么它设计用于块,绝对索引通过?从实践角度看,有什么好处?
通过阅读Ruby编程语言,我找到了一个使用alias关键字来扩充方法的例子.
def hello # A nice simple method
puts 'Hello world' # Suppose we want to augment it...
end
alias original_hello hello # Give the method a backup name
def hello # Now we define a new method with the old name
puts "Your attention please" # That does some stuff
original_hello # Then calls the original method
puts "This has been a test" # Then does some more stuff
end
Run Code Online (Sandbox Code Playgroud)
事实上original hello,即使在重新定义它引用的方法之后,也会保留旧的行为.
但是,在我看来,这个例子几乎没有说明这种技术的真正好处.不能以传统方式实现(例如通过提供块)?那为什么要用这个成语呢?任何人都能提供一个来自现实世界的例子,当 …
当我尝试将任意块传递给each_with_object方法时,会引发错误:
%w(foo bar baz).each_with_object([]) &->(i,m) { m << i.upcase }
# => NoMethodError: undefined method `&' for #<Enumerator: ["foo", "bar", "baz"]:each_with_object([])>
Run Code Online (Sandbox Code Playgroud)
当我尝试将块传递给inject方法时,它也会引发错误:
%w(foo bar baz).inject('') &->(m,i) { m + i.upcase }
# => NoMethodError: undefined method `' for "foo":String
Run Code Online (Sandbox Code Playgroud)
但是如果我没有传递初始值,它就有效:
%w(foo bar baz).split.inject &->(m,i) { m + i.upcase }
Run Code Online (Sandbox Code Playgroud)
当我将块传递给each方法时,它也可以工作.
%w(foo bar baz).each &->(i) { puts i.upcase }
# FOO
# BAR
# BAZ
Run Code Online (Sandbox Code Playgroud)
谁能解释这种行为?如何将任意块传递给前两个示例?