Spyros
Spyros

Reputation: 48626

Map string to another string in Ruby Rails

Hey guys, i have 5 model attributes, for example, 'str' and 'dex'. A user has strength, dexterity attribute.

When i call user.increase_attr('dex') i want to do it through 'dex' and not having to pass 'dexterity' string all the way.

Of course, i can just check if ability == 'dex' and convert it to 'dexterity' when i will need to do user.dexterity += 1 and then save it.

But what is a good ruby way to do that ?

Upvotes: 1

Views: 2295

Answers (2)

the Tin Man
the Tin Man

Reputation: 160551

Look at Ruby's Abbrev module that's part of the standard library. This should give you some ideas.

require 'abbrev'
require 'pp'

class User
  def increase_attr(s)
    "increasing using '#{s}'"
  end
end

abbreviations = Hash[*Abbrev::abbrev(%w[dexterity strength speed height weight]).flatten]

user = User.new
user.increase_attr(abbreviations['dex']) # => "increasing using 'dexterity'"
user.increase_attr(abbreviations['s']) # => "increasing using ''"
user.increase_attr(abbreviations['st']) # => "increasing using 'strength'"
user.increase_attr(abbreviations['sp']) # => "increasing using 'speed'"

If an ambiguous value is passed in, (the "s"), nothing will match. If a unique value is found in the hash, the returned value is the full string, making it easy to map short strings to the full string.

Because having varying lengths of the trigger strings would be confusing to the user you could strip all elements of the hash that have keys shorter than the shortest unambiguous key. In other words, remove anything shorter than two characters because of the collision of "speed" ("sp") and "strength" ("st"), meaning "h", "d" and "w" need to go. It's a "be kind to the poor human users" thing.

Here's what is created when Abbrev::abbrev does its magic and it's coerced into a Hash.

pp abbreviations
# >> {"dexterit"=>"dexterity",
# >>  "dexteri"=>"dexterity",
# >>  "dexter"=>"dexterity",
# >>  "dexte"=>"dexterity",
# >>  "dext"=>"dexterity",
# >>  "dex"=>"dexterity",
# >>  "de"=>"dexterity",
# >>  "d"=>"dexterity",
# >>  "strengt"=>"strength",
# >>  "streng"=>"strength",
# >>  "stren"=>"strength",
# >>  "stre"=>"strength",
# >>  "str"=>"strength",
# >>  "st"=>"strength",
# >>  "spee"=>"speed",
# >>  "spe"=>"speed",
# >>  "sp"=>"speed",
# >>  "heigh"=>"height",
# >>  "heig"=>"height",
# >>  "hei"=>"height",
# >>  "he"=>"height",
# >>  "h"=>"height",
# >>  "weigh"=>"weight",
# >>  "weig"=>"weight",
# >>  "wei"=>"weight",
# >>  "we"=>"weight",
# >>  "w"=>"weight",
# >>  "dexterity"=>"dexterity",
# >>  "strength"=>"strength",
# >>  "speed"=>"speed",
# >>  "height"=>"height",
# >>  "weight"=>"weight"}

Upvotes: 3

Mike Lewis
Mike Lewis

Reputation: 64137

def increase_attr(attr)
  attr_map = {'dex' => :dexterity, 'str' => :strength}
  increment!(attr_map[attr]) if attr_map.include?(attr)
end

Basically create a Hash that has the key of 'dex', 'str' etc and points to the expanded version of that word(in symbol format).

Upvotes: 1

Related Questions