Sinatra and question mark - ruby

I need to make some methods with Sinatra that should look like:
http//:localhost:1234/add?string_to_add
But when I declare it like this:
get "/add?:string_to_add" do
...
end
it doesn't see the string_to_add param.
How should I declare my method and use this parameter to make things work?

In a URL, a question mark separates the path part from the query part. The query part normally consists of name/value pairs, and is often constructed by a web browser to match the data a user has entered into a form. For example a url might look like:
http://example.com/submit?name=John&age=93
Here the path section in /submit, and the query sections is name=John&age=93 which refers to the value “John” for the name key, and “93” for the age.
When you create a route in Sinatra, you only specify the path part. Sinatra then parses the query, and makes the data in it available in the params object. In this example you could do something like this:
get '/submit' do
name = params[:name]
age = params[:age]
# use name and age variables
...
end
If you use a ? character when defining a Sinatra route, it makes part of the url optional. In the example you used (get "/add?:string_to_add"), it will actually match any url starting with /ad, then optionally another d, and then anything else will be put in the :string_to_add key of the params hash, and the query section will be parsed separately. In other words the question mark makes the preceding d character optional.
If you want to get the ‘raw’ text of the query string in Sinatra, you can use the query_string method of the request object. In your example that would look something like this:
get '/add' do
string_to_add = request.query_string
...
end
Note that the route doesn’t include the ? character, just the base /add.

You should declare it as:
get "/add?:string_to_add?" do
...
end

Related

Laravel - How do I navigate to a url with a parameter to left of subdirectory

I have to test this Route, but I am not sure how to navigate to it.
Route::get('/{type}/Foo/{page}/{date}', 'FooController#index');
I understand that URLs usually have subdirectories defined before the parameters in the URL.
I have worked with URLs like this example
Route::get('/Foo/{type}', 'FooController#index');
which would have an endpoint that looks like
/Foo?type=bar
Does anybody know how to test a route such as the one above?
Well i think that you need to clear out a bit the difference between route and query parameters.
In your case you are trying to use route parameters which will actually look something like:
/{type}/Foo/{page}/{date} => /myType/Foo/15/12-11-2021
Laravel considers the words inside {} as variables that you can retrieve via request so you can do something like:
$request->type
and laravel will return you the string myType as output.
In your second case that you have tried in the past you are referring to query parameters which are also a part of the $request. Consider it as the "body" of a GET request but i don't mean in any way to convert your post routes to GET :)
The thing with your second url is that:
/Foo/{type} is not similar to /Foo?type=bar
instead it should be like: /Foo/bar
In general query parameters are when you want to send an optional field most of the times in your GET endpoint (for filtering, pagination etc etc) and the route parameters are for mandatory fields that lead to sub-directories for example /Foo/{FooId}/Bar/{BarId}
The thing to remember is that you must be careful about your routes because variables can conflict with other routes.
For example a route looking like this:
Route::get('/foo/{fooId}', [FooController::class, 'getFoo']);
Route::get('/foo/bar', [BarController::class, 'getBar']);
will conflict because laravel will consider bar as the variable of the fooId so your second route can never be accessed.
The solution to this is to order your routes properly like:
Route::get('/foo/bar', [BarController::class, 'getBar']);
Route::get('/foo/{fooId}', [FooController::class, 'getFoo']);
So when you give as a route parameter anything else than bar your will go to your second route and have it working as expected.

Remove a specific query parameter from URL

I have a URL such as:
http://www.example.com/something?abc=one&def=two&unwanted=three
I want to remove the URL parameter unwanted and keep the rest of the URL in tact and it should look like:
http://www.example.com/something?abc=one&def=two
This specific parameter can be anywhere in the URL with respect to other parameters.
The question looks very simple, but I tried many times but failed in the end.
The entire query string is present in the $args variable or at the end of the $request_uri variable. You will need to construct a regular expression to capture everything before and after the part you wish to delete.
For example:
if ($request_uri ~ ^(/something\?.*)\bunwanted=[^&]*&?(.*)$ )
{
return 301 $1$2;
}
See this document for more, and this caution on the use of if.

