Rails: combining multiple find requests - ruby-on-rails

What I want to do is something like this:
searchid = 4
while searchid != -1
#a += A.find(searchid)
#b = B.find(searchid)
searchid = #b.parentid
end
The problem being the line
#a += A.find(searchid)
The error being something like
NoMethodError: undefined method `+' for #<A:0x173f9a0>
So, how do you combine multiple 'find' requests?

You have to initialize #a = [] as an array before the += .
searchid = 4
#a = []
while searchid != -1
#a += A.find(searchid)
#b = B.find(searchid)
searchid = #b.parentid
end
You can combine them like:
searchid = 4
#a = []
while searchid != -1
#a += A.find(searchid)
#a += B.find(searchid)
searchid = #a.last.parentid
end

Got it to work (with help).
Did the following:
#a = []
with
#a << A.find_by_something(something)
seems to have worked.
Also using #a.compact! to get rid of the null entries.
Thanks for all the help :)

Related

How delete \r\n in Ruby?

error: undefined method `delete' for nil:NilClass
"updated_at" => "",
"fias_ao_guid" => "\r\n",
"file_path" => nil
how delete "\r\n"?
splitted_records = []
id = 3141634
string = 0
row = 0
h = {}
record_candidate = {}
open('/home/dayanov-sa/PGadmin/finish.csv') do |csv|
csv.each_line do |line|
index = 0
row += 1
line.split(";").each do |key_filed|
record_candidate["#{key_filed.delete("\r\n")}"] = nil
end if row.eql?(1)
next if row.eql?(1)
copy_object = Marshal.load(Marshal.dump(line))
values = line.split(";")
record_candidate.keys.each do |keys|
index += 1
record_candidate[keys] = values[index].delete("\r\n")
end
id = id + 1
puts string
splitted_records << record_candidate
I'm trying to remove from the hash \ r \ n
This is because of some hash keys have nil values e.g. ("file_path" => nil)
You need to bypass the nil values
Your code will be like this:
record_candidate.keys.each do |keys|
index += 1
if !values[index].nil?
record_candidate[keys] = values[index].delete("\r\n")
end
end
Your code looks like an attempt to parse CSV with a header. Ruby already has that in stdlib:
require 'csv'
file_contents = File.read('/home/dayanov-sa/PGadmin/finish.csv')
data = CSV.parse(file_contents, headers: true, col_sep: ';')
splitted_records = data.map(&:to_h)
see ruby documentation on CSV

doing away with loop result in rails

I am working on a kind of order where I have multiple amount in different currencies in just one attribute. So am trying to make sum on different currencies inside that attribute using other attributes in the table, which works fine but outputs the result as a count of all the rows instead of just showing the sum of the random values calculated.
orders_controller.rb
module Admin
module Statistic
class OrdersController < BaseController
def show
#orders_grid = ::Statistic::OrdersGrid.new(params[:statistic_orders_grid]) do |value|
value.page(params[:page]).per(20)
end
#assets = #orders_grid.assets
##fee_groups = {:fee => #assets.sum(:fee)}
#fee_groups = {
:fee => #assets.sum{|t|
olaoa = t.type
market_string = t.currency
base_currency = market_string.slice(0..2)
quote_currency = market_string.slice(3..5)
if olaoa == 'OrderBid' and base_currency == 'btc'
"#{ t.fee.to_s + ' ' + base_currency.upcase }"
elsif olaoa == 'OrderAsk' and quote_currency == 'ngn'
"#{ t.fee.to_s + ' ' + quote_currency.upcase }"
end
}
}
#orders_filter = true
#orders_group = true
end
end
end
end
summary.htm.slim
.panel.panel-default
.panel-heading
h4.panel-title.row
a data-parent="#filter-accordion" data-toggle="collapse" href="#summary"
span.col-xs-8.text-muted = t('admin.statistic.summary')
span.col-xs-4.text-right.text-muted = t('admin.statistic.click-to-expand')
#summary.panel-collapse.collapse
.panel-body
.datagrid-groups
- if !#orders_group
- if groups
- groups.each do |key, val|
.datagrid.group.row
span.col-xs-2.title = t("admin.statistic.#{controller_name}.#{controller.action_name}.#{key}")
span.col-xs-10.value = val
- if #orders_group
/ Summary Count Loop
- if groups
- groups.each do |key, val|
.datagrid.group.row
span.col-xs-2.title = t("admin.statistic.#{controller_name}.#{controller.action_name}.#{key}")
span.col-xs-10.value = pluralize(val, 'Order')
/ Summary Fees Loop. This is the Fee loop causing problem if am rigth and I dont know how to fix this.
- if #fee_groups
- #fee_groups.each do |key, val|
.datagrid.group.row
span.col-xs-2.title = t("admin.statistic.#{controller_name}.#{controller.action_name}.#{key}")
span.col-xs-10.value = val
The result of the code
So as you can see it renders 0.0BTC 5 times because the filter only has 5 orders. How do i deal with this. I want just the sum of all BTCs to show in the result instead of showing it 5 times.
Any help will be appreciated.
Because you sum strings in you're #fee_groups query that will results in putting strings next to each other instead of a total amount.
If you call it like this
#fee_groups = { fee: #assets.sum{|t| t.fee}}
You will get the total sum of you're assets.

Why aren't these 2 strings equal

