moosex 0.0.19 → 0.0.20

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f6ba383dda20e87558daa2dd8725a8807ff893c1
4
- data.tar.gz: ea4c39f097690433c3961b744c375a9ecd94a6b0
3
+ metadata.gz: 81a1d69a0ea74ca118361a16b549201215fd255e
4
+ data.tar.gz: 562b285c934e2e1a798c89b4ff02afd9af4c3754
5
5
  SHA512:
6
- metadata.gz: d9f697fe80bafb7713e5375ac38a08a79de809fff7805cabb10a4e2c7e6f362d9513239b4463deb75cdd19f6d7a52dc3093af03d2567575cdc831ab07fadf12a
7
- data.tar.gz: f722f87f1cf89779e44cffdbc89c550a4ffeb8c3b6120dc8f4392d46c9eda901567239f86a6503f913a3ef4bbc6284e717a95b748f2bdddc0ceac3b94a6fea7d
6
+ metadata.gz: a68c128bb6fffdcb6c50eb174d486e963919e031c111ffe537f89a517fda547e62180abfcf96a096c310790b48fe5759e2cb2846745ef7267f94f30bf9fd5fbf
7
+ data.tar.gz: 31fa71baa921d302d7603197e6dca60c0f423064e9e2eccfcab0d47f3bf463a88a2343e28979c5ea89021a40d6815cda02b4218e31c7f317ed375b62006f45ad
data/Changelog CHANGED
@@ -1,3 +1,7 @@
1
+ 0.0.20 - 2014-02-16
2
+ - add plugins Chained and ExpiredAttribute #76
3
+ - remove experimental traits, add Expire
4
+
1
5
  0.0.19 - 2014-02-14
2
6
  - improvements in examples and internals