Wildcard route in Grape

I'm having issues getting Grape to respond to a purely wild card route.
By that I mean that if I have a simple route defined as
get do
...
end
I need to respond to all potential requests made to the API. The situation being I need to parse the path and params and then work through a decision tree based on those values.
I've tried a few variations on the route definition, such as:
get '/*' do
...
end
get '/(*)' do
...
end
But to no avail.
I know that there is some support for regular expressions and route anchoring in Grape, but I've had no luck figuring it out.
Thanks!
You were close with the guess at the syntax, you just need to name the matching param:
E.g.
get '*thing' do
{ :thing => params[:thing] }
end
Using the * will make the param capture the rest of the URI path, ignoring / separators. But otherwise it behaves just like any other param.
Note this will only pickup within the Rack mount point at best, so if you have
prefix 'api'
version 'v2'
then it will respond to paths like /api/v2/hkfhqk/fwggw/ewfewg
If you are using this for custom 404 or other catch-all routes, then you need to add it at the end, otherwise it will mask more specific routes.

No implicit conversion of Array into String?

I have a Sinatra application with the following GET method that takes the URL passed in:
get %r{/html/(.+)} do
url = params[:captures] # stores url => http://www.example.com
gethtml(url)
end
However, when gethtml(url) is called, it raises the error Sinatra no implicit conversion of Array into String.
gethtml accepts input such as http://example.com.
I know this is a data-type conversion issue and I tried calling to_s but it did not work.
Any help would be appreciated.
params[:captures] returns an array of strings, while get_html most likely accepts one URL as string.
Since you want to use the first group that matches as the URL:
get %r|/html/(.+)| do
get_html params[:captures].first
end
This is consistent with the Route matching with Regular Expressions example in the Routes section of the README.

Local variables in a block that are not passed as parameters [duplicate]

This question already has answers here:
Rails params explained?
(5 answers)
Closed 9 years ago.
I'm trying to understand how to make a variable available to a block that is not passed to the block as a parameter.
For example, how does Sinatra make params hash available?
get '/hello/:name' do
howAmIAccessingThis = params[:name]
end
Where is params coming from? This:
get '/hello/:name' do |params|
#hisName = params[:name]
end
might make sense because params is declared as a block argument, but that's not how it works. Looking through the source I cannot find how the params hash is getting passed to the block without it being a block parameter.
If it is not a local variable or a block variable, then it is a method. I don't know about Sinatra, but there must be a method params defined somewhere.
Using Parameters
Parameters in Sinatra are like everything else--simple and straightforward.
#!/usr/bin/env ruby
require 'rubygems'
require 'sinatra'
get '/hello/:name' do
"Hello #{params[:name]}!"
end
Once you've made this change, you'll need to restart the Sinatra application. Kill it with Ctrl-C and run it again. (There's a way around this, but we'll look at that in a future article.) Now, the parameters are straightforward. We've made an action called /hello/:name. This syntax is imitating what the URLs will look like, so go to http://localhost:4567/hello/Your Name to see it in action.
The /hello portion matches that portion of the URL from the request you made, and :name will absorb any other text you give it and put it in the params hash under the key :name. Parameters are just that easy. There is of course much more you can do with these, including regexp-based parameters, but this is all you'll need in almost every case.
Reference: http://ruby.about.com/od/sinatra/a/sinatra2.htm
EDIT
params values can come from the query string of a GET request, or the form data of a POST request, but there's also a third place they can come from: The path of the URL.
As you might know, Rails uses something called routes to direct requests to their corresponding controller actions. These routes may contain segments that are extracted from the URL and put into params. For example, if you have a route like this:
match 'products/:id', ...
Then a request to a URL like http://example.com/products/42 will set params[:id] to 42
So, whenever an URL GET, POST or Path contains such pattern then params hash is automatically constructed by rails.
Also check the Parameters section(Section 4) here

Resources