Search code examples
rubyruby-datamapper

Ruby DataMapper: undefined method `include?'


I am trying an example on the page http://ruby.about.com/od/sinatra/a/datamapper.htm. I copied the following code from the web site:

require 'rubygems'
require 'dm-core'
require 'dm-migrations'

DataMapper.setup(:default, "sqlite3:///tmp/test1.db")

class Person
  include DataMapper::Resource

  property :firstname, String
  property :lastname, String
  property :email, String, :key => true
end

p = Person.new
p.attributes = {
  :firstname => 'John',
  :lastname => 'Doe',
  :email => '[email protected]'
}

Running this code by ruby test.rb, I got an error message

/usr/local/Cellar/ruby/2.0.0-p247/lib/ruby/gems/2.0.0/gems/dm-core-1.2.1/lib/dm-core/resource.rb:335:in `block in attributes=': undefined method `include?' for nil:NilClass (NoMethodError)
    from /usr/local/Cellar/ruby/2.0.0-p247/lib/ruby/gems/2.0.0/gems/dm-core-1.2.1/lib/dm-core/resource.rb:332:in `each'
    from /usr/local/Cellar/ruby/2.0.0-p247/lib/ruby/gems/2.0.0/gems/dm-core-1.2.1/lib/dm-core/resource.rb:332:in `attributes='
    from test.rb:16:in `<main>'

What am I doing wrong? Thanks.


Solution

  • I found the below code from dm-core / lib / dm-core / resource.rb.

    # Assign values to multiple attributes in one call (mass assignment)
    #
    # @param [Hash] attributes
    #   names and values of attributes to assign
    #
    # @return [Hash]
    #   names and values of attributes assigned
    #
    # @api public
    def attributes=(attributes)
      model = self.model
      attributes.each do |name, value|
        case name
        when String, Symbol
          if model.allowed_writer_methods.include?(setter = "#{name}=")
            __send__(setter, value)
          else
            raise ArgumentError, "The attribute '#{name}' is not accessible in #{model}"
          end
        when Associations::Relationship, Property
          self.persistence_state = persistence_state.set(name, value)
        end
      end
    end
    

    allowed_writer_methods is a reader, which has not been set. There could be several reason for not to set the variable @allowed_writer_methods to The list of writer methods that can be mass-assigned to in #attributes=. Out of those reason, you might not run auto_migrate! to drops and recreates the repository upwards to match model definitions. Thus run this method to see, if your code works or not.

    Regarding the error, yes it came from the line model.allowed_writer_methods.include?(setter = "#{name}="), as for the above said reason, allowed_writer_methods gives nil and Nilclass#include? method doesn't exist. That's the reason (NoMethodError) obvious.