3
7
  - add basic suport to traits #24
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- moosex (0.0.19)
4
+ moosex (0.0.20)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -5,6 +5,8 @@ A postmodern object DSL for Ruby [![Build Status](https://travis-ci.org/peczenyj
5
5
 
6
6
  This is another DSL for object creation, aspects, method delegation and much more. It is based on Perl Moose and Moo, two important modules who add a better way of Object Orientation development (and I enjoy A LOT). Using a declarative style, using Moose/Moo you can create attributes, methods, the entire constructor and much more. But I can't find something similar in Ruby world, so I decide port a small subset of Moose to create a powerfull DSL for object construction.
7
7
 
8
+ Want to help? Install the gem `moosex` and start to use. If you find some issue, please assign to me :)
9
+
8
10
  Of course, there is few similar projects in ruby like
9
11
 
10
12
  - [Virtus](https://github.com/solnic/virtus)
@@ -12,9 +14,10 @@ Of course, there is few similar projects in ruby like
12
14
 
13
15
  But the objetive of MooseX is different: this is a toolbox to create Classes based on DSL, with unique features like
14
16
 
15
- - method delegation ( see 'handles')
17
+ - method delegation and currying ( see 'handles')
16
18
  - lazy attributes
17
- - roles
19
+ - roles / abstract classes / interfaces
20
+ - traits / monads
18
21
  - parameterized roles
19
22
  - composable type check
20
23
  - events
@@ -32,7 +35,9 @@ This rubygem is based on this modules:
32
35
  See also:
33
36
  - [Reindeer](https://github.com/broquaint/reindeer), another Moose port to Ruby (still on 0.0.1 version)
34
37
  - [Joose](https://code.google.com/p/joose-js/), a javascript port of Moose.
35
- - [Perl 6](http://en.wikipedia.org/wiki/Perl_6#Object-oriented_programming) Perl 6 OO programming style.
38
+ - [Perl 6](http://en.wikipedia.org/wiki/Perl_6#Object-oriented_programming), Perl 6 OO programming style.
39
+ - [Elk](http://frasertweedale.github.io/elk/), Elk is an object system for Python inspired by Moose.
40
+
36
41
 
37
42
  Why MooseX? Because the namespace MooseX/MooX is open to third-party projects/plugins/extensions. You can upgrade your Moo(se) class using other components if you want. And there is one gem called 'moose' :/
38
43
 
@@ -490,9 +495,9 @@ Optional.
490
495
 
491
496
  If you need override one attribute, you should use `override: true`, or MooseX will raise one exception.
492
497
 
493
- ### traits => Trait|[Array of Traits]
498
+ ### traits => Trait | [Array of Traits]
494
499
 
495
- The objective of use traits is extends the original attribute, using delegators. We support few traits at this moment and, **Important**, if you set a list of Traits we will apply each trait in sequence. Have a Suggestion? Open an Issue on Github!
500
+ The objective of use traits is extends the original attribute, using delegators (think in Monads). We support few traits at this moment and, **Important**, if you set a list of Traits we will apply each trait in sequence. Have a Suggestion? Open an Issue on Github!
496
501
 
497
502
  #### Trait Counter
498
503
 
@@ -554,30 +559,37 @@ Sometimes we need store an array of fixed size and each element has an identity.
554
559
 
555
560
  We store surname and name as a tuple of Strings. Instead access `array_with_surname_name[0]` or `array_with_surname_name[1]`, we can apply the Trait `Pair`, and access (or save!) each component of this pair, but you can't change the pair itself. Look the example of currying in `surname_and_name`, calling join with "," as an argument.
556
561
 
557
- #### Trait RescueToNil
562
+ #### Trait Expires
558
563
 
559
- The objective of `MooseX::Traits::RescueToNil` is avoid `NoMethodError` if, for example, you set nil as value. For example:
564
+ This trait will wrap the original value and set one expiration time (in seconds, -1 to never expires). Accepts one tuple (array) of [ value, expiration ].
560
565
 
561
566
  ```ruby
562
- has important: {
567
+ requires 'moosex'
568
+ requires 'moosex/traits'
569
+
570
+ class MyHomePage
571
+ include MooseX
572
+ has session: {
563
573
  is: :rw,
564
- default: 0,
565
- traits: MooseX::Traits::RescueToNil,
566
- handles: {
567
- plus: :+,
568
- minus: :-,
569
- }
574
+ default: -> { {} },
575
+ coerce: ->(value) { ((value.is_a?(Array))? value : [value, 3]) },
576
+ traits: MooseX::Traits::Expires,
570
577
  }
571
- ```
572
- Imagine you can accept nil as a valid value. In this case, you can't use `+` or `-`, right? It will raise a NoMethodError. Well... you can avoid this with RescueToNil trait. Using this, we will return `nil` for each operation in case of NoMethodError, and raise other kinds of exceptions.
573
-
574
- #### Trait RescueToZero
575
-
576
- Similar to RescueToNil, but return 0 in case of `NoMethodError`.
578
+ end
577
579
 
578
- #### Trait RescueToEmptyString
580
+ page = MyHomePage.new
581
+ page.session.valid? # => true
582
+ page.session # => {}
583
+ sleep(3)
584
+ page.session.valid? # => false
585
+ page.session= { bar: 5 } # will be coerce to [ {bar: 5}, 3 ]
586
+ page.session.valid? # => true
587
+ page.session # => { bar: 5 }
588
+ sleep(3)
589
+ page.session.valid? # => false
590
+ ```
579
591
 
580
- Similar to RescueToNil, but return empty string "" in case of `NoMethodError`.
592
+ See plugin "ExpiredAttribute" for a more clean interface (without this ugly coerce)!
581
593
 
582
594
  ##### Create your own trait
583
595
 
@@ -603,47 +615,108 @@ module MooseX
603
615
  ```
604
616
  You can create or extend your own Traits too. It is easy.
605
617
 
606
- ##### Composable Traits
618
+ #### Traits Removed
619
+
620
+ **IMPORTANT** RescueToNil, RescueToZero and RescueToEmptyString traits are removed since 0.0.20 version
607
621
 
608
- It is easy compose traits, for example:
622
+ ## Plugins
623
+
624
+ You can extend MooseX using Plugins, and you can create your own plugins. The only kind of plugin supported is `attribute plugin`, but we can accept other kinds of plugins in the future. To enable one ( or more ) plugins you should specify the list of plugins in the init method when you include the MooseX module.
625
+
626
+ ### Plugin Chained
627
+
628
+ The original behavior of the writter method is return the attribute value. If you want return `self` to continue calling other methods - to create one fluent interface, for example - you can use the plugin `MooseX::Plugins::Chained` and avoid writters with = in the end. For example:
609
629
 
610
630
  ```ruby
611
- class ComplexExample
612
- include MooseX
613
- include MooseX::Types
631
+ require 'moosex'
632
+ require 'moosex/plugins'
633
+
634
+ class EmailMessage
635
+ include MooseX.init(
636
+ with_plugins: MooseX::Plugins::Chained
637
+ )
638
+ has :_from, writter: :from, chained: true
639
+ has :_to, writter: :to, chained: true
640
+ has :_subject, writter: :withSubject, chained: true
641
+ has :_body , writter: :withBody, chained: true
642
+
643
+ def send!
644
+ # add logic
645
+ end
646
+ end
614
647
 
615
- has surname_name: {
616
- is: :rw,
617
- isa: isMaybe(isTuple(String, String)),
618
- default: nil,
619
- traits: [ MooseX::Traits::RescueToEmptyString, MooseX::Traits::Pair ],
620
- handles: {
621
- surname: :first,
622
- name: :second,
623
- :surname= => :first=,
624
- :name= => :second=,
625
- surname_and_name: { join: ->{", "} }
626
- }
648
+ EmailMessage.new.
649
+ from("foo@bar.com").
650
+ to("me@baz.com").
651
+ withSubject("test").
652
+ withBody("hi!").
653
+ send!
654
+ ```
655
+
656
+ ### Plugin ExpiredAttribute
657
+
658
+ It is a easy way to apply the trait Expired in lazy attributes!
659
+
660
+ ```ruby
661
+ require 'moosex'
662
+ require 'moosex/plugins'
663
+
664
+ class MyClass
665
+ include MooseX.init(with_plugins: MooseX::Plugins::ExpiredAttribute)
666
+
667
+ has config: {
668
+ is: :lazy,
669
+ clearer: true, # mandatory
670
+ expires: 60, # seconds
627
671
  }
672
+
673
+ def build_config
674
+ # read configuration...
675
+ end
676
+ end
628
677
  ```
629
- First, we apply `RescueToEmptyString`, then `Pair`. In this case, if you set `nil`, name and surname will act as empty string values. For example:
678
+
679
+ Instead force a coerce to a tuple, here we use a `expires` keyword. You need enable the clearer to read the configuration, in this case.
680
+
681
+ ### Build your own Plugin
682
+
683
+ You should create one Class who accepts one parameter in the constructor (it is a reference for the MooseX::Attribute class) and one method 'process' who will be invoked against the argument hash ( in the constructor ). The reference for the attribute can be used to change the original behavoir and you must delete the used arguments from the hash (in process). See the file `lib/moosex/plugins.rb` for more examples.
630
684
 
631
685
  ```ruby
632
- ce = ComplexExample.new(surname_name: nil)
633
- ce.name # => ""
634
- ce.surname_and_name # => ", "
635
-
636
- ce.name= "Isaac"
637
- ce.surname_and_name # => ", Isaac"
638
- ce.surname= "Asimov"
639
- ce.surname_and_name # => "Asimov, Isaac"
640
-
641
- ce.surname_name= nil
642
- ce.name # => ""
643
- ce.surname_and_name # => ", "
686
+ module MooseX
687
+ module Plugins
688
+ class Chained
689
+ def initialize(this)
690
+ @this = this
691
+ end
692
+ def process(options)
693
+ chained = !! options.delete(:chained)
694
+
695
+ if chained
696
+ writter = @this.attribute_map[:writter]
697
+ old_proc = @this.methods[ writter ]
698
+ @this.methods[writter] = ->(this, value) { old_proc.call(this, value); this }
699
+ end
700
+
701
+ @this.attribute_map[:chained] = chained
702
+ end
703
+ end
704
+ ...
644
705
  ```
645
706
 
646
- In this example it is safe set nil to `surname_name`. when we try to create the Pair, the [0] and [1] calls will return "", and we have one pair ["", ""]. This is why we add RescueToEmptyString first. If we use Pair as first trait, Pair expects an array, not a nil. *The Order is Important*.
707
+ **Important** the public API for MooseX::Attribute is under development and can change in any moment. This will be true until the first stable release.
708
+
709
+ ### Enable more than one plugin
710
+
711
+ You can pass the list of plugins as an array.
712
+
713
+ ```ruby
714
+ require 'moosex'
715
+ require 'moosex/plugins'
716
+
717
+ class MyClass
718
+ include MooseX.init(with_plugins: [ MooseX::Plugins::ExpiredAttribute, MooseX::Plugins::Chained ])
719
+ ```
647
720
 
648
721
  ## Hooks: after/before/around
649
722
 
@@ -665,9 +738,7 @@ class Point3D < Point
665
738
 
666
739
  has z: { is: :rw, required: true }
667
740
 
668
- after :clear! do |object|
669
- object.z = 0
670
- end
741
+ after :clear! ->(this) { this.z = 0 }
671
742
  end
672
743
  ```
673
744
 
@@ -697,10 +768,10 @@ class Point
697
768
  # do something
698
769
  end
699
770
 
700
- before :my_method do |this, x|
771
+ before :my_method ->(this, x) do
701
772
  puts "#{Time.now} before my_method(#{x})"
702
773
  end
703
- after :my_method do |this, x|
774
+ after :my_method ->(this, x) do
704
775
  puts "#{Time.now} after my_method(#{x})"
705
776
  end
706
777
  end
@@ -711,7 +782,7 @@ end
711
782
  The around hook is agressive: it will substitute the original method for a lambda. This lambda will receive the original method as a lambda, a reference for the object and the argument list, you shuld call the method_lambda using object + arguments
712
783
 
713
784
  ```ruby
714
- around(:sum) do |method_lambda, this, a,b,c|
785
+ around(:sum) ->(method_lambda, this, a,b,c) do
715
786
  c = 0
716
787
  result = method_lambda.call(this,a,b,c)
717
788
  result + 1
@@ -967,8 +1038,8 @@ Parameterized roles is a good way of reuse code based on roles. For example, to
967
1038
  module EasyCrud
968
1039
  include MooseX
969
1040
 
970
- on_init do |*attributes|
971
- attributes.each do | attr |
1041
+ on_init ->(*attributes) do
1042
+ attributes.each ->(attr) do
972
1043
  has attr, { is: :rw, predicate: "has_attr_#{attr}_or_not?" }
973
1044
  end
974
1045
  end
@@ -989,7 +1060,7 @@ To combine one or more parameterized roles to another parameterized role you sho
989
1060
  module Logabble2
990
1061
  include MooseX
991
1062
 
992
- on_init do |args|
1063
+ on_init ->(args) do
993
1064
  args[:klass] = self
994
1065
  include Logabble.init(args)
995
1066
  end
@@ -998,7 +1069,7 @@ end
998
1069
  module Logabble
999
1070
  include MooseX
1000
1071
 
1001
- on_init do | args |
1072
+ on_init ->(args) do
1002
1073
 
1003
1074
  klass = args[:klass] || self # <= THIS will guarantee you will
1004
1075
  methods = args[:methods] || [] # modify the right class
@@ -1082,11 +1153,11 @@ end
1082
1153
 
1083
1154
  e = Example.new
1084
1155
 
1085
- e.on(:pinged) do |object|
1156
+ e.on(:pinged) ->(this) do
1086
1157
  puts "Ping!"
1087
1158
  end
1088
1159
 
1089
- e.once(:pinged) do |object|
1160
+ e.once(:pinged) ->(this) do
1090
1161
  puts "Ping Once!"
1091
1162
  end
1092
1163
 
@@ -1099,7 +1170,7 @@ e.ping # will no longer print nothing
1099
1170
 
1100
1171
  # you can use arguments
1101
1172
  # consider you have one logger attribute in this example
1102
- listener = e.on(:error) do |obj, message|
1173
+ listener = e.on(:error) ->(obj, message) do
1103
1174
  obj.logger.fatal("Error: #{message}")
1104
1175
  end
1105
1176
 
@@ -1147,11 +1218,11 @@ end
1147
1218
 
1148
1219
  ep = EventProcessor.new()
1149
1220
 
1150
- ep.on_ping do |obj|
1221
+ ep.on_ping ->(obj) do
1151
1222
  puts "receive ping!"
1152
1223
  end
1153
1224
 
1154
- ep.on_pong do |obj, message|
1225
+ ep.on_pong ->(obj, message) do
1155
1226
  puts "receive pong with #{message}!"
1156
1227
  end
1157
1228
 
@@ -15,6 +15,7 @@ require "moosex/traits"
15
15
  require "weakref"
16
16
 
17
17
  module MooseX
18
+ @@PLUGINS = []
18
19
  @@ALIAS = nil
19
20
  @@MOOSEX_WARNINGS = true
20
21
  @@MOOSEX_FATAL = false
@@ -40,6 +41,10 @@ module MooseX
40
41
  @@ALIAS = (args[:meta].is_a?(TrueClass))? :meta : args[:meta]
41
42
  end
42
43
 
44
+ if args.has_key?(:with_plugins)
45
+ @@PLUGINS = [ args[:with_plugins] ].flatten
46
+ end
47
+
43
48
  self
44
49
  end
45
50
 
@@ -62,6 +67,11 @@ module MooseX
62
67
  unless class_or_module.respond_to? :__moosex__meta
63
68
  meta = MooseX::Meta.new
64
69
 
70
+ @@PLUGINS.each do |plugin|
71
+ meta.add_plugin(plugin)
72
+ end
73
+ @@PLUGINS = []
74
+
65
75
  class_or_module.define_singleton_method(:__moosex__meta) { meta }
66
76
 
67
77
  if @@ALIAS
@@ -15,24 +15,24 @@ module MooseX
15
15
  def default ; @attribute_map[:default] ; end
16
16
 
17
17
  @@LIST_OF_PARAMETERS = [
18
- [:is, MooseX::AttributeModifiers::Is.new ],
19
- [:isa, MooseX::AttributeModifiers::Isa.new ],
20
- [:default, MooseX::AttributeModifiers::Default.new ],
21
- [:required, MooseX::AttributeModifiers::Required.new ],
22
- [:predicate, MooseX::AttributeModifiers::Predicate.new],
23
- [:clearer, MooseX::AttributeModifiers::Clearer.new ],
24
- [:traits, MooseX::AttributeModifiers::Traits.new ],
25
- [:handles, MooseX::AttributeModifiers::Handles.new ],
26
- [:lazy, MooseX::AttributeModifiers::Lazy.new ],
27
- [:reader, MooseX::AttributeModifiers::Reader.new ],
28
- [:writter, MooseX::AttributeModifiers::Writter.new ],
29
- [:builder, MooseX::AttributeModifiers::Builder.new ],
30
- [:init_arg, MooseX::AttributeModifiers::Init_arg.new ],
31
- [:trigger, MooseX::AttributeModifiers::Trigger.new ],
32
- [:coerce, MooseX::AttributeModifiers::Coerce.new ],
33
- [:weak, MooseX::AttributeModifiers::Weak.new ],
34
- [:doc, MooseX::AttributeModifiers::Doc.new ],
35
- [:override, MooseX::AttributeModifiers::Override.new ],
18
+ [:is, MooseX::AttributeModifiers::Is ],
19
+ [:isa, MooseX::AttributeModifiers::Isa ],
20
+ [:default, MooseX::AttributeModifiers::Default ],
21
+ [:required, MooseX::AttributeModifiers::Required ],
22
+ [:predicate, MooseX::AttributeModifiers::Predicate],
23
+ [:clearer, MooseX::AttributeModifiers::Clearer ],
24
+ [:traits, MooseX::AttributeModifiers::Traits ],
25
+ [:handles, MooseX::AttributeModifiers::Handles ],
26
+ [:lazy, MooseX::AttributeModifiers::Lazy ],
27
+ [:reader, MooseX::AttributeModifiers::Reader ],
28
+ [:writter, MooseX::AttributeModifiers::Writter ],
29
+ [:builder, MooseX::AttributeModifiers::Builder ],
30
+ [:init_arg, MooseX::AttributeModifiers::Init_arg ],
31
+ [:trigger, MooseX::AttributeModifiers::Trigger ],
32
+ [:coerce, MooseX::AttributeModifiers::Coerce ],
33
+ [:weak, MooseX::AttributeModifiers::Weak ],
34
+ [:doc, MooseX::AttributeModifiers::Doc ],
35
+ [:override, MooseX::AttributeModifiers::Override ],
36
36
  ]
37
37
 
38
38
  def initialize(attr_symbol, options ,klass)
@@ -40,24 +40,23 @@ module MooseX
40
40
  @attribute_map = {}
41
41
 
42
42
  init_internal_modifiers(options.clone, klass.__moosex__meta.plugins, klass)
43
-
44
- generate_all_methods
45
43
  end
46
-
44
+
47
45
  def init_internal_modifiers(options, plugins, klass)
48
46
  @@LIST_OF_PARAMETERS.each do |tuple|
49
- parameter, obj = tuple
50
- @attribute_map[parameter] = obj.process(options, @attr_symbol)
47
+ parameter, k = tuple
48
+ @attribute_map[parameter] = k.new(self).process(options, @attr_symbol)
51
49
  end
52
50
 
53
- plugins.sort.uniq.each do |key|
54
- begin
55
- klass = MooseX::AttributeModifiers::ThirdParty.const_get(key.to_s.capitalize.to_sym)
56
- @attribute_map[key.to_sym] = klass.new.process(options, @attr_symbol)
51
+ generate_all_methods
52
+
53
+ plugins.sort.uniq.each do |plugin_klass|
54
+ begin
55
+ plugin_klass.new(self).process(options)
57
56
  rescue NameError => e
58
57
  next
59
58
  rescue => e
60
- raise "Unexpected Error in #{key} #{@attr_symbol}: #{e}"
59
+ raise "Unexpected Error in #{klass} #{key} #{@attr_symbol}: #{e}"
61
60
  end
62
61
  end
63
62
 
@@ -77,15 +76,15 @@ module MooseX
77
76
 
78
77
  inst_variable_name = "@#{@attr_symbol}".to_sym
79
78
  if @attribute_map[:predicate]
80
- @methods[@attribute_map[:predicate]] = Proc.new do
81
- instance_variable_defined? inst_variable_name
79
+ @methods[@attribute_map[:predicate]] = ->(this) do
80
+ this.instance_variable_defined? inst_variable_name
82
81
  end
83
82
  end
84
83
 
85
84
  if @attribute_map[:clearer]
86
- @methods[@attribute_map[:clearer]] = Proc.new do
87
- if instance_variable_defined? inst_variable_name
88
- remove_instance_variable inst_variable_name
85
+ @methods[@attribute_map[:clearer]] = ->(this) do
86
+ if this.instance_variable_defined? inst_variable_name
87
+ this.remove_instance_variable inst_variable_name
89
88
  end
90
89
  end
91
90
  end
@@ -103,25 +102,25 @@ module MooseX
103
102
 
104
103
  @methods[method] = generate_handles_with_currying(delegator, original_method, currying)
105
104
  else
106
- @methods[method] = Proc.new do |*args, &proc|
107
- delegator.call(self).__send__(target_method, *args, &proc)
105
+ @methods[method] = Proc.new do |this, *args, &proc|
106
+ delegator.call(this).__send__(target_method, *args, &proc)
108
107
  end
109
108
  end
110
109
  end
111
110
  end
112
111
 
113
112
  def generate_handles_with_currying(delegator, original_method, currying)
114
- Proc.new do |*args, &proc|
113
+ Proc.new do |this, *args, &proc|
115
114
 
116
115
  a1 = [ currying ]
117
116
 
118
117
  if currying.is_a?Proc
119
- a1 = currying.call()
118
+ a1 = currying[]
120
119
  elsif currying.is_a? Array
121
- a1 = currying.map{|c| (c.is_a?(Proc)) ? c.call : c }
120
+ a1 = currying.map{|c| (c.is_a?(Proc)) ? c[] : c }
122
121
  end
123
122
 
124
- delegator.call(self).__send__(original_method, *a1, *args, &proc)
123
+ delegator.call(this).__send__(original_method, *a1, *args, &proc)
125
124
  end
126
125
  end
127
126
 
@@ -153,8 +152,7 @@ module MooseX
153
152
  inst_variable_name = "@#{@attr_symbol}".to_sym
154
153
  object.instance_variable_set inst_variable_name, value
155
154
  end
156
-
157
- private
155
+
158
156
  def generate_reader
159
157
  inst_variable_name = "@#{@attr_symbol}".to_sym
160
158
 
@@ -168,7 +166,7 @@ module MooseX
168
166
  traits = @attribute_map[:traits]
169
167
  before_get = ->(object) do
170
168
  return if object.instance_variable_defined? inst_variable_name
171
-
169
+
172
170
  value = builder.call(object)
173
171
  value = coerce.call(value)
174
172
  type_check.call( value )
@@ -179,9 +177,9 @@ module MooseX
179
177
  end
180
178
  end
181
179
 
182
- -> do
183
- before_get.call(self)
184
- instance_variable_get inst_variable_name
180
+ ->(this) do
181
+ before_get.call(this)
182
+ this.instance_variable_get inst_variable_name
185
183
  end
186
184
  end
187
185
 
@@ -202,13 +200,13 @@ module MooseX
202
200
  type_check = protect_isa(@attribute_map[:isa], "isa check for #{writter_name}")
203
201
  trigger = @attribute_map[:trigger]
204
202
  traits = @attribute_map[:traits]
205
- Proc.new do |value|
203
+ ->(this, value) do
206
204
  value = coerce.call(value)
207
205
  type_check.call( value )
208
- trigger.call(self,value)
206
+ trigger.call(this,value)
209
207
  value = traits.call(value)
210
- instance_variable_set inst_variable_name, value
208
+ this.instance_variable_set inst_variable_name, value
211
209
  end
212
- end
210
+ end
213
211
  end
214
212
  end
@@ -3,6 +3,9 @@ module MooseX
3
3
  module ThirdParty
4
4
  end
5
5
  module AttrBaseModifier
6
+ def initialize(attrs)
7
+ @attrs=attrs
8
+ end
6
9
  def process(options, attr_symbol)
7
10
  @attr_symbol = attr_symbol
8
11
 
@@ -289,10 +292,9 @@ module MooseX
289
292
  def coerce(traits,f)
290
293
  original = ->(value) { value }
291
294
 
292
- [ traits ].flatten.inject(original) do |inner, trait|
295
+ [traits].flatten.inject(original) do |inner, trait|
293
296
  ->(value) { trait.new inner.call value }
294
297
  end
295
-
296
298
  end
297
299
  def validate(traits,f)
298
300
  # TODO
@@ -99,8 +99,10 @@ module MooseX
99
99
  end
100
100
 
101
101
  def __moosex__create_methods(attr)
102
- attr.methods.each_pair do |method, proc|
103
- define_method method, &proc
102
+ attr.methods.each_pair do |method, block|
103
+ define_method method do |*args|
104
+ block.call(self, *args)
105
+ end
104
106
  end
105
107
 
106
108
  if attr.is.eql?(:rwp)
@@ -117,7 +117,7 @@ module MooseX
117
117
  end
118
118
 
119
119
  def add_plugin(plugin)
120
- @plugins << plugin.to_sym
120
+ @plugins << plugin
121
121
  end
122
122
 
123
123
  private
@@ -0,0 +1,63 @@
1
+ module MooseX
2
+ module Plugins
3
+ class Chained
4
+ def initialize(this)
5
+ @this = this
6
+ end
7
+ def process(options)
8
+ chained = !! options.delete(:chained)
9
+
10
+ if chained
11
+ writter = @this.attribute_map[:writter]
12
+ old_proc = @this.methods[ writter ]
13
+ @this.methods[writter] = ->(this, value) { old_proc.call(this, value); this }
14
+ end
15
+
16
+ @this.attribute_map[:chained] = chained
17
+ end
18
+ end
19
+
20
+ class ExpiredAttribute
21
+ def initialize(this)
22
+ @this = this
23
+ end
24
+ def process(options)
25
+ expires = options.delete(:expires) || nil
26
+
27
+ if expires
28
+ lazy = @this.attribute_map[:lazy]
29
+ clearer = @this.attribute_map[:clearer]
30
+ predicate = @this.attribute_map[:predicate]
31
+ reader = @this.attribute_map[:reader]
32
+ writter = @this.attribute_map[:writter]
33
+
34
+ old_traits= @this.attribute_map[:traits]
35
+
36
+ @this.attribute_map[:traits] = ->(this) do
37
+ MooseX::Traits::Expires.new([ old_traits.call(this), expires ])
38
+ end
39
+
40
+ if reader && clearer && lazy
41
+ reader_proc = @this.generate_reader
42
+ @this.methods[reader] = ->(this) do
43
+ x = reader_proc.call(this)
44
+ unless x.valid?
45
+ this.__send__(clearer)
46
+ x = reader_proc.call(this)
47
+ end
48
+ x
49
+ end
50
+ elsif reader
51
+ @this.methods[reader] = @this.generate_reader
52
+ end
53
+ if writter
54
+ @this.methods[writter] = @this.generate_writter
55
+ end
56
+ end
57
+
58
+ @this.attribute_map[:expires] = expires
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -2,6 +2,21 @@ require 'delegate'
2
2
 
3
3
  module MooseX
4
4
  module Traits
5
+ class Expires < SimpleDelegator
6
+ def initialize(args)
7
+ value, expires = args[0], args[1]
8
+ @value = value
9
+ @expires = ((expires >= 0)? Time.now + expires : nil)
10
+
11
+ __setobj__(@value)
12
+ end
13
+
14
+ def valid?
15
+ return true if @expires.nil?
16
+ @expires > Time.now
17
+ end
18
+ end
19
+
5
20
  class Counter < SimpleDelegator
6
21
  def initialize(value)
7
22
  @value = value
@@ -73,43 +88,6 @@ module MooseX
73
88
  def value
74
89
  ! self.not
75
90
  end
76
- end
77
-
78
- class RescueToNil < SimpleDelegator
79
-
80
- def initialize(value)
81
- @value = value
82
- @default_value = -> { nil }
83
- __setobj__(@value)
84
- end
85
-
86
- def method_missing(m, *args, &block)
87
- begin
88
- super(m, *args, &block)
89
- rescue NoMethodError
90
- @default_value.call
91
- rescue Exception
92
- raise
93
- end
94
- end
95
91
  end
96
-
97
- class RescueToZero < RescueToNil
98
-
99
- def initialize(value)
100
- super(value)
101
- @default_value = ->{ 0 }
102
- end
103
-
104
- end
105
-
106
- class RescueToEmptyString < RescueToNil
107
-
108
- def initialize(value)
109
- super(value)
110
- @default_value = -> { "" }
111
- end
112
-
113
- end
114
- end
92
+ end
115
93
  end
@@ -1,3 +1,3 @@
1
1
  module MooseX
2
- VERSION = "0.0.19"
2
+ VERSION = "0.0.20"
3
3
  end
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Tiago Peczenyj"]
10
10
  spec.email = ["tiago.peczenyj@gmail.com"]
11
11
  spec.summary = %q{A postmodern object DSL for Ruby}
12
- spec.description = %q{MooseX is an extension of Ruby object DSL. The main goal of MooseX is to make Ruby Object Oriented programming easier, more consistent, and less tedious. With MooseX you can think more about what you want to do and less about the mechanics of OOP. It is a port of Moose/Moo from Perl to Ruby world.}
12
+ spec.description = %q{MooseX is an extension of Ruby object DSL. The main goal of MooseX is to make Ruby Object Oriented programming easier, more consistent, and less tedious. With MooseX you can think more about what you want to do and less about the mechanics of OOP. It is a port of Moose/Moo from Perl to Ruby world, providing method delegation, type check, monads, lazy attributes, aspects and much more.}
13
13
  spec.homepage = "http://github.com/peczenyj/MooseX"
14
14
  spec.license = "MIT"
15
15
 
@@ -0,0 +1,54 @@
1
+ require 'moosex'
2
+ require 'moosex/attribute'
3
+
4
+ module MooseX
5
+ module AttributeModifiers
6
+ module ThirdParty
7
+ class Chained
8
+ def initialize(this)
9
+ @this = this
10
+ end
11
+ def process(options, attr_symbol)
12
+
13
+ chained = !! options.delete(:chained)
14
+
15
+ if chained
16
+ writter = @this.attribute_map[:writter]
17
+ old_proc = @this.methods[ writter ]
18
+ @this.methods[writter] = ->(this, value) { old_proc.call(this, value); this }
19
+ end
20
+
21
+ chained
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ module MyPlugin
29
+ def self.included(x)
30
+ x.meta.add_plugin(:chained)
31
+ end
32
+ end
33
+
34
+ class Z
35
+ include MooseX.init(meta: true)
36
+ include MyPlugin
37
+
38
+ has :foo, {
39
+ writter: :set_foo,
40
+ chained: true,
41
+ }
42
+
43
+ has :bar, {
44
+ writter: :set_bar,
45
+ chained: false,
46
+ }
47
+ end
48
+
49
+ a1 = Z.new
50
+ a2 = Z.new
51
+
52
+ puts a1.set_foo(1).foo
53
+
54
+ puts a2.set_bar(1)#.bar
@@ -3,7 +3,7 @@ require 'moosex/attribute/modifiers'
3
3
  describe MooseX::AttributeModifiers::Is do
4
4
  it "should accept only valid parameters" do
5
5
  expect {
6
- MooseX::AttributeModifiers::Is.new.process({is: :forbidden}, :foo)
6
+ MooseX::AttributeModifiers::Is.new(nil).process({is: :forbidden}, :foo)
7
7
  }.to raise_error(MooseX::InvalidAttributeError,
8
8
  "invalid value for field 'foo' is 'forbidden', must be one of :private, :rw, :rwp, :ro or :lazy")
9
9
  end
@@ -12,7 +12,7 @@ end
12
12
  describe MooseX::AttributeModifiers::Predicate do
13
13
  it "should accept only valid parameters" do
14
14
  expect {
15
- MooseX::AttributeModifiers::Predicate.new.process({predicate: 0}, :foo)
15
+ MooseX::AttributeModifiers::Predicate.new(nil).process({predicate: 0}, :foo)
16
16
  }.to raise_error(MooseX::InvalidAttributeError,
17
17
  "cannot coerce field predicate to a symbol for foo: undefined method `to_sym' for 0:Fixnum")
18
18
  end
@@ -21,7 +21,7 @@ end
21
21
  describe MooseX::AttributeModifiers::Handles do
22
22
  it "should accept only valid parameters" do
23
23
  expect {
24
- MooseX::AttributeModifiers::Handles.new.process({handles: BasicObject}, :foo)
24
+ MooseX::AttributeModifiers::Handles.new(nil).process({handles: BasicObject}, :foo)
25
25
  }.to raise_error(MooseX::InvalidAttributeError,
26
26
  "ops, should not use BasicObject for handles in foo")
27
27
  end
@@ -1,47 +1,58 @@
1
1
  require 'moosex'
2
- require 'moosex/attribute'
3
- require 'moosex/attribute/modifiers'
4
-
5
- module MooseX
6
- module AttributeModifiers
7
- module ThirdParty
8
- class Bar
9
- def process(options, attr_symbol)
10
- !! options.delete(:bar)
11
- end
12
- end
13
- end
14
- end
15
- end
2
+ require 'moosex/traits'
3
+ require 'moosex/plugins'
16
4
 
17
- module MyPlugin
18
- def self.included(x)
19
- x.meta.add_plugin(:bar)
5
+ module TestAddAttribute
6
+ class EmailMessage
7
+ include MooseX.init(
8
+ with_plugins: MooseX::Plugins::Chained
9
+ )
10
+ has :_from, writter: :from, chained: true
11
+ has :_to, writter: :to, chained: true
12
+ has :_subject, writter: :withSubject, chained: true
13
+ has :_body , writter: :withBody, chained: true
14
+
15
+ def send
16
+ {
17
+ from: self._from,
18
+ to: self._to,
19
+ subject: self._subject,
20
+ body: self._body,
21
+ }
22
+ end
20
23
  end
21
- end
22
-
23
- module TestAddAttribute
24
+
24
25
  class A
25
- include MooseX.init(meta: true)
26
- include MyPlugin
26
+ include MooseX.init(
27
+ meta: true,
28
+ with_plugins: MooseX::Plugins::Chained
29
+ )
27
30
 
28
31
  has :foo, {
29
- bar: true
32
+ writter: :set_foo,
33
+ chained: true
30
34
  }
31
35
  end
32
36
 
33
37
  class B < A
34
38
 
35
39
  has :foo2, {
36
- bar: true
40
+ writter: :set_foo2,
41
+ chained: true
37
42
  }
43
+
44
+ has :foo3, {
45
+ writter: :set_foo3,
46
+ chained: false
47
+ }
38
48
  end
39
49
 
40
50
  class C
41
51
  include MooseX.init(meta: true)
42
52
 
43
53
  has :foo, {
44
- bar: true
54
+ writter: :set_foo,
55
+ chained: true, # will warn only!
45
56
  }
46
57
  end
47
58
  end
@@ -52,23 +63,114 @@ describe TestAddAttribute do
52
63
  end
53
64
 
54
65
  it "A should support the new attribute in meta" do
55
- TestAddAttribute::A.meta.attrs[:foo].attribute_map[:bar].should be_true
66
+ TestAddAttribute::A.meta.attrs[:foo].attribute_map[:chained].should be_true
56
67
  end
57
68
 
69
+ it "A should return self in writter" do
70
+ a = TestAddAttribute::A.new(foo: 1)
71
+ a.foo.should == 1
72
+ a.set_foo(2).should == a
73
+ a.foo.should == 2
74
+ end
75
+
58
76
  it "B should support the new attribute" do
59
77
  TestAddAttribute::B.new(foo: 1, foo2: 2)
60
78
  end
61
79
 
62
80
  it "B should support the new attribute in meta" do
63
- TestAddAttribute::B.meta.attrs[:foo].attribute_map[:bar].should be_true
64
- TestAddAttribute::B.meta.attrs[:foo2].attribute_map[:bar].should be_true
81
+ TestAddAttribute::B.meta.attrs[:foo].attribute_map[:chained].should be_true
82
+ TestAddAttribute::B.meta.attrs[:foo2].attribute_map[:chained].should be_true
65
83
  end
66
84
 
85
+ it "B should return self in writter" do
86
+ a = TestAddAttribute::B.new(foo: 1, foo2: 2)
87
+ a.foo.should == 1
88
+ a.foo2.should == 2
89
+ a.set_foo(2).should == a
90
+ a.set_foo2(4).should == a
91
+ a.foo.should == 2
92
+ a.foo2.should == 4
93
+
94
+ a.set_foo(5).set_foo2(9).should == a
95
+ a.foo.should == 5
96
+ a.foo2.should == 9
97
+ end
98
+
99
+ it "B foo3 should not be chained" do
100
+ a = TestAddAttribute::B.new(foo3: 4)
101
+ a.foo3.should == 4
102
+ a.set_foo3(7).should == 7
103
+ a.foo3.should == 7
104
+ end
105
+
67
106
  it "C should support the new attribute" do
68
107
  TestAddAttribute::C.new(foo: 1)
69
108
  end
70
109
 
71
110
  it "C should support the new attribute in meta" do
72
- TestAddAttribute::C.meta.attrs[:foo].attribute_map[:bar].should be_nil
73
- end
74
- end
111
+ TestAddAttribute::C.meta.attrs[:foo].attribute_map[:chained].should be_nil
112
+ end
113
+
114
+ it "C should return value in writter" do
115
+ a = TestAddAttribute::C.new(foo: 1)
116
+ a.foo.should == 1
117
+ a.set_foo(2).should == 2
118
+ a.foo.should == 2
119
+ end
120
+ end
121
+
122
+ describe "TestAddAttribute::EmailMessage" do
123
+
124
+ it "should return a hash with options" do
125
+ TestAddAttribute::EmailMessage.new.
126
+ from("foo@bar.com").
127
+ to("me@baz.com").
128
+ withSubject("test").
129
+ withBody("hi!").
130
+ send.should == {
131
+ from: "foo@bar.com",
132
+ to: "me@baz.com",
133
+ subject: "test",
134
+ body: "hi!"
135
+ }
136
+ end
137
+ end
138
+
139
+ module TestAddAttribute
140
+ class MyClass
141
+ include MooseX.init(meta: true, with_plugins: MooseX::Plugins::ExpiredAttribute)
142
+
143
+ has :log
144
+
145
+ has config: {
146
+ is: :lazy,
147
+ clearer: true,
148
+ predicate: true,
149
+ expires: 4, # seconds
150
+ }
151
+
152
+ has :session, default: ->{ {} }, expires: -1
153
+
154
+ def build_config
155
+ log.info(:created)
156
+ { foo: 1 }
157
+ end
158
+ end
159
+ end
160
+
161
+ describe TestAddAttribute::MyClass do
162
+ it "should reload config, but not session" do
163
+ log = double
164
+ log.should_receive(:info).with(:created).twice
165
+
166
+ c = TestAddAttribute::MyClass.new(log: log)
167
+
168
+ c.config.should == { foo: 1}
169
+ c.session.valid?.should be_true
170
+
171
+ sleep(4)
172
+
173
+ c.config.should == { foo: 1}
174
+ c.session.valid?.should be_true
175
+ end
176
+ end
@@ -55,97 +55,47 @@ module TestTrait
55
55
  }
56
56
  }
57
57
 
58
- has bit: {
59
- is: :ro,
58
+ has __bit__: {
59
+ is: :private,
60
60
  default: true,
61
61
  traits: MooseX::Traits::Bool,
62
- handles: [ :toggle!, :not, :set!, :unset!, :value ],
63
- }
64
-
65
- has important: {
66
- is: :rw,
67
- default: nil,
68
- traits: MooseX::Traits::RescueToNil,
69
62
  handles: {
70
- plus: :+,
71
- minus: :-,
72
- }
63
+ :bit_toggle! => :toggle!,
64
+ :bit_turn_on! => :set!,
65
+ :bit_turn_off! => :unset!,
66
+ :bit_on? => :value,
67
+ :bit_off? => :not,
68
+ },
69
+ init_arg: :bit,
73
70
  }
74
-
75
- has important2: {
71
+
72
+ has session: {
76
73
  is: :rw,
77
- default: nil,
78
- traits: MooseX::Traits::RescueToZero,
79
- handles: {
80
- plus2: :+,
81
- minus2: :-,
82
- }
83
- }
84
-
85
- has phrase: {
86
- is: :rw,
87
- default: nil,
88
- traits: MooseX::Traits::RescueToEmptyString,
89
- handles: {
90
- upcase_phrase: :upcase
91
- }
74
+ default: -> { {} },
75
+ coerce: ->(value) { ((value.is_a?(Array))? value : [value, 3]) },
76
+ traits: MooseX::Traits::Expires,
92
77
  }
93
78
 
94
79
  def build_lazy_counter
95
80
  0
96
81
  end
97
82
  end
98
-
99
- class ComplexExample
100
- include MooseX
101
- include MooseX::Types
102
-
103
- has surname_name: {
104
- is: :rw,
105
- isa: isMaybe(isTuple(String, String)),
106
- default: nil,
107
- traits: [ MooseX::Traits::RescueToEmptyString, MooseX::Traits::Pair ],
108
- handles: {
109
- surname: :first,
110
- name: :second,
111
- :surname= => :first=,
112
- :name= => :second=,
113
- surname_and_name: { join: ->{", "} }
114
- }
115
- }
116
- end
117
- end
118
-
119
- describe TestTrait::ComplexExample do
120
- it "should be possible call surname_and_name" do
121
- ce = TestTrait::ComplexExample.new(surname_name: ["Asimov", "Isaac"])
122
- ce.name.should == "Isaac"
123
- ce.surname_and_name.should == "Asimov, Isaac"
124
- end
125
-
126
- it "should be possible call surname_and_name if nil" do
127
- ce = TestTrait::ComplexExample.new(surname_name: nil)
128
- ce.name.should == ""
129
- ce.surname_and_name.should == ", "
130
- end
131
-
132
- it "should be possible call surname_and_name if nil 2" do
133
- ce = TestTrait::ComplexExample.new(surname_name: nil)
134
- ce.name.should == ""
135
- ce.surname_and_name.should == ", "
136
-
137
- ce.name= "Isaac"
138
- ce.surname_and_name.should == ", Isaac"
139
- ce.surname= "Asimov"
140
- ce.surname_and_name.should == "Asimov, Isaac"
141
-
142
- ce.surname_name= nil
143
- ce.name.should == ""
144
- ce.surname_and_name.should == ", "
145
- end
146
83
  end
147
84
 
148
85
  describe TestTrait::MyHomePage do
86
+ it "should accept valid session" do
87
+ page = TestTrait::MyHomePage.new
88
+ page.session.valid?.should be_true
89
+ page.session.should == {}
90
+ sleep(3)
91
+ page.session.valid?.should be_false
92
+ page.session= { bar: 5 }
93
+ page.session.valid?.should be_true
94
+ page.session.should == { bar: 5 }
95
+ sleep(3)
96
+ page.session.valid?.should be_false
97
+ end
98
+
149
99
  it "should increase counter" do
150
100
  page = TestTrait::MyHomePage.new(counter: 0)
151
101
  page.counter.should be_zero
@@ -249,76 +199,31 @@ describe TestTrait::MyHomePage do
249
199
  page.surname_name.count.should == 2
250
200
  }.to raise_error(NoMethodError)
251
201
  end
202
+
203
+ it "bit should act as a boolean in arg list" do
204
+ page = TestTrait::MyHomePage.new(bit: false)
205
+ page.bit_on?.should be_false
206
+ end
252
207
 
253
208
  it "bit should act as a boolean" do
254
209
  page = TestTrait::MyHomePage.new
255
- page.bit.should == true
256
- page.toggle!
257
- page.bit.should == false
258
- page.not.should == true
210
+ page.bit_on?.should be_true
211
+ page.bit_toggle!
212
+ page.bit_on?.should be_false
213
+ page.bit_off?.should be_true
259
214
 
260
- page.set!
261
- page.bit.should == true
215
+ page.bit_turn_on!
216
+ page.bit_on?.should be_true
262
217
 
263
- unless page.bit
218
+ unless page.bit_on?
264
219
  raise "should act as a true value"
265
220
  end
266
- page.unset!
267
- page.bit.should == false
221
+ page.bit_turn_off!
222
+ page.bit_on?.should be_false
268
223
 
269
- if !! page.bit # necessary!!!
224
+ if page.bit_on?
270
225
  raise "should act as a false value"
271
226
  end
272
-
273
- if page.value
274
- raise "should act as a false value"
275
- end
276
- end
277
-
278
- it "important should be converted to integer" do
279
- page = TestTrait::MyHomePage.new(important: 1)
280
- page.important.should == 1
281
- page.plus(1).should == 2
282
- page.minus(4).should == -3
283
- (page.important + 5).should == 6
284
- end
285
-
286
- it "important should be converted to integer returning nil" do
287
- page = TestTrait::MyHomePage.new(important: nil)
288
- page.important.should == nil
289
- page.plus(1).should == nil
290
- page.minus(4).should == nil
291
- (page.important + 5).should == nil
292
- end
293
-
294
- it "important2 should be converted to integer" do
295
- page = TestTrait::MyHomePage.new(important2: 1)
296
- page.important2.should == 1
297
- page.plus2(1).should == 2
298
- page.minus2(4).should == -3
299
- (page.important2 + 5).should == 6
300
- end
301
-
302
- it "important2 should be converted to integer returning 0" do
303
- page = TestTrait::MyHomePage.new(important2: nil)
304
- page.important2.should be_zero
305
- page.plus2(1).should == 0
306
- page.minus2(4).should == 0
307
- (page.important2 + 5).should == 0
308
- end
309
-
310
- it "phrase should be converted to String" do
311
- page = TestTrait::MyHomePage.new(phrase: "hello")
312
- page.phrase.should == "hello"
313
- page.upcase_phrase == "HELLO"
314
- (page.upcase_phrase.concat ", WORLD").should == "HELLO, WORLD"
315
- end
316
-
317
- it "phrase should returning empty string" do
318
- page = TestTrait::MyHomePage.new(phrase: nil)
319
- page.phrase.should be_eql? ""
320
- page.upcase_phrase == ""
321
- (page.upcase_phrase.concat ", WORLD").should == ", WORLD"
322
- end
227
+ end
323
228
  end
324
229
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moosex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.19
4
+ version: 0.0.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Peczenyj
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-14 00:00:00.000000000 Z
11
+ date: 2014-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -83,7 +83,8 @@ dependencies:
83
83
  description: MooseX is an extension of Ruby object DSL. The main goal of MooseX is
84
84
  to make Ruby Object Oriented programming easier, more consistent, and less tedious.
85
85
  With MooseX you can think more about what you want to do and less about the mechanics
86
- of OOP. It is a port of Moose/Moo from Perl to Ruby world.
86
+ of OOP. It is a port of Moose/Moo from Perl to Ruby world, providing method delegation,
87
+ type check, monads, lazy attributes, aspects and much more.
87
88
  email:
88
89
  - tiago.peczenyj@gmail.com
89
90
  executables: []
@@ -107,6 +108,7 @@ files:
107
108
  - lib/moosex/event.rb
108
109
  - lib/moosex/exceptions.rb
109
110
  - lib/moosex/meta.rb
111
+ - lib/moosex/plugins.rb
110
112
  - lib/moosex/traits.rb
111
113
  - lib/moosex/types.rb
112
114
  - lib/moosex/version.rb
@@ -115,6 +117,7 @@ files:
115
117
  - samples/binary_tree.rb
116
118
  - samples/events.rb
117
119
  - samples/human.rb
120
+ - samples/plugin.rb
118
121
  - samples/point.rb
119
122
  - samples/roles.rb
120
123
  - spec/baserole_spec.rb
@@ -190,4 +193,3 @@ test_files:
190
193
  - spec/trigger_spec.rb
191
194
  - spec/types_spec.rb
192
195
  - spec/weak_spec.rb
193
- has_rdoc: