3

I'm asking the opposite of the question to force empty strings to be NULL; instead, I want fields that are empty strings to be stored as empty strings. The reason I want to do so (even in contradiction to what some people say) is that I want to have a partial uniqueness constraint on the table that works for multiple database types (postgres, mysql, etc), as described in this question here.

The psuedocode for the schema is basically:

Person {
  first_name : String, presence: true
  middle_name : String, presence: true
  last_name : String, presence: true
  birth_date : String, presence: true
  city_of_birth: String, presence: true
  active: tinyint
}

The constraint is that a person must be unique if they are active; inactive people can be not unique (ie, I can have multiple John Smiths that are not active, but only one active John Smith).

Further complication: According to the project specification, only first_name and last_name are required to be given by the user, all other fields can be blank.

Our current solution for applying the partial uniqueness constraint is to use the fact that NULL != NULL, and set the active tinyint to NULL if someone is not active and set it to 1 if they are active. Thus, we can use this rails code in the migration:

add_index :Persons, [first_name, middle_name, last_name, birth_date, 
  city_of_birth, active], unique:true, name: "unique_person_constraint"

In order for this constraint to work, however, none of the other fields can be NULL. If they are, then two John Smiths with no other filled in fields and active = 1 will still be 'unique' because the middle_name fields with value NULL will be different from each other (because NULL != NULL, regardless of column type).

However, when I do

options = { first_name: "John",
  middle_name: "", 
  last_name: "Smith",
  birth_date: "",
  city_of_birth: "",
}
person = Person.new(options)
success = person.valid?

success is always false because

Middle name can't be blank
City of birth can't be blank
Birth date can't be blank

So I need a way to ensure that I always have at least empty strings for those other fields to enforce that partial uniqueness constraint. How can I do this? If I get rid of the presence:true in the model definition, then it appears that NULL fields are now allowed, which is bad.

This is Rails 3.2.13, and I can give other gems and gem versions if necessary.

Community
  • 1
  • 1
mmr
  • 14,781
  • 29
  • 95
  • 145

1 Answers1

0

Along with presence true, you can also add allow_blank as true which would allow you save empty strings.