Rails API subsetting response - ruby-on-rails

I have a controller designed to perform simple CRUD operations. The model of my data has an attribute called start_date. What should I do in order to make my API return a JSON response with only the entries with a start_date value between two dates that I can specify in the body of the request?

This is more like a generic question about filtering that could be applied to any API request.
If you make a GET request for an endpoint like example.com/model you would have to pass some parameters, in that case, 2 dates in the URL. So it would be something like this:
example.com/model?start_date=12.12.2017&end_date=15.12.2017
This example is super simple of course. You can pass those dates in different ways like a timestamp or ISO format. that is up to you.
On the backend side, you have to fetch those parameters from the request and perform a query on your model. something like this:
def index
start_date = params[:start_date]
end_date = params[:end_date]
# Make sure to parse the params and transform in a date object
result = Model.where('start_date < ? AND start_date > ?', end_date, start_date)
respond_to do |format|
format.json { render json: result }
end
end

Related

Doing search by count in json with params results

I'm trying to implement a counter filter in my json. When I access the url api/v1/contacts?Results=2 [sic], I would like to get only two results from my json.
For this, I created two methods in my controller: an index that takes the information from the database and turns render into json, and a method that returns the number of times the json is returned.
class Api::V1::ContactsController < ApplicationController
before_action :results, only: [:index]
def index
#contacts = Contact.all
render json: {results: #contacts[0..#number_results]}
end
def results
if params[:results]
results = params[:results]["results"]
#number_results = results.to_i
else
#number_results = 3
end
end
end
Regardless of the value entered for results =, the value of #number_results is set to 0, so whenever I type results = I, get only the first result of json. If I do not type results = in the url, it sets #number_results to 3, and shows four results on the screen.
Can anyone help?
First, in the url you propose, "Results" is capitalized. If that is how you intend to submit it, then you'll need to search for it that way on the back end. But since all your code uses lowercase "results", we'll go with that. You should modify your url in the same way: api/v1/contacts?results=2.
If that's what your url looks like then the number you pass in is accessible in params[:results]. If you pass no parameter, then params[:results] will return nil. Don't call #to_i on the param before you check for its existence, because nil.to_i is 0.
All that said, here's what you probably want:
class Api::V1::ContactsController < ApplicationController
def index
number_results = params[:results] || 3
#contacts = Contact.all.limit(number_results.to_i)
render json: {results: #contacts}
end
end
If the result of params[:results] is nil, then number_results is assigned 3.
Now we use #limit to return only the number of contacts that was requested. This allows us to do away with the #results method entirely. You can also get rid of the before_action callback.

building a simple search form in Rails?

I'm trying to build a simple search form in Ruby on Rails, my form is simple enough basically you select fields from a series of options and then all the events matching the fields are shown. The problem comes when I leave any field blank.
Here is the code responsible for filtering the parameters
Event.joins(:eventdates).joins(:categories).where
("eventdates.start_date = ? AND city = ? AND categories.name = ?",
params[:event][:date], params[:event][:city], params[:event][:category]).all
From what I get it's that it looks for events with any empty field, but since all of them have them not empty, it wont match unless all 3 are filled, another problem arises when I try to say, look events inside a range or array of dates, I'm clueless on how to pass multiple days into the search.
I'm pretty new to making search forms in general, so I don't even know if this is the best approach, also I'm trying to keep the searches without the need of a secialized model.
Below is probably what you are looking for. (Note: If all fields all blank, it shows all data in the events table linkable with eventdates and categories.)
events = Event.joins(:eventdates).joins(:categories)
if params[:event]
# includes below where condition to query only if params[:event][:date] has a value
events = events.where("eventdates.start_date = ?", params[:event][:date]) if params[:event][:date].present?
# includes below where condition to query only if params[:event][:city] has a value
events = events.where("city = ?", params[:event][:city]) if params[:event][:city].present?
# includes below where condition to query only if params[:event][:city] has a value
events = events.where("categories.name = ?", params[:event][:category]) if params[:event][:category].present?
end
To search using multiple days:
# params[:event][:dates] is expected to be array of dates.
# Below query gets converted into an 'IN' operation in SQL, something like "where eventdates.start_date IN ['date1', 'date2']"
events = events.where("eventdates.start_date = ?", params[:event][:dates]) if params[:event][:dates].present?
It will be more easy and optimised . If you use concern for filter data.
Make one concern in Model.
filterable.rb
module Filterable
extend ActiveSupport::Concern
module ClassMethods
def filter(filtering_params)
results = self.where(nil)
filtering_params.each do |key, value|
if column_type(key) == :date || column_type(key) ==
:datetime
results = results.where("DATE(#{column(key)}) = ?",
Date.strptime(value, "%m/%d/%Y")) if
value.present?
else
results = results.where("#{column(key)} Like ? ", "%#{value}%") if
value.present?
end
end
results
end
def resource_name
self.table_name
end
def column(key)
return key if key.split(".").count > 1
return "#{resource_name}.#{key}"
end
def column_type(key)
self.columns_hash[key].type
end
end
end
Include this concern in model file that you want to filter.
Model.rb
include Filterable
In your controller Add this methods
def search
#resources = Model.filter(class_search_params)
render 'index'
end
def class_search_params
params.slice(:id,:name) #Your field names
end
So, It is global solution. You dont need to use query for filter. just add this concern in your model file.
That's it.

instance variable is null in show method rails

I have developed a rest api, in which I am using instance variable. there are two methods index and show, I have created a instance variable in index method which I want to use in show method on user request.
But i do not know, the instance variable is null in show method, I am sure that I am not initaializing the class anywhere explicitly. Code snippet is below
def index
data = Hash.new
#temp = DataHelper.filter(params)
if(params[:type] == 'Student')
json = DataStudenteHelper.sfilter(params, #temp)
else
json = EmpDataHelper.empfilter(params, #temp)
end
puts data.to_json
render :status => :ok, :json => json
end
def show
puts #temp.to_json // null here
if (params[:type] == 'Student')
#h = StudentHelpHelper.shfilter(params, #temp)
else
#h = EmpDataHelpHelper.emphfilter(params, #temp)
end
render :status => :ok, :json => #h
end
in the methods sfilter, empfilter, shfilter and emphfilter, I am just processing #temp but it is null in show method...
So any idea what is the issue thanks...
You seem to be assuming that a controller will persist across multiple requests so that you can initialize a variable in an index action and still be able to use it in a subsequent show action. This is not the case. Rails controller instances exist only for the duration of the request they serve. You cannot keep values in memory like this across requests (nor should you want to as that would require that requests be served in a particular order and would leak data between different users).
If you need to initialize this variable before all of your controller actions consider using a before filter. In your case this probably means that you also need to supply the data you need in the params of the show action.

how to filter display based on date in Rails (easy)

def home
#guide = Guide.all
#finished = Guide.where(:date_starting <= Time.now)
end
Why doesn't this work? In my controller I want to compare the the start date of the objects in my database with the Time now, so that Exhibitions that are no longer on display are in the '#finished' variable. I get the error 'comparison of Symbol with Time failed'.
Thanks
Because the where() method does not do comparisons like you show here.
Your query could be written like so:
Guide.where('date_starting <= ?', Time.now)
or
Guide.where('date_starting <= :now', {now: Time.now})

Sending a query string to rails respond_to

I am rather new to ruby and rails development.
for the past little while, I have been trying to figure out how I can pass params/query string to a rails respond_to block. I am focusing on the json response.
Say I have the following
def index
#employees = Employee.all
respond_to do |format|
format.html
format.json { render json: #employees }
end
end
and I am looking to only get a json response containing employees who have an id that is greater than 500. What would be the best way to go about this.
I have been trying to make the json request using jQuery.ajax() and I know you can pass data to the server that is formatted to a query, but not sure how to make it work.
The above example is only hypothetical. I am only looking for a way to be able to use a query sting when wanting a json response.
Thanks for the help!
Whatever parameters are sent with the request (in the query string) should be available in your controller (check the params variable). Here's one way to get the Employees with id's at & above 500:
Replace
#employees = Employee.all
with
#employees = Employee.find(:all, conditions: ["id >= ?", 500])
Please note that you don't need to pass anything besides the format to that respond_to block.

Resources