instance variable is null in show method rails - ruby-on-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.

Related

Problem with selecting elements with the same params

What i do wrong? I want to return every products which pass condition:
def show
products = Product.select{|x| x[:category_id] == params[:id]}
render json: products
end
When i write
def show
products = Product.select{|x| x[:category_id] == 1}
render json: products
end
it works why the first example doesn't work?
I am pretty sure that there is mismatch in data type.
1=='1' #will be always false
1==1 #will be true
'1'=='1' #will be true as well
And also check for nil value from params[:id]
Please make sure to change as follows
def show
products = Product.select{|x| x.category_id == params[:id].to_i}
render json: products
end
OR
The best solution as suggested by #Eyeslandic is to use .where as it will not check for mismatch in data type. And also you don't have to take care of nil value from params[:id].
You should really be using a where to stop sql from loading all your products.
#products = Product.where('category_is = ?', params[:id])
The being said, if you are sticking to rails restful conventions, the fact you have a param called :id that is the category_id suggests you are on the category controller. So maybe consider changing your logic to:
#category = Category.includes(:products).find(params[:id])
you can then access products via
#category.products
or if your not interested in the category too much maybe
#products = Category.includes(:products).find(params[:id])&.products

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.

How to get an array of objects after several ajax calls

In a project, I implement checkbox filters via ajax. In my controller I have an action:
def casinos_filters
providers_from_categories = Provider.joins(:categories).where('categories.id = ?', params[:category_id])
providers = Casino.joins(:providers).where('providers.id = ?', params[:provider_id])
providers_from_categories.each do |provider|
#filtered_casinos = provider.casinos
end
casinos_list = []
casinos_list << #filtered_casinos if params[:category_id]
casinos_list << providers if params[:provider_id]
render json: { casinos: casinos_list.uniq }, status: 200
end
As a result, I want the array casinos_list include the casinos' objects. Clicking on a category checkbox, I get the json. But when I click the next category checkbox, the json doesn't have previous results. I think it's due to the initializing an empty array in the action. Is there any way to initialize the array only once, not on every ajax call? Thanks.
HTTP requests are stateless. You either need to store them in client side (as Javascript models/collections) or on the server side to be able to collect them together.

what var type to dynamically access Model's attribute from another controller? (Rails 4.2)

Goal: dynamically update another Model's properties (Tracker) from Controller (cards_controller.rb), when cards_controller is running the def update action.
Error I receive : NameError in CardsController#update, and it calls out the 2nd last line in the
def update_tracker(card_attribute) :
updated_array = #tracker.instance_variable_get("#{string_tracker_column}")[Time.zone.now, #card.(eval(card_attribute.to_s))]
Perceived problem: I have everything working except that I don't know the appropriate way to 'call' the attribute of Tracker correctly, when using dynamic attributes.
The attribute of the Tracker is an array (using PG as db works fine), I want to
figure out what property has been changed (works)
read the corresponding property array from Tracker's model, and make a local var from it. (works I think, )
push() a new array to the local var. This new array contains the datetime (of now) and, a string (with the value of the updated string of the Card) (works)
updated the Tracker with the correct attribute.
With the following code from the cards_controller.rb
it's the if #card.deck.tracked in the update method that makes the process start
cards_controller.rb
...
def update
#card = Card.find(params[:id])
if #card.deck.tracked
detect_changes
end
if #card.update_attributes(card_params)
if #card.deck.tracked
prop_changed?
end
flash[:success] = "Card info updated."
respond_to do |format|
format.html { render 'show' }
end
else
render 'edit'
end
end
...
private
def detect_changes
#changed = []
#changed << :front if #card.front != params[:card][:front]
#changed << :hint if #card.hint != params[:card][:hint]
#changed << :back if #card.back != params[:card][:back]
end
def prop_changed?
#changed.each do |check|
#changed.include? check
puts "Following property has been changed : #{check}"
update_tracker(check)
end
end
def update_tracker(card_attribute)
tracker_attribute = case card_attribute
when :front; :front_changed
when :back; :back_changed
when :hint; :hint_changed
end
string_tracker_column = tracker_attribute.to_s
#tracker ||= Tracker.find_by(card_id: #card.id)
updated_array = #tracker.instance_variable_get("#{string_tracker_column}")[Time.zone.now, #card.(eval(card_attribute.to_s))]
#tracker.update_attribute(tracker_attribute, updated_array)
end
Edit: For clarity here's the app/models/tracker.rb:
class Tracker < ActiveRecord::Base
belongs_to :card
end
Your use of instance_variable_get has been corrected, however this approach is destined to fail because ActiveRecord column values aren't stored as individual instance variables.
You can use
#tracker[string_column_changed]
#card[card_attribute]
To retrieve attribute values by name. If you want to get an association, use public_send. The latter is also useful if there is some accessor wrapping the column value (eg carrierwave)
From your error it seem your issue is this:
#tracker.instance_variable_get("#{string_tracker_column}")
evaluates to this after string interpolation:
#tracker.instance_variable_get("front_changed")
which is incorrect use of instance_variable_get. It needs an # prepended:
#tracker.instance_variable_get("#front_changed")
Seems like using instance_variable_get is unnecessary, though, if you set attr_reader :front_changed on the Tracker model.

Running GET Request Through Rails on separate thread

I have a get request that retrieves JSON needed for graphs to display on a page. I'd do it in JQuery, but because of the API that I am using, it is not possible -- so I have to do it in rails.
I'm wondering this: If I run the get request on a separate thread in the page's action, can the variable then be passed to javascript after the page loads? I'm not sure how threading works in rails.
Would something like this work:
Thread.new do
url = URI.parse("http://api.steampowered.com/IDOTAMatch_570/GetMatchHistory/v001/?key=#{ENV['STEAM_WEB_API_KEY']}&account_id=#{id}&matches_requested=25&game_mode=1234516&format=json")
res = Net::HTTP::get(url)
matchlist = JSON.parse(res)
matches = []
if matchlist['result'] == 1 then
matchlist['result']['matches'].each do |match|
matches.push(GetMatchWin(match['match_id']))
end
end
def GetMatchWin(match_id, id)
match_data = matchlist["result"]["matches"].select {|m| m["match_id"] == match_id}
end
end
end
Given that the above code is in a helper file, and it then gets called in the action for the controller as such:
def index
if not session.key?(:current_user) then
redirect_to root_path
else
gon.winlossdata = GetMatchHistoryRawData(session[:current_user][:uid32])
end
end
The "gon" part is just a gem to pass data to javascript.

Resources