If equal requires string conversion to work? - ruby-on-rails

It seems that #original_id and comment.id have to be converted to strings to compare equal, when I don't convert them to strings, the string in the else branch is returned. Why is this? And is there a way round it?
- if #original_id.to_s == comment.id.to_s
= "Matched"
- else
= "hi"
Context:
.comment{:class => "c" + nesting.to_s}
.profile
%img{:src => "/assets/profile_image_sample.jpg"}
.message
.username
- if comment.user.username.blank?
= comment.user.first_name
- else
= comment.user.username
= comment.content
.reply-link
= link_to "Reply to comment...", post_path(:original_id => comment.id)
= #original_id.to_s + "and" + comment.id.to_s
- if #original_id.to_s == comment.id.to_s
= "Matched"
- else
= "hi"
- if comment.replies.count > 0
- nesting = nesting + 1
- comment.replies.each do |comment|
= render "comment", :comment => comment, :nesting => nesting

One of those two variables is a string, while the other is a number.
A possible cause is that in the controller, all received (posted) parameters are strings. Without explicit conversion, you are passing this value to the view as a string.
And to answer your second question:
Convert #original_id to an integer when setting it in the controller:
#original_id = params[:original_id].to_i

Related

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.

Rails loop through data fields error

I'm trying to run a median calculation on data fields.
Each Glaze has the following decimal fields: "k2o", "na2o", "cao", "bao", "mgo", "sro".
I want to write a method to calculate the median of each datafield using the entire database of Glazes but I don't want to write individual methods for each oxide.
My plan was to loop through them using an array of the oxide names. I defined an array called #oxides = ["k2o","n2o","cao","bao","mgo","sro"].
View:
<% #oxides.each do |oxide| %>
<%= oxide %> median: <%= median(oxide) %><br/>
<% end %>
Controller:
def median(oxide)
g = Glaze.all
array = g.map { |g| g.oxide.to_s.to_f.round(3) }
sorted = array.sort
len = sorted.length
(sorted[(len - 1) / 2] + sorted[len / 2]) / 2.0
end
helper_method :median
This returns an error:
unknown method 'oxide'
If I substitute k2o in place of oxide in the array then it works fine. I'm not familiar enough with variable types but I guess it is looking for a method because no oxide field exists.
How can I force it to look for the value of oxide so that I can easily loop through g.k2o...,g.na2o...,g.cao...etc. ?
The Glaze class does not have an instance method oxide, but instead has 5 methods k2o, na2o, cao, bao, mgo, sro. In
array = g.map { |g| g.oxide.to_s.to_f.round(3) }
the inner g is an instance of Glaze, so it will fail when you call g.oxide. If you want to do the same to all fields, i.e.
k2o_array = g.map { |g| g.k2o.to_s.to_f.round(3) }
na2o_array = g.map { |g| g.na2o.to_s.to_f.round(3) }
cao_array = g.map { |g| g.cao.to_s.to_f.round(3) }
bao_array = g.map { |g| g.bao.to_s.to_f.round(3) }
mgo_array = g.map { |g| g.mgo.to_s.to_f.round(3) }
sro_array = g.map { |g| g.sro.to_s.to_f.round(3) }
then you need public_send:
OXIDES = [:k2o, :na2o, :cao, :bao, :mgo, :sro]
def median(oxide)
med = Hash.new
OXIDES.each do |oxide|
values = Glaze.all.map do |glaze|
glaze.public_send(oxide).to_s.to_f.round(3)
end
values.sort!
len = values.length
med[oxide] = (values[(len - 1) / 2] + values[len / 2]) / 2.0
end
return values
end
helper_method :median
which will give you
{:k2o=>1.111, :na2o=>2.222, :cao=>3.333, :bao=>4.444, :mgo=>5.556, :sro=>6.667}
Note that I store the oxide list in a constant instead of an instance variable because it never changes.

constructing a new hash from the given values

