views:

52

answers:

2

So lets say I have a class like below

class List
  include DataMapper::Resource
  property :id, Serial  
  property :username, String

  def self.my_username
    return self[:username]
  end
end

list=List.create(:username=>,'jim')
list.my_username

When I run this it tells me that the method cannot be found, and on more investigation that you can only define class methods(not object methods) and that class methods don't have access to objects data.

Is there any way to have these methods included as object methods and get access to object data? I'm using Ruby 1.8.6 and the latest version of datamapper.

+3  A: 

Avoid all self and it become InstanceMethod :

class List
  include DataMapper::Resource
  property :id, Serial  
  property :username, String

  def my_username
    return self[:username]
  end
end

list=List.create(:username=>,'jim')
list.my_username
shingara
+2  A: 

You can think of the class scope as the Model (a table in an RDBMS) and of the instance scope as the Resource (a row in an RDBMS). Now if you define class methods (like you did with self.my_username) you are operating on the Model (aka the table, aka all rows). If you define instance methods, these will be available to a Resource(aka one row).

Typical usecases for class methods are to build up (chains of) query/ies. These will basically work to the same effect as Active Record's 2.x named_scope. You can call a chain of class methods and have it not execute a single query, as long as you don't explicitly access the data the query is supposed to provide. DataMapper will keep on constructing and modifying query objects till the very moment you actually need to access the data. This only works if every class method in the chain returns an instance of DataMapper::Collection which is typically achieved by returning the result of calls to all (or combining these with set operators like +, -, & and |.

snusnu