Understanding Ruby (Sinatra) - very very basic - ruby

I was looking at Sinatra and trying to understand the syntax:
require 'sinatra'
get '/' do
"Hello, World!"
end
I understand it does this:
This is a ‘Route’. Here, we’re telling Sinatra that if the home, or root, URL '/' is requested, using the normal GET HTTP method, to display “Hello, World!”
But what is happening the Ruby language?
What does this syntax mean: get '/'? Is get a method and '/' a parameter to it? If it is method, then in Ruby, I can call a method as methodname (parameter) {}. What is { } there for?
I usually understand do and end as { }, which are kinds of enclosures to function bodies.
Between do and end we have "Hello, World!" so is it a statement? What I mean is, it is getting printed, but we did not call it as print "Hello, World!", so what is going on?
It seems get is a method defined in Sinatra, but if I add a gem, where there is a get method already defined, then how do I know which 'get' method it would call? Or, does it refer to the HTTP get method?
I am sorry if this question sounds very basic, but I want to get through it before I move forward.

May I suggest going through a tutorial on ruby before tackling a larger problem like sinatra which is a fairly specialized library.
A good place to start is with the Ruby Koans
As for your questions.
get is a method. '/' is its argument. and do ... end denotes a block in ruby just like {} would.
Yeah that's what do ... end are
Blocks in Ruby return the last value calculated by default so in the is case having a string is the same as having return "String".
If you are getting a namespace collision, Ruby will complain. In this case get is the sinatra defined method get. Abstractly it stands for an HTTP GET request against the server.

For the "perfect" response, I suggest you have a look at the book "Sinatra Up and Running" by
Alan Harris and Konstantin Haase.
http://shop.oreilly.com/product/0636920019664.do
Pages 6 and 7 explain how the line "get '/' do" is in fact a method call.
And you can view this 2 pages with Google Preview.

Related

How to Write mock of method using with to send params

Hi I want to know how can I write rspec for the following
def find_user(content)
user = User.find(content.to_i) ||
User.find(email: content) rescue
nil
end
I tried writing
It "user with user name" do
expect(User).to receive(:find).with(email: "test#a.com").and_return(user)
End
But I am gettig error saying
Argument Error
Block not Passed
Can someone please tell what am i missing
I may look first at your code here.
def find_user(content)
user = User.find(content.to_i) ||
User.find(email: content) rescue
nil
end
What is content? I looks like you're expecting either a user_id or an email address.
Doing this from the console:
irb(main):080:0> User.find("email#email.com".to_i)
=> ActiveRecord::RecordNotFound (Couldn't find User with 'id'=0)
So it seems as if having a generic find_user method may be contributing to some of the test writing confusion.
Many times, overly complex tests point to overly complex code.
Perhaps you need one method
find_user_by_email(email)
and another
find_user_by_id(id)
Also, refer to https://api.rubyonrails.org/v6.1.3.2/classes/ActiveRecord/FinderMethods.html#method-i-find_by
It will automatically return nil if nothing is found.
Start there, And then like the other commenters, then post your class, and the spec and we can go from there.

How to call a method on a local variable in Ruby?

Probably a stupid question but I was following along this article and came across a bit of code I couldn't quite grasp. Here it is:
class CreateArticle
attr_reader :validate_article, :persist_article
def initialize(validate_article, persist_article)
#validate_article = validate_article
#persist_article = persist_article
end
def call(params)
result = validate_article.call(params)
if result.success?
persist_article.call(params)
end
end
end
More specifically, the problematic line is this:
if result.success?
Here's my problem with it: where did the success? method come from? It's not default in Ruby, and result is a local variable, so it should be nearby. But even if it's just omitted in the code sample, where would it have to be defined for that line to work? Everywhere I tried to define it just gave me an 'undefined method' error.
For example, I tried to define it both in the CreateArticle class and in the (only alluded to) ValidateArticle class, the obvious culprits, but no dice.
Update:
The reason I ask is not so much about what success? does as it is because I'm interested in using the pattern in my code. So, for example, my version of the success? method could be just checking whether a value got updated, or an item was inserted into an array. For example, let's say it's just this:
def success? # or self.success?
return true
end
Problem is, I can find no place where I can put this that works. I even created a module just for it and included it into the class, and still it doesn't work (it just returns 'undefined method'). So I'm still at a loss as to where I would have to define such a method so that it would work the way it looks like it should.
It's a method that comes with rails. It checks.for a server response with a 200 code. If it gets a 200 code it returns true else it returns false. Read the rails API docs about it... https://apidock.com/rails/v3.2.3/ActiveResource/Response/success%3F
Actually . success? is a built in ruby method. Check here. What it actually does is checking Stat and returns a boolean.
I did some more digging around the blog and from what I found I suspect that the code is probably making use of the dry-monads gem:
You can explicitly check the type by calling failure? or success? on a monadic value.
It's not explicit in the code excerpt but it's the only thing that makes sense.

Unable to read cookie in Rspec 3 via last_response

I am trying to read in Rspec 3.1 a cookie received after get call.
I see it is returned but the last_response.cookies doesn't exist.
How can I read response's cookie?
it "doesn't signs in" do
get '/ui/pages/Home'
puts last_response.cookies
end
I know it has been a while, but facing exactly this same issue now, after some struggle, I've found an article here that shares an interesting approach. As I also couldn't find any native parsed method for this, that has worked fine for me.
Basically, place this piece of code below on your spec/spec_helper.rb:
def cookies_from_response(response=last_response)
Hash[response["Set-Cookie"].lines.map { |line|
cookie = Rack::Test::Cookie.new(line.chomp)
[cookie.name, cookie]
}]
end
and you could use this to see the parsed hash:
puts cookies_from_response
For a cookie's value check, you could then use something like:
# Given your cookie name is 'foo' and the content is 'bar'
expect(cookies['foo'].value).to eq 'bar'
Hopefully this becomes helpful to others facing similar issues.

Displaying url parameter in Ruby

I am building a VERY simple ruby test application, just to see how it works, but I'm already stuck in overly complex tutorials.
Say that my ruby app is running at heroku at : http://example.herokuapp.com
And that I am calling it like this: http://example.herokuapp.com/test=3 or perhaps http://example.herokuapp.com/page.rb?test=3 ?
How do I get the value from "test" in my ruby output?
My Heroku demo code:
require 'sinatra'
get '/' do
"The value of test is..."
end
In Sinatra the route patterns may consist of named parameters. These parameters can be accessed using the params hash.You need to do something like this:
get '/:test' do
"The value of test is...#{params[:test]}"
end
Url:
http://example.herokuapp.com/3

Disappearing variable in Ruby

I have a strange problem with the FastImage gem. When I try to access the variable directly or call methods on it, I get a nil error. Rails says that the variable doesn't exist, so something like FastImage.size(url)[0] won't work. However, if I use 'puts', i.e puts FastImage.size(url) the variable can be accessed.
In the console, everything is working fine. Any ideas?
images.each do |d|
puts FastImage.size(d["src"])[0] + FastImage.size(d["src"])[1]
results << d["src"]
end
Figured it out! What happens is that FastImage throws an error if there is a bad url, so one needs to check that the url is valid. What happened was that one of the urls was invalid, so it would throw an exception midway through the iteration.

Resources