Comparison signs (less than, less than or equal to, etc.) - ruby

I'm wondering how to test if a variable is between two values such as 1 and 10. For example I have the following:
bullet_hit = rand(1..10)
if 1 < bullet_hit < 10
...
I think I have the wrong syntax. Any help would be appreciated.

You can do it as simplest syntax:
<% bullet_hit = rand(1..10) %>
<% if 1 < bullet_hit && bullet_hit < 10 %>
<%= bullet_hit %>
<% end %>
but you have many methods to do it such as:
bullet_hit.between?(1,10) # true
(1..10).member?(bullet_hit) # true
(1..10).include?(bullet_hit)

You can use the Range#cover? method:
(2..9).cover?(bullet_hit)
That will return true for a bullet_hit value of 2, 3, 4, 5, 6, 7, 8, or 9.

Related

Algebraic number signs manipulation in ERB templates

I have an ERB template:
<%
a = rand(-10..10)
b = rand(-10..10)
c = rand(-10..10)
%>
The solution of this equation $<%=a%>x + <%=b%> = <%=c%>$ is
$<%=a%>x = <%=c%> - <%=b%>$
...
The problem is that when b is negative I get double minus. Example:
$2x = 4--2$
# a = 2, b= -2, c= 3, I get
Is there a way to avoid that and put + instead of --
Use an if statement:
<%= b > 0 ? '-' : '+' %>
You might also want to consider doing something different (but I don't know what!) if b == 0?
This would work: (instead of -b you could also say b.abs)
<% if b.negative? -%>
$<%= a %>x = <%= c %> - <%= -b %>$
<% else -%>
$<%= a %>x = <%= c %> + <%= b %>$
<% end -%>
Or, via string manipulation:
$<%= a %>x = <%= "#{c} + #{b}".sub('+ -', '- ') %>$

mapping values through deeply nested associations

A controller extracts data from deeply nested associations where bilancino belongs_to :operativo which in turn belongs_to :cdg as such:
#cdgs = Cdg.order("id ASC").all
#bilancinos = Bilancino.joins(:operativo).order('cdg_id ASC').all
(with a where clause in there).
However when rendering
<% #cdgs.each do |cdg| %>
<% #cdgs_for_bilancino = #bilancinos.select{ |i| i.operativo.cdg_id == cdg } %>
<%= #cdgs_for_bilancino.each do |bilancino| %> XX <% end %>
<%= number_with_precision(#cdgs_for_bilancino.map(&:saldo).sum, :precision => 0, :delimiter => "\u00a0") %>
<% end %>
is generating an empty array, yet if underneath the following
<% #bilancinos.each do |bilancino| %>
<%= bilancino.operativo.cdg.conto %> <%= bilancino.saldo %><br />
<% end %>
will render. Thus the expression #bilancinos.select{ |i| i.operativo.cdg_id is missing the nested target somehow.
What is the proper syntax?
I suspect your issue is here:
#bilancinos.select{ |i| i.operativo.cdg_id == cdg }
For example, this is what I see in the console of one of my apps:
irb(main):022:0> recruiter = Recruiter.find_by_id(1)
Recruiter Load (0.9ms) SELECT "recruiters".* FROM "recruiters" WHERE "recruiters"."id" = $1 LIMIT 1 [["id", 1]]
=> #<Recruiter id: 1>
irb(main):023:0> ping = Ping.find_by_id(1)
Ping Load (0.9ms) SELECT "pings".* FROM "pings" WHERE "pings"."id" = $1 LIMIT 1 [["id", 1]]
=> #<Ping id: 1, recruiter_id: 1>
irb(main):024:0> recruiter.pings.select{ |p| p.id == ping }
Ping Load (0.5ms) SELECT "pings".* FROM "pings" WHERE "pings"."recruiter_id" = $1 [["recruiter_id", 1]]
=> []
irb(main):025:0> recruiter.pings.select{ |p| p.id == ping.id }
=> [#<Ping id: 1, recruiter_id: 1>]
So try:
#bilancinos.select{ |i| i.operativo.cdg_id == cdg.id }

.each returning entire array after iterating through each element [duplicate]

This question already has an answer here:
Rails in rendering unnecessary information
(1 answer)
Closed 8 years ago.
I have a function in ruby
def words
ret =""
res = Net::HTTP.start(url.host, url.port) {|http|http.request(req)}
res.body.each_line do |line|
words = line.split("\"")
ret << words[1] << " "
end
return ret
end
say ret returns "Bill Dan Mike Sarah".
in my view I am doing
<%= #class.words.split(" ").each do |name| %>
<p><%= name %></p>
<% end %>
Instead of just displaying each name on a line, it does
Bill
Dan
Mike
Sarah
["Bill", "Dan", "Mike", "Sarah"] #this shouldn't be printed
What is causing it to display the entire array there at the end? How do I prevent this?
Remove an extra = from first line in each:
<% #class.words.split(" ").each do |name| %>
<p><%= name %></p>
<% end %>

List all Books by Price Range

I have created a functioning e-commerce platform where Members can buy books. Everything works fine, But I would like to group all of my Books in my Index Page by a Price Range.
Currently I am able to list all of my Books through a Loop, but my code is not very DRY.
How can I list all of the Books corresponding to a Price Range while keeping my code DRY?
EX of what I need.
Books Under $1
(.50, .99, .99. .50)
--------------------------
Books Between $1 & $2
(1.50, 1.99, 1.99. 1.50)
--------------------------
Books Between $2 & $3
(2.50, 2.99, 2.99. 2.50)
CONTROLLER
class BooksController < ApplicationController
def index
#publisher = Publisher.find(params[:publisher_id])
#books = #publisher.books.where(:ready => true).order("price")
end
end
MODELS
class Book < ActiveRecord::Base
attr_accessible :publisher_id, :price, :ready
end
VIEW
###This works fine, but can be really repetitive if I have books at a high price.
<% #books.each do |book| %>
<% if 0 <= book.price && book.price < 1 %>
Books under $1
<% end %$>
<% if 1 <= book.price && book.price < 2 %>
Books Between $1 & $2
<% end %$>
<% if 2 <= book.price && book.price < 3 %>
Books Between $2 & $3
<% end %$>
<% if 3 <= book.price && book.price < 4 %>
Books Between $3 & $4
<% end %$>
<% end %>
You can group by price.to_i to get them grouped properly, and then use a loop to write them all:
<% #books.group_by { |x| x.price.to_i }.each do |low_price, books| %>
<p>
Books between $<%= low_price %> and $<%= low_price + 1 %><br/>
(<%= books.map(&:price).join(', ') %>) <br/>
--------------------------
</p>
<% end %>
try a method in your books model:
def by_price(low, high)
self.price.between?(low, high)
end
then you could call books.by_price(0, 5) and get books between $0 and $5

Chef erubis template: Format output based on value's classes

In my Chef cookbook (for mailman), I want use an attribute that is a hash and contains all the configuration options I want to write into a template (similar to how it's done in the chef-client cookbook).
So I want to have in my attributes:
default[:myapp][:config] = {
"I_AM_A_STRING" => "fooo",
"I_AM_AN_INT" => 123,
"I_AM_AN_ARRAY" => ["abc", "cde"]
}
As output, I want the following (mailman compatible):
I_AM_A_STRING = 'fooo'
I_AM_AN_INT = 123
I_AM_AN_ARRAY = ['abc', 'cde']
However, it does not work.
To debug the problem, I have the following code in my erubis template:
<% node[:myapp][:config].each_pair do |key, value| -%>
<% case value.class %>
<% when Chef::Node::ImmutableArray %>
# <%= key %> is type <%= value.class %>, used when Chef::Node::ImmutableArray
<%= key %> = ['<%= value.join("','") %>']
<% when Fixnum %>
# <%= key %> is type <%= value.class %>, used when Fixnum
<%= key %> = <%= value %> #fixnum
<% when String %>
# <%= key %> is type <%= value.class %>, used when String
<%= key %> = '<%= value %>' #string
<% else %>
# <%= key %> is type <%= value.class %>, used else
<%= key %> = '<%= value %>'
<% end -%>
<% end -%>
So I want to use the case .. when to distinguish between value.class. However, none of the when conditions matches. So the output is:
# I_AM_A_STRING is type String, used else
I_AM_A_STRING = 'fooo'
# I_AM_AN_INT is type Fixnum, used else
I_AM_AN_INT = '123'
# I_AM_AN_ARRAY is type Chef::Node::ImmutableArray, used else
I_AM_AN_ARRAY = '["abc", "cde"]'
When I try when Whatever.class, the first when matches for all types.
What am I doing wrong?
Looks like you mean
<% case value %>
instead of
<% case value.class %>
That's how case..when works in ruby. It's often the case you need to switch based on value (or even a range of values ), and also on type.
It let's you do things like this in ruby (and hence also in erubis/eruby):
def f(x)
case x
when String then "#{x} is a String"
when 42 then "It's #{x==42}, x is 42"
when 21..27 then "#{x} is in 21..27"
when Fixnum then "#{x} is numeric, that's all I know"
else "Can't say."
end
end
f(1) # "1 is numeric, that's all I know"
f(25) # "25 is in 21..27"
f("hello") # "hello is a String"
f(false) # "Can't say."

Resources