MDekker
MDekker

Reputation: 443

Saving first key/value pair in Postgres HSTORE via Rails Activerecord

I am working on my Ruby on Rails application and this application has a Model called 'User'. This model has a database column (in my Postgres database) called 'remark'. And this 'remark' field is of the type HSTORE. It stores a hash with extra information about this user.

I am using a method which saves the value of a parameter (params[:info]) into this 'remark' field with a key 'info'. This code works.

def save_info_for_user(info)
    @user.remark = { :info => info }
    @user.save
  end  

And this code doesn't work when the database field is empty . So only when it holds a minimum of one key/value pair it is possible to save a new value like this.

  def save_info_for_user(info)
    @user.remark['info'] = info 
    @user.save
  end

It gives the following error:

   > undefined method `[]=' for nil:NilClass

And this code works neither:

  def save_info_for_user(info)
    @user.remark[:info] = info 
    @user.save
  end

It gives the same error

> undefined method `[]=' for nil:NilClass

And after some testing I found that 'remark[:info]' holds a different value than 'remark['info']'

Very confusing to me.

My question: Why does

@user.remark[:info] = info

gives that error. It should know that the database field 'remark' is a hash because its type is defined as HSTORE?

Hope someone can explain whats going on here and how to make this method futureproof.

Upvotes: 0

Views: 568

Answers (2)

Suneel
Suneel

Reputation: 381

Please try this. hopefully it will work for you.

def save_info_for_user(info)
  @user.remark = { "info" => info }
  @user.save
end  

Upvotes: -2

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230336

It should know that the database field 'remark' is a hash

Its type is a hash, all right, but its current value is NULL (these two are completely separate things). Meaning that it's unknown. Not even an empty hash (because that would be a known value).

So to futureproof this you make sure that remark is, at minimum, an empty hash before attempting any updates on it.

  def save_info_for_user(info)
    @user.remark ||= {}
    @user.remark['info'] = info 
    @user.save
  end

Upvotes: 1

Related Questions