Updating an item in an array key...

4 views
Skip to first unread message

Travis Bell

unread,
Oct 19, 2009, 1:20:33 AM10/19/09
to mongo...@googlegroups.com
Hey guys,

I swear I read through the docs I could find on this one, and as far as I can tell it's right but I have no idea why it won't save the new values I am trying to dump in:

class Test
   include MongoMapper::Document
   
   key :title, String
   key :_keywords, Array, :index => true
end

test = Test.first(:conditions => {:slug => id})
test._keywords << "test"
test.save

Yet test._keywords is the original value. If I inspect test before I save it, it has the new value in it, but the second I use .save, it reverts back to the original value.

Any ideas?

--
Travis Bell







Cyril Mougel

unread,
Oct 19, 2009, 4:43:05 AM10/19/09
to mongo...@googlegroups.com
Travis Bell a écrit :

Which version of MongoMapper ?
Maybe it's a dirty issue include in 0.5.x

--
Cyril Mougel
http://blog.shingara.fr/

Travis Bell

unread,
Oct 19, 2009, 10:45:10 AM10/19/09
to mongo...@googlegroups.com
Hi Cyril,

mongo (0.15.1)
mongo_ext (0.15.1)
mongo_mapper (0.5.5)


--
Travis Bell






John Nunemaker

unread,
Oct 19, 2009, 12:00:34 PM10/19/09
to mongo...@googlegroups.com
Not sure what your problem is. I'm not having any issues when doing the same thing:

class Test
  include MongoMapper::Document
  key :title, String
  key :_keywords, Array
end

test = Test.new
test._keywords = ['foo', 'bar', 'baz']
test.save
puts Test.find(test.id)._keywords.inspect # ['foo', 'bar', 'baz']

Travis Bell

unread,
Oct 19, 2009, 12:19:26 PM10/19/09
to mongo...@googlegroups.com
Hey John,

Thanks. The problem seems to be around using before_save:

class Test
   include MongoMapper::Document
   key :title, String
   key :_keywords, Array, :index => true
   before_save do |record|
      record._keywords = record.title.split(' ').uniq
   end
end

Sorry for not including that in my original example. This should not work for you:

class Test
   include MongoMapper::Document
   key :title, String
   key :_keywords, Array, :index => true
   before_save do |record|
      record._keywords = record.title.split(' ').uniq
   end
end

test = Test.create(:title => 'One Two')
test._keywords << "test"
test.save

So I suppose, my question is, what is it about the before_save that is preventing this from working?


--
Travis Bell






John Nunemaker

unread,
Oct 19, 2009, 12:22:38 PM10/19/09
to mongo...@googlegroups.com
I never use procs like that. I tend to go for a method which can reveal more intent of what you are doing. This works fine for me:

class Test
  include MongoMapper::Document
  key :title, String
  key :_keywords, Array, :index => true
  before_save :set_keywords_from_title
  
  private
    def set_keywords_from_title
      self._keywords = title.split(' ').uniq
    end
end

test = Test.create(:title => 'One Two')
test._keywords << "test"
test.save

puts Test.find(test.id)._keywords.inspect

Travis Bell

unread,
Oct 19, 2009, 12:27:50 PM10/19/09
to mongo...@googlegroups.com
I copied that code straight up and it does not work. 

Test.find(test.id)._keywords.inspect only contains:

["One", "Two"]


Strange eh?

John Nunemaker

unread,
Oct 19, 2009, 12:29:28 PM10/19/09
to mongo...@googlegroups.com
That us what it is suppose to contain. Isn't it? An array of keywords from the title? Or did I look at it wrong? 


Travis Bell

unread,
Oct 19, 2009, 12:32:01 PM10/19/09
to mongo...@googlegroups.com
Yes, but we're updating it with:

test._keywords << "test"

Aren't we?

Shouldn't it contain:

["One", "Two", "test"]

Or maybe it is me who is now confused… *blink-blink*

Roy Wright

unread,
Oct 19, 2009, 1:24:16 PM10/19/09
to mongo...@googlegroups.com
The problem is that the before_save is overwriting :_keywords.  What you probably want is:

def set_keywords_from_title
  if self._keywords.nil? || self.keywords.empty?
    self._keywords = title.split(' ').uniq
  end
end

HTH,
Roy

Roy Wright

unread,
Oct 19, 2009, 1:39:37 PM10/19/09
to mongo...@googlegroups.com
Sorry for following up my own post, but have a question regarding the callback I gave.  Does MM follow AR's standard where a return value of false will break the callback chain?  I.e., should the example callback be:

def set_keywords_from_title
  if self._keywords.nil? || self.keywords.empty?
    self._keywords = title.split(' ').uniq
  end
  true
end

TIA,
Roy

Travis Bell

unread,
Oct 19, 2009, 1:44:45 PM10/19/09
to mongo...@googlegroups.com
Damnit Roy.

Now that you mention it, that makes a whole lot of sense but damn, I didn't even come close to seeing it. Looking in the complete wrong area.


I owe you a beer.

Cheers man,

Roy Wright

unread,
Oct 19, 2009, 2:56:07 PM10/19/09
to mongo...@googlegroups.com
No problem.  Thank you for themoviedb.org which feeds my gentoo xbmc htpc.  ;)

Have fun,
Roy

John Nunemaker

unread,
Oct 20, 2009, 1:20:29 PM10/20/09
to mongo...@googlegroups.com
You don't have to return true. I think if you return false though it will stop the callbacks. Don't remember and too lazy to look. :) Will be switching to ActiveModel soon anyway. :)
Reply all
Reply to author
Forward
0 new messages