Converting filesize string to kilobyte equivalent in Rails
Asked Answered
S

4

5

My objective is to convert form input, like "100 megabytes" or "1 gigabyte", and converts it to a filesize in kilobytes I can store in the database. Currently, I have this:

def quota_convert
  @regex = /([0-9]+) (.*)s/
  @sizes = %w{kilobyte megabyte gigabyte}
  m = self.quota.match(@regex)
  if @sizes.include? m[2]
    eval("self.quota = #{m[1]}.#{m[2]}")
  end
end

This works, but only if the input is a multiple ("gigabytes", but not "gigabyte") and seems insanely unsafe due to the use of eval. So, functional, but I won't sleep well tonight.

Any guidance?

EDIT: ------

All right. For some reason, the regex with (.*?) isn't working correctly on my setup, but I've worked around it with Rails stuff. Also, I've realized that bytes would work better for me.

def quota_convert
  @regex = /^([0-9]+\.?[0-9]*?) (.*)/
  @sizes = { 'kilobyte' => 1024, 'megabyte' => 1048576, 'gigabyte' => 1073741824}
  m = self.quota.match(@regex)
  if @sizes.include? m[2].singularize
    self.quota = m[1].to_f*@sizes[m[2].singularize]
  end
end

This catches "1 megabyte", "1.5 megabytes", and most other things (I hope). It then makes it the singular version regardless. Then it does the multiplication and spits out magic answers.

Is this legit?

EDIT AGAIN: See answer below. Much cleaner than my nonsense.

Semidome answered 30/6, 2010 at 0:2 Comment(0)
B
3
def quota_convert
  @regex = /([0-9]+) (.*)s?/
  @sizes = "kilobytes megabytes gigabytes"
  m = self.quota.match(@regex)
  if @sizes.include? m[2]
    m[1].to_f.send(m[2])
  end
end
  • Added ? for optional plural in the regex.
  • Changed @sizes to a string of plurals.
  • Convert m[1] (the number to a float).
  • Send the message m[2] directly
Bowline answered 30/6, 2010 at 0:29 Comment(2)
Wow. This is really perfect. Thank you so much. It's so clean.Semidome
If clean is what you seek, how about moving that functionality into String#bytes and calling self.quota.bytesBowline
E
4

You can use Rails ActiveHelper number_to_human_size.

Edea answered 7/10, 2013 at 15:12 Comment(1)
This answer converts a number to a string. It has nothing to do with the question.Bowline
B
3
def quota_convert
  @regex = /([0-9]+) (.*)s?/
  @sizes = "kilobytes megabytes gigabytes"
  m = self.quota.match(@regex)
  if @sizes.include? m[2]
    m[1].to_f.send(m[2])
  end
end
  • Added ? for optional plural in the regex.
  • Changed @sizes to a string of plurals.
  • Convert m[1] (the number to a float).
  • Send the message m[2] directly
Bowline answered 30/6, 2010 at 0:29 Comment(2)
Wow. This is really perfect. Thank you so much. It's so clean.Semidome
If clean is what you seek, how about moving that functionality into String#bytes and calling self.quota.bytesBowline
S
1

why don't you simply create a hash that contains various spellings of the multiplier as the key and the numerical value as the value? No eval necessary and no regexs either!

Succuss answered 30/6, 2010 at 0:4 Comment(2)
The problem with that is I want to account for all cases ("550 megabytes", "1.5 gigabytes", etc) and a hash would just be ridiculous if I did that. I'd rather hand the conversion part over to Rails. I just need to parse it all out...somehow...Semidome
the point is you can read in the numeric values as numbers and just have the hash contain the multiplicative factor (kb, gb, mb etc.)Succuss
C
0

First of all, changing your regex to @regex = /([0-9]+) (.*?)s?/ will fix the plural issue. The ? says match either 0 or 1 characters for the 's' and it causes .* to match in a non-greedy manner (as few characters as possible).

As for the size, you could have a hash like this:

@hash = { 'kilobyte' => 1, 'megabyte' => 1024, 'gigabyte' => 1024*1024}

and then your calculation is just self.quota = m[1].to_i*@hash[m2]

EDIT: Changed values to base 2

Cataplexy answered 30/6, 2010 at 0:8 Comment(1)
Also, to account for values such as '1.5 kilobytes', your regex would be @regex = /([0-9]+\.?[0-9]*?) (.*?)s?/. In that case, you would need to change the calculation to m[1].to_f to convert the string to a floating point valueCataplexy

© 2022 - 2024 — McMap. All rights reserved.