Evan Walsh
Evan Walsh

Reputation: 442

Converting filesize string to kilobyte equivalent in Rails

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.

Upvotes: 5

Views: 4159

Answers (4)

netwire
netwire

Reputation: 7215

You can use Rails ActiveHelper number_to_human_size.

Upvotes: 4

Bryan Ash
Bryan Ash

Reputation: 4488

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

Upvotes: 3

hundredwatt
hundredwatt

Reputation: 308

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

Upvotes: 0

ennuikiller
ennuikiller

Reputation: 46965

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!

Upvotes: 1

Related Questions