Gary
Gary

Reputation: 4241

How can I make a property of a class case-insensitive?

In CoffeeScript, let's say I've got the following:

class Greeter
    message: ->
        greeting = switch @gender
            when 'male' then 'Sir'
            when 'female' then 'Madame'
            else 'Unknown'

        "Hello #{greeting}!"

greeter = new Greeter
greeter.gender = 'Male'
alert greeter.message()

This currently alerts Hello Unknown! when I want it to output Hello Sir!.

How do I make it so that the Greeter class will lowercase the @gender instance variable so that the correct output is achieved? I don't want to just lowercase it in the message method, but rather, all throughout an Instance of the Class. This is so that it works in other methods too.

I think I'm missing something very basic but I just can't seem to wrap my head around it.

NOTE: To those saying I got the capitalization wrong for "Male". Yes, I purposely did that. I'd like the class to automatically lowercase gender in all cases, before using it. So the user can get the capitalization wrong and it still works.

The reason is that I'd eventually like to extrapolate this to other situations, rather than just those dealing with case-insensitivity issues.

Some people have mentioned JavaScript Getters and Setters, which are relatively new and therefore not supported in all major browsers. I'll take a look at those. I'm somewhat familiar with them through Ruby.

Upvotes: 1

Views: 319

Answers (2)

jcollum
jcollum

Reputation: 46609

coffee> 
  class Greeter
    message: =>
        greeting =
          if /^male/i.test(@gender) then 'Sir'
          else if /^female/i.test(@gender) then 'Madame'
          else 'Unknown'

        "Hello #{greeting}!"

greeter = new Greeter
greeter.gender = 'Male'
greeter.message()

'Hello Sir!'
coffee> greeter.gender  = 'female' 
'female'
coffee> greeter.message()
'Hello Madame!'
coffee> greeter.gender  = 'smizmar' 
'smizmar'
coffee> greeter.message()
'Hello Unknown!'
coffee> 

So that's the simple way to do it, but it doesn't change the value stored. To do that, you'll need to use Object.defineProperty (SO answer about it):

Function::property = (prop, desc) ->
  Object.defineProperty @prototype, prop, desc

class Greeter
  constructor: () ->
  @property 'gender',
    get: -> "#{@ciGender}"
    set: (v) -> @ciGender = v.toLowerCase()
  message: ->
    greeting = switch @ciGender
        when 'male' then 'Sir'
        when 'female' then 'Madame'
        else 'Unknown'

    "Hello #{greeting}!"

Upvotes: 0

Sylvain Leroux
Sylvain Leroux

Reputation: 52040

Male is not male. Try normalize your string as lower case:

message: ->
    greeting = switch @gender.toLowerCase()
        when 'male' then 'Sir'
        when 'female' then 'Madame'
        else 'Unknown'

If necessary, you might want to encapsulate the call to lowercase in some property getter: https://stackoverflow.com/a/11592890/2363712 Something like that:

class Greeter
    constructor: ->
        Object.defineProperty  @, 'gender',
            get: ->
                return @_gender
            set: (value) ->
                @_gender = value.toLowerCase()

    message: ->
        greeting = switch @gender
            when 'male' then 'Sir'
            when 'female' then 'Madame'
            else 'Unknown'

        "Hello #{greeting}!"

For this to work, your run-time environment must support Object.defineProperty
See that table for a quick lookup of supported browsers.

Upvotes: 2

Related Questions