I seem lost trying to achieve the following, I tried all day please help
I HAVE
h = {
"kv1001"=> {
"impressions"=>{"b"=>0.245, "a"=>0.754},
"visitors" =>{"b"=>0.288, "a"=>0.711},
"ctr" =>{"b"=>0.003, "a"=>0.003},
"inScreen"=>{"b"=>3.95, "a"=>5.031}
},
"kv1002"=> {
"impressions"=>{"c"=>0.930, "d"=>0.035, "a"=>0.004, "b"=>0.019,"e"=>0.010},
"visitors"=>{"c"=>0.905, "d"=>0.048, "a"=>0.005, "b"=>0.026, "e"=>0.013},
"ctr"=>{"c"=>0.003, "d"=>0.006, "a"=>0.004, "b"=>0.003, "e"=>0.005},
"inScreen"=>{"c"=>4.731, "d"=>4.691, "a"=>5.533, "b"=>6.025, "e"=>5.546}
}
}
MY GOAL
{
"segment"=>"kv1001=a",
"impressions"=>"0.754",
"visitors"=>"0.711",
"inScreen"=>"5.031",
"ctr"=>"0.003"
}, {
"segment"=>"kv1001=b",
"impressions"=>"0.245",
"visitors"=>"0.288",
"inScreen"=>"3.95",
"ctr"=>"0.003"
}, {
"segment"=>"kv1002=a",
"impressions"=>"0.004"
#... etc
}
My goal is to create a hash with 'kv1001=a' i.e the letters inside the hash and assign the keys like impressions, visitors etc. The example MY GOAL has the format
So format type "kv1001=a" must be constructed from the hash itself, a is the letter inside the hash.
I have solved this now
`data_final = []
h.each do |group,val|
a = Array.new(26){{}}
val.values.each_with_index do |v, i|
keys = val.keys
segment_count = v.keys.length
(0..segment_count-1).each do |n|
a0 = {"segment" => "#{group}=#{v.to_a[n][0]}", keys[i] => v.to_a[n][1]}
a[n].merge! a0
if a[n].count > 4
data_final << a[n]
end
end
end
end`
Here's a simpler version
h.flat_map do |segment, attrs|
letters = attrs.values.flat_map(&:keys).uniq
# create a segment entry for each unique letter
letters.map do |letter|
seg = {"segment" => "#{segment}=#{letter}"}
seg.merge Hash[attrs.keys.map {|key| [key,attrs[key][letter]]}]
end
end
Output:
[{"segment"=>"kv1001=b",
"impressions"=>0.245,
"visitors"=>0.288,
"ctr"=>0.003,
"inScreen"=>3.95},
{"segment"=>"kv1001=a",
"impressions"=>0.754,
"visitors"=>0.711,
"ctr"=>0.003,
"inScreen"=>5.031},
{"segment"=>"kv1002=c",
"impressions"=>0.93,
"visitors"=>0.905,
"ctr"=>0.003,
"inScreen"=>4.731},
{"segment"=>"kv1002=d",
"impressions"=>0.035,
"visitors"=>0.048,
"ctr"=>0.006,
"inScreen"=>4.691},
{"segment"=>"kv1002=a",
"impressions"=>0.004,
"visitors"=>0.005,
"ctr"=>0.004,
"inScreen"=>5.533},
{"segment"=>"kv1002=b",
"impressions"=>0.019,
"visitors"=>0.026,
"ctr"=>0.003,
"inScreen"=>6.025},
{"segment"=>"kv1002=e",
"impressions"=>0.01,
"visitors"=>0.013,
"ctr"=>0.005,
"inScreen"=>5.546}]

adding a key value to array isn't display the key value on debugger

ruby on rails
def get_process_order_items
po = ProcessOrder.find(params[:id])
ids = po.process_order_items.map { |e| e.fabric.id }
a = Fabric.where(:id => ids.uniq())
a.collect{ |b| b[:pre_weight] = get_fabric_num(params[:id]) }
debugger
wando_grid_for_array(params, a)
end
can't display the key value on a. on debugger. Could you tell me?
thanks
a.collect{ |b| b[:pre_weight] = get_fabric_num(params[:id]) } seems to have no side-effect, did you mean a.collect!{ |b| b[:pre_weight] = get_fabric_num(params[:id]) }, perhaps?

Setting Helper Method Return Value as Instance Variable

So I have an application wide helper method for breadcrumbs, that I use in the layout, across all view pages.
Here is the method below
- if request.fullpath != '/'
.row
.col-md-12
#breadcrumbs
= link_to 'home', '/'
%span »
- #BreadcrumbsHelper = breadcrumbs
- i = 0
- #BreadcrumbsHelper.each do |name, breadcrumb|
= link_to name, breadcrumb
- if i != (#BreadcrumbsHelper.count - 1)
%span »
- i = i + 1
From what I understand, variables in the view should be instance variables and not methods, however declaring the instance variable in the view doesn't really seem to make sense, but I am not sure how else to go about it, would it be acceptable just to leave it as a method call ie breadcrumbs.each do for example? Would that even work? What is the best practice.
EDIT (the helper, just in case it helps) :
module BreadcrumbsHelper
def breadcrumbs
current_path = request.fullpath
noparam_path = current_path.split('?')
path_parts = noparam_path[0].split('/')
path_parts.shift
counter = path_parts.size
new_paths = Hash.new
counter.times do
new_path = ""
path_name = ""
i = 0
path_parts.each do |part|
if i < counter
if new_path == ""
new_path = '/' + part
else
new_path = new_path + '/' + part
end
path_name = part
i = i + 1
end
end
counter = counter -1
#path functions
def routeValid(new_path)
route = "/" + new_path.gsub("_","/")
route_valid = true
begin
Rails.application.routes.recognize_path(route, :method => :get)
rescue
# error means that your route is not valid, so do something to remember that here
route_valid = false
end
return route_valid
end
def processPath(new_path, path_name, new_paths)
if routeValid(new_path) == true
#Optional Overrides
if path_name == "signup"
path_name = "sign up"
end
new_paths[path_name] = new_path
end
end
processPath(new_path, path_name, new_paths)
end
new_paths = Hash[new_paths.to_a.reverse]
return new_paths
end
end
Helpers are modules that are included in the view. They are not accessed via instance variables.
You should be able to access a method defined in a helper directly in a view. So rather than writing
- #BreadcrumbsHelper = breadcrumbs
- i = 0
- #BreadcrumbsHelper.each do |name, breadcrumb|
you would just write something like
- breadcrumbs.each do |name, breadcrumb|
You will also probably want to capture the count of breadcrumbs before the loop, with something like
- my_breadcrumbs = breadcrumbs
- breadcrumbs_count = my_breadcrumbs.size
- my_breadcrumbs.each do |name, breadcrumb|
and replacing
#BreadcrumbsHelper.count
with
breadcrumbs_count

Resources