Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make mappers friendlier to Structs, etc #41

Open
jgaskins opened this issue Jan 21, 2014 · 3 comments
Open

Make mappers friendlier to Structs, etc #41

jgaskins opened this issue Jan 21, 2014 · 3 comments

Comments

@jgaskins
Copy link
Owner

We assume that object state is stored in instance variables, so we don't go in via accessor methods — using accessor methods might modify state, trigger API calls, etc. Using instance variables means that your mappers have intimate knowledge of your models, but your models can remain completely oblivious to the mapper.

However, sometimes when you want to hammer out a quick proof of concept, you use a Struct instead of defining a class. Structs don't store their state into instance variables:

2.0.0p247 :004 > Boy = Struct.new(:name)
2.0.0p247 :007 > Boy.new('Sue').instance_variables
 => []

I'm not sure I want to make Structs a special case, but I'm open to ideas on how to use accessor methods instead of ivars.

@acook
Copy link

acook commented Feb 27, 2014

I can see the advantage of going in, expecting values to be stored in instance variables, but there's plenty of cases where that wouldn't be enough, Struct just being one example.

Perhaps something like this for both methods and generic operations:

Perpetuity.generate_mapper_for Article do
  attribute :title, accessor: :title
  attribute :body,  via: lambda{|article| article.content(:unescaped) }
end

I'd see the individual methods implemented before the lambda.

@jgaskins
Copy link
Owner Author

Yep. It'd be pretty nice to have other options to store/retrieve attributes. I like the ivars as the default (since I'd bet that's the most common). I originally thought about passing blocks instead of lambdas:

Perpetuity.generate_mapper_for Article do
  attribute :title do |article|
    article.title
  end
  # ... or ...
  attribute(:title) { |article| article.title }
end

Aesthetically, I'm not sure I like either one of these, though. Using do/end on separate lines breaks up the declarations. Using parentheses to override precedence for the curly-brace block would make it look different from other lines.

Also, it wouldn't account for storing the attributes. Something like the :accessor attribute would take care of that, but if we pass in procs, blocks, or lambdas (oh my) we'll need to allow two different ones to allow for deserialization as well as serialization.

Perpetuity.generate_mapper_for Article do
  attribute :body, reader: proc { |article| article.title }, writer: proc { |article, value| article.title = value }
end

The upside of something like this is that we can get rid of the hardcoded instance variable access and supply default procs instead (which technically would still hardcode the instance variable access, but at least it'd be overridable :-)).

@jgaskins
Copy link
Owner Author

Hmm … It seems some of the things I mentioned here might conflict with what we've discussed in #15. Maybe using procs might not be a good idea and we should stick to letting users specify whether to use ivars or accessor methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants