Rails 2 - Absolute of money - ruby-on-rails-2

How to get absolute value of money?
e.g:
-2.to_money.? = 2.to_money
2.to_money.? = 2.to_money
I have an attribute total_price, which may be positive or negative. I want to calculate the absolute value of total_price.

Try taking the absolute value before converting to money.
2.abs.to_money

There's now an absolute value method built-in to the Money::Arithmetic module:
2.to_money.abs == #<Money fractional:200 currency:USD> # true
-2.to_money.abs == #<Money fractional:200 currency:USD> # true

Related

how to use ruby to assign a default if a value is nil?

I have the following to default to 5 if there is not value for json_element['LIMIT']:
json_element['LIMIT'] = 500
limit ||= json_element['LIMIT'].to_i
limit ||= 5
This is the current implementation, but it seems like one line too long.
As Amndan says, the idea here is you order things in order of precedence, highest to lowest, left to right, so generally speaking:
def do_thing(limit_override)
limit ||= limit_override || input || DEFAULT
end
In your case you're testing a Hash property and converting to integer, so you have options:
limit ||= json_element['LIMIT'] ? json_element['LIMIT'].to_i : 5
Or just to_i whatever you get even if it's ever so slightly less efficient:
limit ||= (json_element['LIMIT'] || 5).to_i

What does .between? method means in Ruby?

I have a exercise of the school and i can't resolve it. Can you help me?
The problem is this:
Try using a method that takes two arguments - use the between? method
to determine if the number 2 lies between the numbers 1 and 3.
I tried to find what is the .between? method but í couldn't find it.
I just know that is a method
The method is Comparable#between?, and you can use it like this:
2.between?(1, 3)
# => true
use between? is the easiest way, I found most answers here didn't mention (ruby doc explanation is hard to understand too), using between? does INCLUDE the min and max value.
for example:
irb(main):001:0> 2.between?(1, 3)
=> true
irb(main):002:0> 3.between?(1, 3)
=> true
irb(main):003:0> 1.between?(1, 3)
=> true
irb(main):004:0> 0.between?(1, 3)
=> false
by the way, ruby doc quote (too hard to understand for newbie):
between?(min, max) → true or false Returns false if obj <=> min is
less than zero or if anObject <=> max is greater than zero, true
otherwise.
From "between" ruby documentation:
between?(min, max) → true or false
Returns false if obj <=> min is less than zero or if anObject <=> max is greater than zero, true otherwise.
Uh oh, and of course, it's #=== method for ranges:
( 1..3 ) === 2 #=> true
( 1..3 ) === 4 #=> false
You can use Range#cover? as a solution :
(1..3).cover? 2 #=> true

Ruby - modifying classes

