How to pass the second parameter to Mongo::Collection#find? - ruby

This is a newbie question. I find the method definition in the YARD Rdoc:
(Object) find(selector = {}, opts = {})
Options Hash (opts):
:fields (Array, Hash)
then I try this coll.find('English' => 'fulcrum',{English:1,Chinese:1}), want the result 'English' field is fulcrum ,and only return English and Chinese field, but Ruby punished me with the this
irb(main):018:0> coll.find('English' => 'fulcrum',{English:1,Chinese:1})
SyntaxError: (irb):18: syntax error, unexpected ')', expecting tASSOC
from /usr/local/bin/irb:12:in `<main>'
irb(main):019:0>
I want to know why, thanks
after correct the syntax problem by the suggestion by #mu, I got Unknown options error:
irb(main):013:0> coll.find({English:'fulcrum'},{English:1, :Chinese => 1})RuntimeError: Unknown options [{:English=>1, :Chinese=>1}]
from /usr/local/lib/ruby/gems/1.9.1/gems/mongo-1.5.2/lib/mongo/collection.rb:234:in `find'
from (irb):13
from /usr/local/bin/irb:12:in `<main>'
irb(main):014:0>

When Ruby sees an unwrapped Hash in argument list:
o.m(k => v, ...)
it assumes that you really mean this:
o.m({ k => v, ... })
So, when you say this:
coll.find('English' => 'fulcrum', {English: 1, Chinese: 1})
Ruby sees this:
coll.find({ 'English' => 'fulcrum', {English: 1, Chinese: 1} })
A Hash is a perfectly valid key so Ruby expects it to be followed by a => value:
coll.find('English' => 'fulcrum', {English: 1, Chinese: 1} => some_value)
and that's where the error message comes from:
syntax error, unexpected ')', expecting tASSOC
If you want to pass two hashes, you need to wrap the first one in braces:
coll.find({'English' => 'fulcrum'}, {English: 1, Chinese: 1})
The second argument to [find](
http://api.mongodb.org/ruby/current/Mongo/Collection.html#find-instance_method) should be an options Hash and it looks like you want the :fields option and you can give that an array of names instead of a noisy Hash:
coll.find({'English' => 'fulcrum'}, :fields => %w[English Chinese])

Related

What does a hash without a key mean in Ruby?

What does the {TOKEN} and {ACCOUNT_ID} mean in the following Ruby?
my_function({
:amount => 2000,
:currency => "usd",
:source => {TOKEN},
:destination => {ACCOUNT_ID}
})
I have Ruby 2.3.1 and am getting an error syntax error, unexpected '}', expecting => (SyntaxError)
A hash needs to be defined as either empty or with key, value pairs (see here). I'm guessing if you are following some sort of a tutorial, you need to fill those values in with some constants.
Usually variables in CAPS are constants, but it is possible to define a method in caps. Even so, one would need to call it explicitly with braces, as in TOKEN() and I can't think of anything that could be put inside curly braces to initialize a hash of some sort.
You probably need to end up with a structure like this:
my_function({
:amount => 2000,
:currency => "usd",
:source => "THE TOKEN",
:destination => "THE ACCOUNT ID"
})
or
my_function({
:amount => 2000,
:currency => "usd",
:source => "ckjnsdncc98n9dnx93d372n",
:destination => 123456
})
The {X} syntax looks like it's used as a placeholder for either Strings or numbers (most likely Strings)

What is the difference between Ruby hash construction with "=>" or ":"?

What is the difference between these examples?
a = {'a' : 'b'}
a = {'a' => 'b'}
The first one is wrong, and gives you a syntax error. With the second syntax, you can use a key of any class. Otherwise, this syntax is just a shortcut for a symbol key.
a = {a: 'b'}
is equivalent to:
a = {:a => 'b'}

What is the proper way to pass a hash as a parameter to function call?

I have a function:
def a p
p
end
and a hash of symbols :a => :b. How should I pass it as a's parameter? What are possible ways?
I can use parentheses or the shorter form:
a(:a => :b) # => {:a=>:b}
a(a: :b) # => {:a=>:b}
Is there any way to pass this hash as a parameter without setting a variable and using parens? Just omitting them doesn't work.
a :a => :b # => SyntaxError: (irb):103: syntax error, unexpected ':', expecting end-of-input
a a: :b # => SyntaxError: (irb):105: syntax error, unexpected ':', expecting end-of-input

Hash declaration syntax error in irb

1. { :a => 10 } #=> no error
2. { a: 10 } #=> no error
3. { :"str" => 10 } #=> no error
4. { "str": 10 } #=> syntax error, unexpected ':', expecting =>
Isn't 4. same as 2? Why 2 is working and 4 throws syntax error?
My understanding is that {"key": value} is not a valid syntax as it is not clear whether it means {:"key" => value} or {"key" => value}
There is a discussion on this here. Quote from Matz in the discussion
| Iff {'key': 'value'} means {:key => 'value'} I have no objection.
| Won't that be misleading? I think the OP wants {'key': 'value'} to mean {'key' => 'value}
But considering the fact that {key: "value"}
is a shorthand for {:key => "value"}, {"key": "value"} should be a
shorthand for {:"key" => "value"}. Besides that, since it reminds me
JSON so much, making a: and "a": different could cause more confusion
than the above misleading.
matz.
Hash: Hashes allow an alternate syntax form when your keys are always symbols.
options = { :font_size => 10, :font_family => "Arial" }
You could write it as:
options = { font_size: 10, font_family: "Arial" }
In your first 3 cases all are symbols in key position,but the fourth is a string instance,not the symbol instance as key.That's the reason 4th case is invalid Ruby syntax.
{ :a => 10 }.keys[0].class # => Symbol
{ a: 10 }.keys[0].class # => Symbol
{ :"str" => 10 }.keys[0].class # => Symbol
No. (1) is standard symbol, (2) is shorthand 1.9 syntax for symbol-key hashes, (3) is shorthand for "str".to_sym, (4) does not exist and you should use the hashrocket.

Ruby - method parameters

My method:
def my_method=(attributes, some_option = true, another_option = true)
puts hello
end
When i try to call this, i get such error:
my_method=({:one => 'one', :two => 'two'}, 1, 1)
#you_code.rb:4: syntax error, unexpected ',', expecting ')'
#my_method=({:one => 'one', :two => 'two'}, 1, 1)
^
What's the problem?
Method with suffix punctuation = can have only one argument.
Otherwise, you must use send to invoke with multiple parameters.
send :'my_method=', {:a => 1}, 1, 1
Don't use parenthesis when invoking a method using the = syntactic sugar.
Invoke it like this:
mymethod= {:one => 'one', :two => 'two'}, 1, 1

Resources