Going blind here.. I can't understand why these 2 strings are not equal.. When I puts them to the terminal they are both class string and when I just compare the output they ARE equal. But somehow in my code they are not.. I can't figure out why.
Here is my Ruby code:
def prep_for_duplicate_webhook
#redis_cart = Redis.new
cart_stamp_saved = #redis_cart.get("cart_stamp_saved")
if cart_stamp_saved.nil?
cart_stamp_saved = {}
cart_stamp_saved[:token] = cart_params['token']
cart_stamp_saved[:updated_at] = cart_params['updated_at']
#redis_cart.set("cart_stamp_saved", cart_stamp_saved.to_json)
end
#cart_stamp_incoming = {}
#cart_stamp_incoming["token"] = cart_params['token']
#cart_stamp_incoming["updated_at"] = cart_params['updated_at']
end
def duplicate_webhook?
prep_for_duplicate_webhook
#cart_stamp_saved = redis_cart.get("cart_stamp_saved")
cart_stamp_saved == cart_stamp_incoming.to_json
end
And then the hash's I'm comparing are these two:
cart_stamp_saved = {"token"=>"4a093432ba5c430dd545b16c0e89f187",
"updated_at"=>"2017-02-17T15:27:22.923Z"}
cart_stamp_incoming= {"token"=>"4a093432ba5c430dd545b16c0e89f187",
"updated_at"=>"2017-02-17T15:27:22.923Z"}
If I just copy and paste the above into a new page, and the do this, the response is true
pp cart_stamp_saved == cart_stamp_incoming.to_json
What am I missing?

How to loop through arrays of different length in Ruby?

Let's say i have two relation arrays of a user's daily buy and sell.
how do i iterate through both of them using .each and still let the the longer array run independently once the shorter one is exhaused. Below i want to find the ratio of someone's daily buys and sells. But can't get the ratio because it's always 1 as i'm iterating through the longer array once for each item of the shorter array.
users = User.all
ratios = Hash.new
users.each do |user|
if user.buys.count > 0 && user.sells.count > 0
ratios[user.name] = Hash.new
buy_array = []
sell_array = []
date = ""
daily_buy = user.buys.group_by(&:created_at)
daily_sell = user.sells.group_by(&:created_at)
daily_buy.each do |buy|
daily_sell.each do |sell|
if buy[0].to_date == sell[0].to_date
date = buy[0].to_date
buy_array << buy[1]
sell_array << sell[1]
end
end
end
ratio_hash[user.name][date] = (buy_array.length.round(2)/sell_array.length)
end
end
Thanks!
You could concat both arrays and get rid of duplicated elements by doing:
(a_array + b_array).uniq.each do |num|
# code goes here
end
Uniq method API
daily_buy = user.buys.group_by(&:created_at)
daily_sell = user.sells.group_by(&:created_at
buys_and_sells = daily_buy + daily_sell
totals = buys_and_sells.inject({}) do |hsh, transaction|
hsh['buys'] ||= 0;
hsh['sells'] ||= 0;
hsh['buys'] += 1 if transaction.is_a?(Buy)
hsh['sells'] += 1 if transaction.is_a?(Sell)
hsh
end
hsh['buys']/hsh['sells']
I think the above might do it...rather than collecting each thing in to separate arrays, concat them together, then run through each item in the combined array, increasing the count in the appropriate key of the hash returned by the inject.
In this case you can't loop them with each use for loop
this code will give you a hint
ar = [1,2,3,4,5]
br = [1,2,3]
array_l = (ar.length > br.length) ? ar.length : br.length
for i in 0..array_l
if ar[i] and br[i]
puts ar[i].to_s + " " + br[i].to_s
elsif ar[i]
puts ar[i].to_s
elsif br[i]
puts br[i].to_s
end
end

Ruby method return more than one variable

I need to return to my Rails view more than one variable from method... But how could i do this?
For example now i have
def my1
#price = 1
#price
end
but how could i also return other valuem somethin like:
def my1
#qnt = 2
#price = 1
#price, #qnt
end
?
Also my idea is to split them to string like
#price + "/-/" + #qnt
and then just split them via /-/ in view.... But this is a bad practice...
So how could i get from one method two or more variables?
Return an array:
def my1
qnt = 2
price = 1
[price, qnt]
end
then you can do this:
p, q = my1() # parentheses to emphasize a method call
# do something with p and q
Option 2
Or you can return a custom object, like this:
require 'ostruct'
def my1
qnt = 2
price = 1
OpenStruct.new(price: price, quantity: qnt)
end
res = my1() # parentheses to emphasize a method call
res.quantity # => 2
res.price # => 1
Use another object that will hold the variables and return it. You can then access the variables from that object;
Array
The easiest way is to return an Array:
def my1
#qnt = 2
#price = 1
[ #price, #qnt ]
end
price, quantity = my1
Hash
But you could also return a Hash:
def my1
#qnt = 2
#price = 1
{ :quantity => #qnt, :price = #price
end
return_value = my1
price = return_value[:price]
quantity = return_value[:quantity]
# or
price, quantity = [ return_value[:price], return_value[:quantity] ]
Custom Class
Or a custom Class:
class ValueHolder
attr_reader :quantity, :price
def initialize(quantity, price)
#quantity = quantity
#price = price
end
end
def my1
#qnt = 2
#price = 1
ValueHolder.new(#qnt, #price)
end
value_holder = my1
price = value_holder.price
quantity = value_holder.quantity
# or
price, quantity = [ value_holder.price, value_holder.quantity ]
OpenStruct
You could use OpenStruct as Sergio mentioned.

Resources