I'm trying to assert a method call happens where the first argument is a symbol like so:
Foo.bar(:some_key, {})
I don't really care what the second argument is at this stage.
I've tried:
Foo.expects(:bar).with(includes(:some_key))
and other variations found in the documentation here. The test passes when I expect the method call with any arguments.
Any ideas?
Have you tried this :
Foo.expects(:bar).with(:some_key, anything)
If you need to be more specific you can also use a block :
Foo.expects(:bar).with do |first_arg, second_arg|
first_arg == :some_key
end
Related
I want to invoke some system commands from a ruby script without having a shell fiddle with things. The catch is that at coding time I don't know how many args there will be.
If I were going through a shell I would build up the command line by concatenation...
I used to do this in perl by passing system and array with however many arguments I wanted. This worked because of the way parameters are passed in perl. Unsurprisingly Ruby does not support that.
Is there a way to do this?
Put the arguments in an array:
cmd = %w[ls -l -a]
and then splat that array when calling system:
system(*cmd)
# -----^ splat
That's the same as saying:
system('ls', '-l', '-a')
The same syntax is used to accept a variable number of arguments when calling a method:
def variadic_method(*args)
# This splat leaves all the arguments in the
# args array
...
end
Is this what you might be referring to? As shown on:
https://ruby-doc.com/docs/ProgrammingRuby/html/tut_methods.html
But what if you want to pass in a variable number of arguments, or want to capture multiple arguments into a single parameter? Placing an asterisk before the name of the parameter after the ``normal'' parameters does just that.
def varargs(arg1, *rest)
"Got #{arg1} and #{rest.join(', ')}"
end
varargs("one") » "Got one and "
varargs("one", "two") » "Got one and two"
varargs "one", "two", "three" » "Got one and two, three"
In this example, the first argument is assigned to the first method parameter as usual. However, the next parameter is prefixed with an asterisk, so all the remaining arguments are bundled into a new Array, which is then assigned to that parameter.>
I'm new to Ruby and doing some experimenting with NeoVim/ALE which I'm also new to. I'm coming from Perl using the syntastic plugin and I'm trying to figure out how to best set up NeoVim/ALE/RuboCop. I've never used a delinter before.
My confusion stems from this bit of code:
#!/usr/bin/env ruby
r = Array() # Improper array initialization, should be Array.new()
puts r
When run, I get:
Traceback (most recent call last):
1: from /Users/me/ruby/workshop/dink.rb:3:in `<main>'
/Users/me/ruby/workshop/dink.rb:3:in `Array': wrong number of arguments (given
0, expected 1) (ArgumentError)
RuboCop didn't catch this error. I turned syntastic on and it didn't catch the error either. I assume because it's a runtime error and not a compile time error like I thought it would be. Running ruby -c on the script yields no errors either. But perhaps I'm wrong and aren't using the syntax checking tools properly. Can someone please confirm that this is indeed a runtime error and that it's impossible to catch before executing the script?
I have a second question as well: Do I need syntastic with Ruby? Does it do anything more that RuboCop doesn't?
Thanks.
Both tools are correct, because there is the Array() method defined in Kernel.
That means this is not a syntax but a runtime error because that method expects at least one argument.
From the docs:
Array(arg) → array
Returns arg as an Array.
First tries to call to_ary on arg, then to_a. If arg does not respond to to_ary or to_a, returns an Array of length 1 containing arg.
I have a prompt in my "app", like irb that takes an input,I want it to parse the input and execute a function that I've defined.
Similarly, my app takes an input through gets, and calls the function.
For example,
command = gets.gsub("\n","")
takes an input "pwd", now I want to call the function pwd, which is defined below:
def pwd
Dir.pwd
end
Now, I could simply use if conditions to do so, but a lot of these conditions wouldn't be as elegant as Ruby's philosophy requires it to be.
The Question
I want to parse the input to call a defined function.
Like, "pwd" calls pwd,
"ls" calls its equivalent function that I have defined.
How do I do this?
Comment if question is still not clear.
Cheers.
Addressing Possible Duplicate
The question suggested specifically wants to run Shell commands. Whereas, I am using only built-in Ruby methods and classes and maybe in the future I'll even use Gems, so as to attain platform independence. My commands may look and behave like shell, but I'm not actually running shell. Therefore, my question is not a possible duplicate.
Furthermore, future readers will find it helpful for parsing input in Ruby.
You can write a mapping for the different inputs in the form of a case:
case command
when "pwd"
Dir.pwd # or move it into another method and call it here
when "ls"
# etc
end
or a hash, which is slightly more concise
actions = {
pwd: -> { Dir.pwd },
ls: -> { <foobar> }
}
actions[command.to_sym].call
You can also make method names matching the commands and use send, but don't do this if the input is coming from strangers:
def pwd
Dir.pwd
end
command = command.to_sym
send(command)
Why gives this code in ruby18 and ruby19 a syntax error:
a (b.c do;end)
I would have expected it to mean the following. A call to the method a with one argument. The parentheses after the space are not method argument parentheses, but only normal parentheses like you can put almost everywhere. The argument is the return value of the call to the method c on the object b with a block.
All of the following are however interpreted as syntactically correct by ruby18. Only the first of these examples is treated as syntactically incorrect by ruby19.
a (b do;end)
and:
a (b.c {})
and:
(b.c do;end)
Remove the space in between the method name and the (. Ruby used to warn that this was dodgy and it does seem to throw ruby 1.9 off in some cases.
So, I get this warning when I'm running my tests in ruby/RoR
.(eval):289: warning: don't put space before argument parentheses
I've checked every where (but obvoiusly not) and I can't find the origin of this error.
The above error just pops up inbetween the unit tests ...
Can someone clue me in onto how to find the location of this error?
The file and line number are contained in the backtrace. However, in your case, the warning is inside a string being evaled at runtime. Which means there is no file. (Actually, the eval method does take optional arguments for the file name and line number that should be displayed in a backtrace, but in this case whoever wrote the code in question unfortunately forgot to pass those arguments.)
I fear that you have no other choice than to manually examine every single call to eval in your entire codebase, and that includes Rails, your testing framework, your entire application, your tests, your plugins, your helpers, the ruby standard library, ...
Of course, you should be aware that the problem might not be obvious as in
eval 'foo (bar, baz)'
It could also be something like
def foo(*args)
puts args.join
end
bar = 'Hello'
baz = 'World'
foostr = 'foo' # in one file
barstr = 'bar' # in another file in a different directory
bazstr = 'baz' # in another file in a different directory
argstr = "(#{barstr}, #{bazstr})" # in yet another file
$, = ' ' # in some third-party plugin
str = [foostr, argstr].join # in a fourth file
eval str # somewhere else entirely
eval str, binding, __FILE__, __LINE__ # this is how it *should* be done
Note the difference between the two warning messages: the first one reads exactly like the one you posted, but the second one has the filename instead of (eval) and the line number inside the file instead of the line number inside the eval string.
By the way: the line number 289 in the warning message is the line number inside the evald string! In other words: somewhere in your application there is a string being evald, which is at least 289 lines long! (Actually, it is more likely that this done not in your application but rather in Rails. The Rails router used to be a particularly bad offender, I don't know if this is still the case.)
It sounds to me that there is a rule which forbids a space between a function name and the parentheses enclosing the arguments of the function.
In many languages this would be considered a permissible stylistic variation.
Is the eval mentioned in the warning message, the 'function' being complained about?
Does the number 289 mean anything as a line number?
Could you search your source files for a parenthesis preceded by a space?
Incidentally, the message says warning. What happens if you ignore it?
If it's happening in between the unit tests it might be in a setup or teardown method. Try searching for eval or try reducing the code you are running until the error goes away. Then you'll know where to look (the code you just removed).