How do I format this hash? - ruby-on-rails

I have a UUID with three unique properties for each UUID. I want to store all these. I know I need a hash inside a hash, but I am having trouble doing this.
It's creating them inside a loop, and for each iteration I need to append/add it to the hash, so I'm not sure how to do that either.
19ee480015a2012f0aeb64ce8f2f69f4:
status: complete
name: SaveComment
pct_complete: 100
083732301597012f0aea64ce8f2f69f4:
status: working
name: SaveComment
pct_complete: 35
bf40ca301596012f0ae864ce8f2f69f4:
status: complete
name: SaveComment
pct_complete: 100
This is the code it's going into:
get '/percentcomplete' do
progress = {}
Resque::Status.status_ids.each do |uuid|
active_status = Resque::Status.get(uuid)
#update hash each loop here with name, status, pct_complete, and uuid
end
end

Assuming we can get name, status, pct_complete from active_status object,
get '/percentcomplete' do
progress = {}
Resque::Status.status_ids.each do |uuid|
active_status = Resque::Status.get(uuid)
#update hash each loop here with name, status, pct_complete, and uuid
progress[uuid.to_s] = {:name => active_status.name,
:status => active_status.status,
:ptc_complete => active_status.ptc_complete}
end
end

Related

Why is my joins/where lookup failing when I pass a variable into it?

Models:
# committee.rb
has_and_belongs_to_many :chambers
# chamber.rb
has_and_belongs_to_many :committees
I'm trying to perform the following lookup (in a rake task, if that matters):
lookup = Committee.joins(:chambers)
.where(chambers: { id: chamber.id })
.where(name: clean_name)
.first
The problem I'm having is with clean_name at the end. When I manually put name: "Judiciary" there the lookup succeeds as-expected. However, when "Judiciary" is passed into clean_name the lookup returns nil. I have tried name: "#{clean_name}" as well, but to no avail.
Here's how clean_name gets generated:
# scheduler.rake
# "committee" is previously-defined via an API lookup
clean_name = Committee.gsub_name(committee)
# committee.rb
# I have to sanitize the API-returned name in order to make
it consistent with my own naming convention
def self.gsub_name(name)
return name.gsub("Committee on the ", "").gsub("Committee on ", "").gsub("'", "'").gsub("House ", "").gsub("Senate ", "").gsub("Committee", "")
end
I've confirmed that gsub_name returns the appropriate text before executing the lookup.
Here's the whole function in scheduler.rake:
def add_committee_for(bill, chamber)
params = [
:level => "#{chamber.government.level}",
:endpoint => "bill_committee",
:api_url => bill.api_url
]
# Retrieve original unsuanitized value from API:
committee = Bill.set_request(params)
clean_name = Committee.gsub_name(committee)
chamber_committees = chamber.committees
yn_committee = Committee
.joins(:chambers)
.where(chambers: { id: chamber.id })
.where(name: "#{clean_name.to_s}")
.first
end
As solved in the comments it turned out to be because of whitespace in the string. The solution is to use the String#strip method to get rid of that.
lookup = Committee.joins(:chambers)
.where(chambers: { id: chamber.id })
.where(name: clean_name.strip)
.first

Too many checks for empty params. How to optimize queries to ActiveRecord in Rails5?

I'm doing checks for empty parameters before do the query.
There is only 1 check for params[:car_model_id]. I can imagine if I will add more checks for other params, then there will be a mess of if-else statements. It doesn't look nice and I think it can be optimized. But how? Here is the code of controller:
class CarsController < ApplicationController
def search
if params[:car_model_id].empty?
#cars = Car.where(
used: ActiveRecord::Type::Boolean.new.cast(params[:used]),
year: params[:year_from]..params[:year_to],
price: params[:price_from]..params[:price_to],
condition: params[:condition]
)
else
#cars = Car.where(
used: ActiveRecord::Type::Boolean.new.cast(params[:used]),
car_model_id: params[:car_model_id],
year: params[:year_from]..params[:year_to],
price: params[:price_from]..params[:price_to],
condition: params[:condition]
)
end
if #cars
render json: #cars
else
render json: #cars.errors, status: :unprocessable_entity
end
end
end
The trick would be to remove the blank values, do a little bit of pre-processing (and possibly validation) of the data, and then pass the params to the where clause.
To help with the processing of the date ranges, you can create a method that checks both dates are provided and are converted to a range:
def convert_to_range(start_date, end_date)
if start_date && end_date
price_from = Date.parse(price_from)
price_to = Date.parse(price_to)
price_from..price_to
end
rescue ArgumentError => e
# If you're code reaches here then the user has invalid date and you
# need to work out how to handle this.
end
Then your controller action could look something like this:
# select only the params that are need
car_params = params.slice(:car_model_id, :used, :year_from, :year_to, :price_from, :price_to, :condition)
# do some processing of the data
year_from = car_params.delete(:year_from).presence
year_to = car_params.delete(:year_to).presence
car_params[:price] = convert_to_range(year_from, year_to)
price_from = car_params.delete(:price_from).presence
price_to = car_params.delete(:price_to).presence
car_params[:price] = convert_to_range(price_from, price_to)
# select only params that are present
car_params = car_params.select {|k, v| v.present? }
# search for the cars
#cars = Car.where(car_params)
Also, I'm pretty sure that the used value will automatically get cast to boolean for you when its provided to the where.
Also, #cars is an ActiveRecord::Relation which does not have an errors method. Perhaps you mean to give different results based on whether there are any cars returned?
E.g: #cars.any? (or #cars.load.any? if you don't want to execute two queries to fetch the cars and check if cars exist)
Edit:
As mentioned by mu is too short you can also clean up your code by chaining where conditions and scopes. Scopes help to move functionality out of the controller and into the model which increases re-usability of functionality.
E.g.
class Car > ActiveRecord::Base
scope :year_between, ->(from, to) { where(year: from..to) }
scope :price_between, ->(from, to) { where(price: from..to) }
scope :used, ->(value = true) { where(used: used) }
end
Then in your controller:
# initial condition is all cars
cars = Cars.all
# refine results with params provided by user
cars = cars.where(car_model_id: params[:car_model_id]) if params[:car_model_id].present?
cars = cars.year_between(params[:year_from], params[:year_to])
cars = cars.price_between(params[:price_from], params[:price_to])
cars = cars.used(params[:used])
cars = cars.where(condition: params[:condition]) if params[:condition].present?
#cars = cars

