Comments (17)
@emmanuel I think you've mentioned in the past that subclassing Module is a little known, but powerful technique. Do you mind commenting on some specifics?
from virtus.
@hookercookerman you need to create an instance of that module subclass and include it then. For example:
class MyModule < Module
def foo
end
end
class A
include MyModule.new
end
A.new.foo
This technique is our small experiment that was started by @emmanuel. Subclassing modules allowed us to clean up various pieces of Virtus. The general idea is that a module subclass is aware of a special behavior that's required when the module gets included in a class. Previously we had a class that would include a module into something and perform other extra work - now we have a module that performs this work which results in better encapsulation. Or at least we think it does :)
I'm sure @emmanuel has more to say about this though
from virtus.
I remember @dkubb's answer to a similar question a few weeks ago: https://twitter.com/dkubb/status/211106940879781889
It made perfect sense to me at that time (and still does, in fact)
from virtus.
Thanks for the feedback having trouble running your example
I am using 1.9.3p194
class MyModule < Module
def foo
end
end
class A
include MyModule.new
end
A.new.foo
undefined method `foo' for #<A:0x007fbd8487c8c0> (NoMethodError)
from virtus.
@hookercookerman ugh. right - my bad. you'd have to define included
hook and extend/include other modules there if you want
In Virtus the attribute set is now a module subclass which knows how to define attribute readers and writes on a class that included it. I agree it looks weird because nobody is using such approach but I like how it cleaned up the code which makes me think it's a neat solution.
We'll see how it works - as I said we're experimenting with this approach :)
from virtus.
sorry on last thing; no worries if no as this is a bit out there;
I have 95% ported virtus to work with rubymotion; motion does not support subclassing of modules what would be the approach for attributeSet and Equalizer that you would implement if you did not have use of this feature; just enough info to send me down the right path would be cool
cheers
from virtus.
I keep looking at the source to try to untangle what is going on; if the subclass of a module cannot include methods that it defines; and the subclass itself does not have a self.included method that I cant see what it does; I am hoping for an epiphany moment.
I like to read code I can understand
I would like to understand this but I cannot; more ruby foo is required be me;
cheers
from virtus.
@hookercookerman it dynamically defines methods that's why there's no included
hook. See here
from virtus.
Every time you use the module
keyword to create a module (as opposed to reopening an existing module) Ruby creates an instance of the class Module
. The only state retained by a module created this way is the set of instance methods it holds that can be inserted into the method lookup chain via include
and extend
.
With a subclass of Module
, you are free to design the class so that instances of it (which are themselves modules) hold additional state beyond the set of instance methods. It gets a bit confusing when thinking about instances of a Module subclass having instance methods (defined in the class body, as usual), and holding instance methods.
So far it looks like this pattern is most useful when you would otherwise use an anonymous module (eg., using Module.new
), where the anonymous module has instance methods dynamically defined (eg., with define_method
or module_eval
).
AttributeSet
is the furthest that I've pushed the idea so far. In that case, AttributeSet
instances hold references to Attribute
instances and the methods to use them (getters & setters). Previously there were separate collection and module objects.
Hope that helps.
On Jul 26, 2012, at 4:30 AM, Piotr [email protected] wrote:
@hookercookerman it dynamically defines methods that's why there's no included hook. See here
Reply to this email directly or view it on GitHub:
#106 (comment)
from virtus.
super thanks for the reply really helps; I am like oooooh I see it now; so thats cool.
I always thought it was not even a feature
http://www.rubyist.net/~slagell/ruby/modules.html
I was really close to getting this library working on rubymotion (not easy); as I think it will really help with people creating mappers for core data and dealing with rest; just a good lib to work on top of basically;
but isubclassing a Module does not work in motion :( I tried to circumvent this but my head nearly exploded.
Cheers
from virtus.
@hookercookerman I'm happy to help you with this. Virtus used to have "a traditional" approach to this which means we used anonymous modules. I think it should be possible to build a compatibility layer for RubyMotion using same techniques as we used to have.
It would be a matter of using a separate strategy for attribute set and defining attribute accessors and a separate class for Equalizer - both would be only used in RubyMotion environment. This would mean using the previous version of AttributeSet class, overriding extended
and inherited
hooks so that they no longer include attribute_set module instance and falling back to using anonymous modules for defining accessors.
You can take a look at older versions of Virtus to see how we used anonymous modules to define attribute accessors.
I'm not sure how we should handle class loading. I guess you could remove AttributeSet and Equalizer constants and provide your own that will work with RubyMotion.
from virtus.
cheers you guys are helpful cool; I will give this a whirl and take a look at the older version; cheers
from virtus.
I'm going to mark this issue as closed.
from virtus.
Giving this another shot, for the record. I have the project up at this repository.
@hookercookerman is dead on - RubyMotion does not support subclassing of modules, and getting Virtus to work with it was not trivial. I have the project building correctly now (though there are still a few bugs I'm trying to squash). I'm temporarily using a workaround for the subclassing of modules, but I'll need to come up with a better solution shortly.
As a sidenote - that's a really clean approach. @solnic, I'd read your blog post, but it makes a lot more sense in the context of a project.
from virtus.
@rclosner do you know why RubyMotion doesn't support it? Is it not possible to implement?
from virtus.
@solnic i really don't know. it definitely recognizes the syntax as valid, but it could be that it's slated for later release. i'm only 3 days into RM... can't really speak authoritatively on the subject yet. :)
Everything appears to be in working order for motion_virtus, though. I have one more bug to fix with method visibility not working, then it should be good to go.
One thing I noticed (tangentially) is that coercible raises an error if it can't find the appropriate coercion method. While I think that's a better solution than returning the value (like it was before), it gets obnoxious when you're just trying to instantiate an empty object.
class User
include Virtus
attribute :name, String
end
User.new
#=> UnsupportedCoercion: Coercible::Coercer::Object#to_string doesn't know how to coerce nil.
Are you planning on adding a NilClass coercer, or will users have to handle this case manually?
from virtus.
@rclosner that's a bug please report
from virtus.
Related Issues (20)
- Publish 1.0.6
- Avoid override of previously assigned attributes
- Put link to dry-rb in README.md to save time for new comers
- possible to dynamically add attributes? HOT 1
- What replaces `ValueObject::InstanceMethods::with`?
- Class not getting initialized HOT 1
- Bug: nil default value of Array attribute ignored HOT 1
- Coerce proc and strict mode don't match
- Default values aren't assigned when initialize method is present. HOT 1
- Array of Array of FooClass
- Strange Boolean behaviour HOT 5
- Validation from class attributes
- Show Embedded value on edit form
- Calling methods inside of a Virtus::Attribute
- Mark as unmaintaned HOT 2
- Hash.try_convert(attributes) errors on params in Rails 5
- FixedWidth Coercion HOT 2
- Date formats HOT 1
- How can I use array of tags(Strings) in a key of a hash? HOT 1
- Strict mode only works for basic values HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from virtus.