Please explain this ruby code (in rails) - ruby-on-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 ^

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.

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.

Related

Ruby on Rails console, beginner error

In rails console when I want to add a column to my table with below command
2.1.1 :001 >post = Post.new( :title => "first post", :job => "first job”)
it gives me
2.1.1 :002">
2.1.1 :003">
2.1.1 :004">
and doing nothing! I don't know what is problem here?
You didn't close quotes.
"first job”
Note that ” are not the same as " Console is waiting for you to close all the brackets and quotes before it executes the command.
if you copied and pasted the code the problem is with the last double-quotes
'”'.ord #=> 8221
'"'.ord #=> 34
'”' == '"' #=> false

Ruby default values error

I was reading the source code of a gem "activerecord-postgres-earthdistance".
While running the migration script, it threw an error on the following method
def order_by_distance lat, lng, order: "ASC"
It gave an error for order: "ASC"
syntax error, unexpected tLABEL
Isn't this valid Ruby syntax?
Ruby 2.0 supports keywords arguments
[5] pry(main)> def bar(a: "name", b: "fem"); puts a,b end
[6] pry(main)> bar(a: "John", b: "Male")
John
Male
[7] pry(main)> bar("John", "Male")
ArgumentError: wrong number of arguments (2 for 0)
from (pry):5:in `bar'
However the above is not valid in 1.9 see below:
ruby 1.9.3p448 (2013-06-27 revision 41675) [x86_64-darwin12.4.0]
[2] pry(main)> def bar(a: "name", b: "fem"); puts a,b end
SyntaxError: unexpected ',', expecting $end
def bar(a: "name", b: "fem"); puts a,b end
^
[2] pry(main)> def bar(a: "name"); puts a end
SyntaxError: unexpected ')', expecting $end
def bar(a: "name"); puts a end
^
For better understanding you can read here and here
def order_by_distance(lat, lng, hash={})
puts hash[:order]
end
=> order_by_distance(lat, lng, order: "ASC")
=> "ASC"
use hash arguments in ruby

Why does the JSON returned from my Sinatra App give a syntax error?

I'm developing a Sinatra app, which returns JSON, e.g.
get '/clients' do
# do stuff
response = {
"success" => "true",
"msg" => "Clients successfully retrieved",
"data" => {"clients" => #current_user.clients}
}
return response.to_json
end
The returned JSON looks something like this:
{"success":"true","msg":"Clients successfully retrieved","data":{"clients":[{"client":{"created_at":"2013-03-31T22:50:18Z","email":"test#test.com","first_name":"Marge","gender":"F","hairdresser_id":2,"id":1,"surname":"Simpson","updated_at":"2013-03-31T22:50:18Z"}}]}}
When I copy and paste it into a JSON parser, it works fine.
http://json.parser.online.fr/
But when I fire up irb and try to use it, I get a bunch of errors:
1.9.3-p286 :001 > a = {"success":"true","msg":"Clients successfully retrieved","data":{"clients":[{"client":{"created_at":"2013-03-31T22:50:18Z","email":"test#test.com","first_name":"Marge","gender":"F","hairdresser_id":2,"id":1,"surname":"Simpson","updated_at":"2013-03-31T22:50:18Z"}}]}}
SyntaxError: (irb):1: syntax error, unexpected ':', expecting tASSOC
a = {"success":"true","msg":"Clients success...
^
(irb):1: syntax error, unexpected ',', expecting $end
a = {"success":"true","msg":"Clients successfully r...
^
from /home/[me]/.rvm/rubies/ruby-1.9.3-p286/bin/irb:13:in `<main>'
1.9.3-p286 :002 >
Anyone able to offer any insight? Am I doing something wrong?
Thanks alot
Problem
JSON doesn't constitute a valid Ruby hash. It's a String that you need to parse with JSON#parse.
Solution
Parse JSON as a String by enclosing it in single quotes or a Ruby quote literal. For example:
JSON.parse %q/{"success":"true","msg":"Clients successfully retrieved","data":{"clients":[{"client":{"created_at":"2013-03-31T22:50:18Z","email":"test#test.com","first_name":"Marge","gender":"F","hairdresser_id":2,"id":1,"surname":"Simpson","updated_at":"2013-03-31T22:50:18Z"}}]}}/
=> {"success"=>"true",
"msg"=>"Clients successfully retrieved",
"data"=>
{"clients"=>
[{"client"=>
{"created_at"=>"2013-03-31T22:50:18Z",
"email"=>"test#test.com",
"first_name"=>"Marge",
"gender"=>"F",
"hairdresser_id"=>2,
"id"=>1,
"surname"=>"Simpson",
"updated_at"=>"2013-03-31T22:50:18Z"}}]}}
Your hash has key value pair denoted as { key : value } but ruby uses '=>' symbol to map key to a value.
Try replacing ':' to '=>' and it works fine.
eg) a = {"success" => "true"}
If you want to parse this Json to ruby has then use this snippet:
require 'json'
value = "{\"val\":\"test\",\"val1\":\"test1\",\"val2\":\"test2\"}"
puts JSON.parse(value) # => {"val"=>"test","val1"=>"test1","val2"=>"test2"}

