Rails3 api to retrieve items based on its params using grape - ruby

i m working in rails 3
i have a doubt , i have a method to fetch the items based on its tag
like
resources "blogs" do
get '/tag', '/tag/:name' do
authenticate!
tag_name = params[:name].to_s || ""
# query to fetch from items based on its tag associated
end
end
The above one works, now i would like to change the url like
"apipath/blogs?tag=tag1"
instead of what i did before as "apipath/blogs/tag/tag1"
so i have modified the line
get '/tag', '/tag/:name' do
###
end
with
get '?tag', '?tag=:name' do
end
but this not working ...
Please suggest .

To me this can works :
resources "blogs" do
get '/tag' do
authenticate!
tag_name = params[:tag].to_s || ""
# query to fetch from items based on its tag associated
end
end
You don't need define in your route the params pass by ? this is not interpret by router.

You can add conditionals in the route with parenthesis:
get '/tag(/:name)' do
# params[:name] will contain the tag name
end

Related

Is there a way to use different mime type in my sinatra app

I am creating my Api in Sinatra but i want for example use this routes:
/places
/places.meta
/places.list
/users/id/places.list
i have this working in rails but fails in sinatra
def index
case request.format.to_sym.to_s
when 'list'
result = Place.single_list(parameters)
when 'meta'
result = #parameters.to_meta
else
result = Place.get_all(parameters)
end
render json: result, status: 200
end
Sinatra doesn't have a built-in concept of a "request format", so you have to manually specify a format-aware route pattern which Rails provide you automatically.
Here I use route pattern specified as a Regexp with a named capture:
require 'sinatra'
get /\/places(\.(?<format>meta|list))?/ do # named capture 'format'
case params['format'] # params populated with named captures from the route pattern
when 'list'
result = Place.single_list(parameters)
when 'meta'
result = #parameters.to_meta
else
result = Place.get_all(parameters)
end
result.to_json # replace with your favourite way of building a Sinatra response
end

Refresh url if url parameter changes in rails

I have a url in this format.
/companies/:name?id=company_id
So for example the ABC company, assuming the id is 1,has as url
/companies/ABC?id=1
If someone changes the id parameter value, the company with the new id is correcty loaded and its view is shown but the url keeps showing the previous company name.
For example, having a second company DEF with id 2
/companies/ABC?id=2
Instead of
/companies/DEF?id=2
Is there a way to check that id change and reload the url with the correct company name?
Thank you guys.
The only way to ensure that the :name matches the :id is to compare them, and redirect if the value doesn't match what expected.
For example, you can add a before_action in your controller, or enhance the one where you load the company
before_action :find_company
def find_company
#company = Company.find(params[:id])
# check and redirect
if #company.name != params[:name]
redirect_to(company_path(...))
end
end
Of course, the comparison has to be adjusted depending on how you generate the value for the :name parameter.
Personally, I dislike the approach of having the id as query. I would probably prefer something like:
/companies/:id
and take advantage of the fact that any string with the format \d+-\w+ is translated into an integer in Ruby:
"12-company-name".to_i
=> 12
You can then have URLs like:
/companies/12-company-name
And simply use
Company.find(params[:id].to_i)
Of course, you will still need the before action if you want to redirect in case of name not matching the ID.
before_action :find_company
def find_company
id, name = params[:id].to_s.split("-", 2)
#company = Company.find(id)
# check and redirect
if #company.name != name
redirect_to(company_path(...))
end
end

How to make dynamic template in ror...

I am new to ROR.I am working on spree gem extension. I want to make email template dynamic means the content of html.erb file should store in database table .On shooting mail, all data and dynamic data are managed..?? Is it possible in ror and how to achieve this.??
Yes you can do like this just replace dynamic variables in DB like this:
You have successfully placed Service Request No. {service_requests_id} for {service_requests_category} . Our representative will be in touch with you soon for the same. Thank you." This string is store in database.
and create a helper
def replace_dynamic_variables(str,variables=nil)
variables.each do |k ,v|
str = str.gsub('{' + k.to_s + '}',v || "")
end
return str.html_safe
end
and on mailer prepare variables like:
class yourMailer < ApplicationMailer
def send_service_email(args) # email sending method
#variables = {}
# Other code like subject, to, from etc.
#db_string = #string you get form DB
#variables[:service_requests_id] = #service_requests.id
#variables[:service_requests_category] = #service_requests.category.name
#mail to:
end
end
and in send_service_email.html.erb/ send_service_email.txt.erb whatever suite in your case just call
<%= replace_dynamic_variables(#db_string,#variables)%>
I have not tested but hope this will work for you

Select a record based on translated name

on ruby console when I do Resource.all it give me the following:
[<Resource id:'...', name_translated:{"en"=>'vehicle',"fr"=>'véhicule'}> ...]
How do I make a selection such that Resource.find_by_name_translated("vehicle")
This would work, I think it's not the most efficient way though:
#app/models/resource.rb
def self.find_by_english_name(name)
Resource.all.select do |resource|
resource.name_translated['en'] == name
end
end
if you want to be able to find by multiple languages (defaulting to english) with one method, try this:
def self.find_by_name(name, language = 'en')
Resource.all.select do |resource|
resource.name_translated[language] == name
end
end
Since you're using Postgres this can also be written as follows:
def self.find_by_name(name, language = 'en')
Resource.where("name_translated ->> '#{language}' = '#{name}'")
end
I'd use regex query if your db doesn't allow to query by json fields:
Resource.where("name_translated LIKE '#{translated_name}%'")

Sinatra URL Matching with question mark?

Is there a way to match urls with Sinatra using question mark?
get '/:id?inspect' do
# ...
end
get '/:id?last' do
# ...
end
get '/:id' do
# ...
end
I tried escaping the question mark \?, regex etc, but none of those worked.
I don't want to retrieve the value of inspect or last. I only want to know if they were supplied in the url.
Is that possible?
You can’t directly do what you want. When describing the route, Sinatra treats ? as defining an optional parameter, and doesn’t provide a way to escape it.
In a url a ? separates the path from the query string, and Sinatra only uses the path when matching routes. The contents of the query string are parsed and available in params, and the raw string is available as request.query_string.
Your url scheme seems rather unusual, but one possibility if you want to avoid checking the query_string in the actual route could be to create a custom condition to apply to the routes, and check in there:
set(:query) { |val| condition { request.query_string == val } }
get '/:id', :query => 'inspect' do
# ...
end
get '/:id', :query => 'last' do
# ...
end
get '/:id' do
# ...
end
A standard route is not defined by query parameters and should not be. Why don't you use a if construct on the params in the get /:id route?
I also suggest that when you want to set a query parameter in the request you set it like this: /:id?inspect=true (provide a dummy value)

Resources