looping from database and no implicit conversion of Symbol into Integer

I encounter a strange problem when trying to alter values from a Hash. I have the following setup:
def index
data, total = Role.with_filtering(params, current_holding_company)
data.each do |total_user|
total_user = { total_user: RoleUser.where(role_id: data[:id]).group(:user_id).count.to_s }
data[:total_user] = total_user
end
respond_to do |format|
format.json { render json: { data: data, total_count: total }.to_json, status: 200 }
end
end
When I execute this code I get: "TypeError: no implicit conversion of Symbol into Integer" . What am I doing wrong?
data is output from database, so my goal is i want to add total_user in every record with add new key and value into data
This might not completely solves your issue but hopefully will guide you to the correct path.
In ruby the error TypeError: no implicit conversion of Symbol into Integer usually happens when you miss treat an array!
lets suppose you have
numbers = [1,2,3]
#now
numbers[0]
# > 1
numbers[2]
# > 3
#But
numbers[:1]
# throws TypeError: no implicit conversion of Symbol into Integer
So, you must be passing a symbol on an array [] operator by mistake
One way to debug this kind of issues is by checking class type of your objects, something like this in the consol
data.class
# > Array (for example)
try this....
def index
data, total = Role.with_filtering(params, current_holding_company)
data.each do |total_user|
total_user = { "total_user" => RoleUser.where(role_id: data[:id]).group(:user_id).count.to_s }
data[:total_user] = total_user
end
respond_to do |format|
format.json { render json: { data: data, total_count: total }.to_json, status: 200 }
end
end

Data from a JSON API combined with local database in Rails

I would like to combine data retrieved from an API with local database data in a new JSON. But I think I'm doing this wrong. Here is my code :
#data = ActiveSupport::JSON.decode(#api_data)
#data.each do |key|
if key['state'] == "active"
user_id = key['id']
user_database = User.where(:user_id => user_id).take
#userlist = []
unless user_database.blank?
user_data = {
:user_id => key['id'],
:enrolement_start_date => key['start_at'],
:enrolement_end_date => key['end_at'],
:user_interest => user_database.interests,
:user_discipline_id => user_database.discipline_id,
}
#userlist.push(user_data)
end
end
end
#userlist = #userlist.to_json
Actually, it's working but I only receive the last user as result. I don't figure how to make it works :-/ Many thanks in advance !
#userlist = []
that line, each time through the loop
#data.each do |key|
is clearing out the previous data by re-initializing #userlist. Then you're returning the user you added last, since all the others were thrown away the last time you assigned an empty array to #userlist.
Just move
#userlist = []
above
#data.each do |key|
and you should be good.

Providing a json response that references a local variable

I am trying to restructure a named-JSON response to return a model object (some attributes only), and some associated arrays stored in local variables, however I am unsure what I'm doing incorrectly. The local variables are definitely being assigned with values, however they're not being returned in the response.
This is the structure of what I want returned...
{ name: "Dan", email: "email#email.com", id: "1", open_gifts: [ { objects }, { here }] }
Setup
#person = Person.find_by_id(params[:id])
gifts_created_open = Gift.created_gifts_open(#person)
return_object = [#person.name, #person.email, #person.id, gifts_created_open]
Now this, returns a JSON object with the details, but its wrapped in an array, and I'm trying to return just a named object, with the associated array inside it.
render :json => return_object
And this returns a named object, but its missing the array. What gives??
render :json => #person.to_json(:gifts_created_open, :only => [:name, :email, :id] )
Many thanks with this. I've already spent several hours :/
Try:
return_object = {name:#person.name, email:#person.email, id:#person.id, gifts:gifts_created_open}.to_json

Resources