RhinoLarva
RhinoLarva

Reputation: 805

Should I use DataMapper entities only for persistence purposes?

I'm creating a non-Rails application and using DataMapper as ORM.

For entities which will be mapped to SQL tables I declare classes which include DataMapper::Resource.

The question is. Is it okay to use the instances of these classes as plain objects (pass to methods, manipulate values etc.)? Or they should be used only for persisting data (for instance in Repository classes)?

I'm new in the Ruby world and do not know the conventions. If I have a User entity, which has methods creates, all etc., is it a good idea to create another class User, which only will store information (will have state - fields and no methods)? Analogue of POJO (Plain old java object) in Java?

Upvotes: 0

Views: 74

Answers (1)

max pleaner
max pleaner

Reputation: 26758

I can see creating a wrapper class for a plain object list having some benefits. As you mention in the comment, if you want to store data in different ways then writing distinct classes is useful.

For typical DataMapper or ActiveRecord usage, though, I don't think it's common to create wrapper classes for plain-object lists, especially if you're not adding any methods to the collection. The main reason why it's not common is that query results in ActiveRecord or DataMapper are array-like already. Additionally, you're not really gaining any added functionality by converting your model instances to hashes. Let me show some example:

# collections are array-like
User.all.map(&:name) == User.all.to_a.map(&:name)

# converting a record to a hash doesn't add much
user = User.first
user_hash = user.attributes 
user.name == user_hash[:name]

That being said, there is one caveat, and that has to do with chainable methods in the ORM:

# this is valid chaining
User.all.where(name: "max")

# this raises a NoMethodError for 'where'
User.all.to_a.where(name: "max")

where is a ORM method, not an array method. So if you convert the query result to an array you couldn't access it. For this reason, making a distinction between arrays and query collections is useful.

But how much benefit do you really get from creating an empty wrapper class?

class RecordsInMemory
  def initialize(query_collection)
    @list = query_collection.map(&:attributes)
  end
end
records_in_memory = RecordsInMemory.new(User.all)
records_in_memory.list.map(&:name)

# versus ...

records_in_memory = User.all.map(&:attributes)
records_in_memory.map(&:name)

if you think in the long run you will add methods to the plain-object list, then you should make it into a class. But otherwise I think using clearly-named variables suffices.

Upvotes: 0

Related Questions