I wrote simple method which checks if a number is Armstrong number.
But now I want to modify default Number class putting method.
So, I have code:
def is_an(number)
(number.to_s.split(//).map(&:to_i).inject{|x,y|x+y**(number.size-1)}) == number ? true : false
end
p is_an(153)
I want to use it as method: 153.is_a?
So, how I do this?
class Number
def is_an
??? How to use object data over here? ???
end
end
Thx a lot for reading.
Incorporating #mikej's answer, plus replacing number with self:
class Fixnum
def is_an
digits = self.to_s.split(//).map(&:to_i)
digits.inject(0) { |x,y| x+y**digits.size } == self
end
end
But I would suggest a name change, to make it more Ruby like. Instead of #is_an, which isn't very descriptive, how about #armstrong? then you can call:
153.armstrong?
Not an answer to your original question, but there are a couple of small bugs in your code. You need to pass 0 to the inject to use as an initial value. Otherwise, inject takes the first value from the list as the initial value. Your current code seems to work for 153 because 1^3 == 1 but it would return false for 370, for example, when it should return true.
Also, the size method on Fixnums doesn't return the number of digits in a number.
Finally, a minor point: the ? true : false isn't needed because the value of the ... == number expression is already the required boolean value. So a possible updated method would be:
def is_an(number)
digits = number.to_s.split(//).map(&:to_i)
digits.inject(0) { |x,y| x+y**digits.size } == number
end

Ruby: counting digits in a float number

Is there any worthy Ruby method to count the number of digits in a float? Also, how do I specify the precise when to_s float numbers?
# Number of digits
12345.23.to_s.split("").size -1 #=> 7
# The precious part
("." + 12345.23.to_s.split(".")[1]).to_f #=> .023
# I would rather used
# 12345.23 - 12345.23.to_i
# but this gives 0.22999999999563
to specify precision of a float in Ruby. you can use the round method.
number.round(2)
2 is the precision.
53.819.round(2) -> 53.82
I think you should check out the number_with_precision helper.
number_with_precision(13, :precision => 5) # => 13.00000

How do I generate a random 10 digit number in ruby?

Additionally, how can I format it as a string padded with zeros?
To generate the number call rand with the result of the expression "10 to the power of 10"
rand(10 ** 10)
To pad the number with zeros you can use the string format operator
'%010d' % rand(10 ** 10)
or the rjust method of string
rand(10 ** 10).to_s.rjust(10,'0')
I would like to contribute probably a simplest solution I know, which is a quite a good trick.
rand.to_s[2..11]
=> "5950281724"
This is a fast way to generate a 10-sized string of digits:
10.times.map{rand(10)}.join # => "3401487670"
The most straightforward answer would probably be
rand(1e9...1e10).to_i
The to_i part is needed because 1e9 and 1e10 are actually floats:
irb(main)> 1e9.class
=> Float
DON'T USE rand.to_s[2..11].to_i
Why? Because here's what you can get:
rand.to_s[2..9] #=> "04890612"
and then:
"04890612".to_i #=> 4890612
Note that:
4890612.to_s.length #=> 7
Which is not what you've expected!
To check that error in your own code, instead of .to_i you may wrap it like this:
Integer(rand.to_s[2..9])
and very soon it will turn out that:
ArgumentError: invalid value for Integer(): "02939053"
So it's always better to stick to .center, but keep in mind that:
rand(9)
sometimes may give you 0.
To prevent that:
rand(1..9)
which will always return something withing 1..9 range.
I'm glad that I had good tests and I hope you will avoid breaking your system.
Random number generation
Use Kernel#rand method:
rand(1_000_000_000..9_999_999_999) # => random 10-digits number
Random string generation
Use times + map + join combination:
10.times.map { rand(0..9) }.join # => random 10-digit string (may start with 0!)
Number to string conversion with padding
Use String#% method:
"%010d" % 123348 # => "0000123348"
Password generation
Use KeePass password generator library, it supports different patterns for generating random password:
KeePass::Password.generate("d{10}") # => random 10-digit string (may start with 0!)
A documentation for KeePass patterns can be found here.
Just because it wasn't mentioned, the Kernel#sprintf method (or it's alias Kernel#format in the Powerpack Library) is generally preferred over the String#% method, as mentioned in the Ruby Community Style Guide.
Of course this is highly debatable, but to provide insight:
The syntax of #quackingduck's answer would be
# considered bad
'%010d' % rand(10**10)
# considered good
sprintf('%010d', rand(10**10))
The nature of this preference is primarily due to the cryptic nature of %. It's not very semantic by itself and without any additional context it can be confused with the % modulo operator.
Examples from the Style Guide:
# bad
'%d %d' % [20, 10]
# => '20 10'
# good
sprintf('%d %d', 20, 10)
# => '20 10'
# good
sprintf('%{first} %{second}', first: 20, second: 10)
# => '20 10'
format('%d %d', 20, 10)
# => '20 10'
# good
format('%{first} %{second}', first: 20, second: 10)
# => '20 10'
To make justice for String#%, I personally really like using operator-like syntaxes instead of commands, the same way you would do your_array << 'foo' over your_array.push('123').
This just illustrates a tendency in the community, what's "best" is up to you.
More info in this blogpost.
I ended up with using Ruby kernel srand
srand.to_s.last(10)
Docs here: Kernel#srand
Here is an expression that will use one fewer method call than quackingduck's example.
'%011d' % rand(1e10)
One caveat, 1e10 is a Float, and Kernel#rand ends up calling to_i on it, so for some higher values you might have some inconsistencies. To be more precise with a literal, you could also do:
'%011d' % rand(10_000_000_000) # Note that underscores are ignored in integer literals
('%010d' % rand(0..9999999999)).to_s
or
"#{'%010d' % rand(0..9999999999)}"
I just want to modify first answer. rand (10**10) may generate 9 digit random no if 0 is in first place. For ensuring 10 exact digit just modify
code = rand(10**10)
while code.to_s.length != 10
code = rand(11**11)
end
Try using the SecureRandom ruby library.
It generates random numbers but the length is not specific.
Go through this link for more information: http://ruby-doc.org/stdlib-2.1.2/libdoc/securerandom/rdoc/SecureRandom.html
Simplest way to generate n digit random number -
Random.new.rand((10**(n - 1))..(10**n))
generate 10 digit number number -
Random.new.rand((10**(10 - 1))..(10**10))
This technique works for any "alphabet"
(1..10).map{"0123456789".chars.to_a.sample}.join
=> "6383411680"
Just use straightforward below.
rand(10 ** 9...10 ** 10)
Just test it on IRB with below.
(1..1000).each { puts rand(10 ** 9...10 ** 10) }
To generate a random, 10-digit string:
# This generates a 10-digit string, where the
# minimum possible value is "0000000000", and the
# maximum possible value is "9999999999"
SecureRandom.random_number(10**10).to_s.rjust(10, '0')
Here's more detail of what's happening, shown by breaking the single line into multiple lines with explaining variables:
# Calculate the upper bound for the random number generator
# upper_bound = 10,000,000,000
upper_bound = 10**10
# n will be an integer with a minimum possible value of 0,
# and a maximum possible value of 9,999,999,999
n = SecureRandom.random_number(upper_bound)
# Convert the integer n to a string
# unpadded_str will be "0" if n == 0
# unpadded_str will be "9999999999" if n == 9_999_999_999
unpadded_str = n.to_s
# Pad the string with leading zeroes if it is less than
# 10 digits long.
# "0" would be padded to "0000000000"
# "123" would be padded to "0000000123"
# "9999999999" would not be padded, and remains unchanged as "9999999999"
padded_str = unpadded_str.rjust(10, '0')
rand(9999999999).to_s.center(10, rand(9).to_s).to_i
is faster than
rand.to_s[2..11].to_i
You can use:
puts Benchmark.measure{(1..1000000).map{rand(9999999999).to_s.center(10, rand(9).to_s).to_i}}
and
puts Benchmark.measure{(1..1000000).map{rand.to_s[2..11].to_i}}
in Rails console to confirm that.
An alternative answer, using the regexp-examples ruby gem:
require 'regexp-examples'
/\d{10}/.random_example # => "0826423747"
There's no need to "pad with zeros" with this approach, since you are immediately generating a String.
This will work even on ruby 1.8.7:
rand(9999999999).to_s.center(10, rand(9).to_s).to_i
A better approach is use Array.new() instead of .times.map. Rubocop recommends it.
Example:
string_size = 9
Array.new(string_size) do
rand(10).to_s
end
Rubucop, TimesMap:
https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Performance/TimesMap
In my case number must be unique in my models, so I added checking block.
module StringUtil
refine String.singleton_class do
def generate_random_digits(size:)
proc = lambda{ rand.to_s[2...(2 + size)] }
if block_given?
loop do
generated = proc.call
break generated if yield(generated) # check generated num meets condition
end
else
proc.call
end
end
end
end
using StringUtil
String.generate_random_digits(3) => "763"
String.generate_random_digits(3) do |num|
User.find_by(code: num).nil?
end => "689"(This is unique in Users code)
I did something like this
x = 10 #Number of digit
(rand(10 ** x) + 10**x).to_s[0..x-1]
Random 10 numbers:
require 'string_pattern'
puts "10:N".gen

Resources