Praveen Prasad
Praveen Prasad

Reputation: 1993

Please explain this ruby code (in rails)

Basically question is about ruby syntax

class Person < ActiveRecord::Base
      validates :name, presence: true #no error
end

Code Source

My 2 Questions

1

To me this code validates :name, presence: true looks a like call to a method.

How can we call a method inside class body, outside any method? I think its not possible in oops.

2

Why I am getting error in these two variations

validates (:name ,  presence: true) #error

or

validates (:name ,  {presence: true}) #error

I have added parentheses to method call, as its allowed in ruby. First parameter is symbol and 2nd parameter is hash.

In first case I have not added curly braces to hash, as I read that if last parameter is hash you can leave curly braces, In second code I have explicitly added curly braces but still got error.

Can anyone explain this syntax.

Thanks

Edit 1

Errors

In first I am getting

product.rb:8: syntax error, unexpected ',', expecting ')' validates (:name , presence: true) # error ^

In Second I am getting

product.rb:10: syntax error, unexpected ',', expecting ')' validates (:title , {presence: true}) # error ^

Upvotes: 0

Views: 96

Answers (2)

sugaryourcoffee
sugaryourcoffee

Reputation: 879

The answer to your first question: "Yes it is a method" and this is also somehow the answer to your second question.

The answer to your second question is "remove the space between validates and (". When having validates (...) it will throw

syntax error, unexpected ',', expecting ')' (SyntaxError)
  validates (:name ,  presence: true)

validates is a method, and if using parentheses you mustn't use spaces.

Upvotes: 2

harald
harald

Reputation: 6126

1: In ruby you can call a method when defining a class:

% irb
2.2.2 :001 > class Dummy
2.2.2 :002?>   puts "Making a class..."
2.2.2 :003?>   def hello
2.2.2 :004?>     puts "Hello"
2.2.2 :005?>   end
2.2.2 :006?> end
Making a class...
 => :hello 
2.2.2 :007 > d = Dummy.new
 => #<Dummy:0x000000009ebbf0> 
2.2.2 :008 > d.hello
Hello
 => nil 

So that's exactly what's going on.

2: You get an error because you have a space between the method name and the argument list:

% irb
2.2.3 :001 > def func(*splat)
2.2.3 :002?>   puts splat.inspect
2.2.3 :003?> end
 => :func 
2.2.3 :004 > func(:test, :another => :test)
[:test, {:another=>:test}]
 => nil 
2.2.3 :005 > func (:test)
[:test]
 => nil 
2.2.3 :006 > func (:test, :another => :test)
SyntaxError: (irb):6: syntax error, unexpected ',', expecting ')'
func (:test, :another => :test)
            ^
        from /home/haraldei/.rvm/rubies/ruby-2.2.3/bin/irb:11:in `<main>'

The second example above, where I'm passing just one arg works because you can enclose any valid expression in parenthesis. This is not the same as an argument list. So the expression:

(:test, :another => :test)

is not a valid expression, but the parser tries to pass it as one parenthesized argument to the method.

So to summarize, both your argument lists are correct, if you remove the space between them and the function name.

Upvotes: 3

Related Questions