rubyormsinatraruby-datamapper

DataMapper first_or_create always set certain field?


I'm using the following with datamapper to create/get a new user from my db:

user = User.first_or_create({:id => data['id']})

This gets the user with id = data['id'] or creates it if it doesn't already exist.

I want to know how to set other attributes/fields of the returned object regardless of whether it is a new record or existing?

Is the only way to do this to then call user.update({:field => value ...}) or is there a better way to achieve this?


Solution

  • Well, you could write it as one line:

    (User.first_or_create(:id => data['id'])).update(:field => value)
    

    with hashes for the parameters if you wish (or if you need to specify more than one); however, it's worth noting that this will only work if the model as specified by the first_or_create is valid. If :name were a required field, for instance, then this wouldn't work:

    (User.first_or_create({:id => data['id'], :name => "Morse"})).update(:name => "Lewis")
    

    as the creation in the first part would fail.

    You could get around this by specifying the parameters needed for a new record with something like

    (User.first_or_create({:id => data['id'], :name => "Morse"}, {:name => "Lewis"})).update(:name => "Lewis")
    

    but this is unusually painful, and is difficult to read.

    Also note that using first_or_create with an :id will attempt to create a model with that specific :id, if such a record doesn't exist. This might not be what you want.

    Alternatively, you can use first_or_new. You can't call update on an object created using this, however, as the record won't exist (although I believe this might have worked in previous versions of DataMapper).