carlosparamio / mongo_odm

Flexible persistence module for any Ruby class to MongoDB
http://github.com/carlosparamio/mongo_odm
MIT License
41 stars 8 forks source link

Document fields initialization improvement proposal (?) #14

Open michalkrause opened 13 years ago

michalkrause commented 13 years ago

I have found that MongoODM::Document mixes default field values with values given to new method as arguments during fields initialization. I found situation when this behavior doesn't play well. The typical case is when document contains faked "field" which just accepts/returns another representation of "master" field. Let's have following sample document:

class Post
    include MongoODM::Document
    field :tags_array, Array, :default => []
    # other fields ...

    def tags
        self.tags_array.join(',')
    end

    def tags=(value)
        self.tags_array = value.split(',').map(&:strip).reject(&:blank?)
    end
end

When Post instance is edited via web form, tags can be used instead of tags_array and user can easily edit tags as comma separated list in a text field. tags_array is than usable everywhere tags should be processed as array one by one.

Now, let's have following code which initializes new Post:

post = Post.new(:tags => 'ruby,mongo_odm')

User (read "me" :) now expects that newly created post will have tags_array set to [ "ruby", "mongo_odm" ] but the truth is that tags_array will be empty. It's because both default and given values are processed at the same time and it depends on internal fields ordering in a attributes hash if tags will be set first and tags_array will than overwrite it with the default value or vice versa.

I'm not really sure, if MongoODM should take into account such special behavior as I'm pretty new to Ruby and Rails and maybe there are some prettier solutions for mentioned situation. I found the problem when I tried to port mongoid_taggable gem (easy and transparent tagging support for any document) from Mongoid to MongoODM.

What do you think about it?

carlosparamio commented 13 years ago

I think that you're right. It should use the default values just when no other values has been provided for the attribute, directly assigned with the attribute accessor or via a custom method like that "tags=" writer. Let's see if I can delay easily the assignment of default values at the end of the initialization.

michalkrause commented 13 years ago

Great, thank you very much :)