0

I have an Active Record model object called Event, which has many event_things. I want to be able to duplicate the event, so that it gets a new id. I'm using Rails 3.2 and in rails console am able to successfully call

event_copy = event.dup
event_copy.save

However, I also want to duplicate each of the Event's event_things.

copy = event_thing.dup
copy.event_id = event_copy.id
copy.save

But that gives me this error stack:

NoMethodError: undefined method `yaml' for nil:NilClass
    from /Users/Ed/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/psych.rb:204:in `dump_stream'
    from /Users/Ed/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/psych/core_ext.rb:35:in `psych_y'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:143:in `attribute_change'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `block in changes'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `map'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `changes'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/attribute_methods/dirty.rb:23:in `save'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:241:in `block (2 levels) in save'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:208:in `transaction'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:241:in `block in save'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:252:in `rollback_active_record_state!'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:240:in `save'
    from (irb):18
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands/console.rb:47:in `start'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands/console.rb:8:in `start'
    from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
4

2 回答 2

1

I ran into the same issue as this. It turns out that there's a Kernel.y extension method that is getting in your way, based on this article. Here is what I did to fix my problem:

class Event < ActiveRecord::Base
  # alias the attributes
  alias_attribute :x_pos, :x
  alias_attribute :y_pos, :y

  after_initialize :init

  # after_initialize will still work, with the aliases
  def init
    self.x_pos ||= 0
    self.y_pos ||= 0
  end

  # override Kernel.y
  def y; end

  # override self.y_pos to read out of the :attributes, since we blew away :y
  def y_pos
    attribute['y']
  end
end

After doing this, I was finally able to use my model without having to rename the y database column.

于 2013-06-28T22:29:38.047 回答
0

While I normally don't advocate using gems liberally, if you have a lot of relations that need to be preserved in the duplication, or find yourself doing these manual duplications a lot, take a look at deep_clonable.

As for your specific error, try surrounding each line of code with a nil check (one line at a time). I'm sure there's just some case where you're ending up with a nil object that you're overlooking.

于 2012-09-02T08:16:40.193 回答