Simple regex check failing in a rails model

I have a check of the following type
validates :callback_handle, :format => { :with => /[_0-9a-zA-Z]+/ix }, :unless => "callback.nil?"
I do not want any non 0-9, a-z A-Z characters to pass. So i set callback_handle to
"!alksjda" (note ! at the begining).
This test does not fail. What am I doing wrong?
I tried a few things on irb: This is what I got:
1.9.2-p320 :001 > a = "!askldjlad"
=> "!askldjlad"
1.9.2-p320 :002 > a =~ /[_0-9a-zA-Z]+/ix
=> 1
1.9.2-p320 :003 > a = "askldjlad"
=> "askldjlad"
1.9.2-p320 :004 > a =~ /[_0-9a-zA-Z]+/ix
=> 0
I thought it would return false or nil on failure to find the match.
Can someone tell me what is wrong here in my understanding?
EDIT:
I figured out that =~ will return position of a match.
So the question becomes How do I not allow something that has any other character to not match?
Your regular expression is still able to match, because there is at least 1 character in your string that is alpha-numeric. If you want to make sure that the entire string matches then you should define the beginning and end of the match.
Old:
a =~ /[_0-9a-zA-Z]+/ix
This is saying "match at least one of these characters somewhere in a.
New:
a =~ /\A[_0-9a-zA-Z]+\z/ix
This is saying "start at the beginning of the string, then match at least 1 of only these characters, followed by the end of the string" in a.
Your regex just asks that your string contains 1 or more valid characters ... this should fix it :
validates :callback_handle, :format => { :with => /^[_0-9a-zA-Z]+$/ix }, :unless => "callback.nil?"

Rails / Ruby not following Rublar on regular expression

I have the following expression that I have tested in Rubular and that successfully matches against a snippet of HTML:
Official Website<\/h3>\s*<p><a href="([^"]*)"
However, when I run the expression in Ruby, using the following code, it returns no matches. I've reduced it down to "Official\s*Website" and it matches that, but nothing further.
Are there any additional options I need to set, or anything else that I need to do to configure Ruby/Rails to start tracking Rubular?
matches = sidebar.match(/Official\s*Website<\/h3>\s*<p><a href="([^"]*)"/)
if matches.nil?
puts "no matches"
else
puts "matches"
end
This is the relevant part of the snippet I'm matching against:
<h3>Official Website</h3><p>website.com</p>
your regular expression is correct. rubular should be working the same way your code does.
i tested it against ruby 1.8.7 and 1.9.3
irb(main):006:0> sidebar = ' <h3>Official Website</h3><p>website.com</p>'
=> " <h3>Official Website</h3><p>website.com</p>"
irb(main):007:0> sidebar.match(/Official\s*Website<\/h3>\s*<p><a href="([^"]*)"/)
=> #<MatchData "Official Website</h3><p><a href=\"http://website.com\"" 1:"http://website.com">
-
1.9.3p0 :005 > sidebar = ' <h3>Official Website</h3><p>website.com</p>'
=> " <h3>Official Website</h3><p>website.com</p>"
1.9.3p0 :006 > sidebar.match(/Official\s*Website<\/h3>\s*<p><a href="([^"]*)"/)
=> #<MatchData "Official Website</h3><p><a href=\"http://website.com\"" 1:"http://website.com">
if you want to quickly check why stuff is not working, you should try it in IRB or in your rails console. most of the times it's typo or bad encoding.

Resources