morph 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +46 -39
- data/lib/morph.rb +27 -8
- data/morph.gemspec +3 -3
- data/spec/morph_spec.rb +75 -0
- metadata +2 -2
data/README
CHANGED
@@ -2,7 +2,7 @@ Morph allows you to emerge class definitions via calling assignment methods; mix
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
-
== Morph
|
5
|
+
== Morph playing with +Hpricot+
|
6
6
|
|
7
7
|
Here's example code showing Morph playing with Hpricot:
|
8
8
|
|
@@ -36,16 +36,18 @@ What new methods do we have?
|
|
36
36
|
|
37
37
|
Ah-ha, so we have a name attribute now:
|
38
38
|
|
39
|
-
why.name
|
39
|
+
why.name # => "why the lucky stiff"
|
40
40
|
|
41
41
|
|
42
42
|
Let's add some of why's projects:
|
43
43
|
|
44
|
-
why.projects = %w[shoes hacketyhack camping hoodwinkd hpricot
|
44
|
+
why.projects = %w[shoes hacketyhack camping hoodwinkd hpricot
|
45
|
+
markaby mousehole parkplace poignant sandbox]
|
45
46
|
|
46
47
|
That why's a productive fellow! Note new accessor methods have been added:
|
47
48
|
|
48
|
-
Hubbit.morph_methods
|
49
|
+
Hubbit.morph_methods
|
50
|
+
# => ["email", "email=", "name", "name=", "projects", "projects="]
|
49
51
|
|
50
52
|
|
51
53
|
Let's do some more morphing:
|
@@ -54,66 +56,71 @@ Let's do some more morphing:
|
|
54
56
|
|
55
57
|
Do we have more methods now?
|
56
58
|
|
57
|
-
Hubbit.morph_methods
|
59
|
+
Hubbit.morph_methods
|
60
|
+
# => ["blog", "blog=", "company", "company=", "email", "email=",
|
61
|
+
# "location", "location=" "name", "name=", "projects", "projects="]
|
58
62
|
|
59
63
|
So, a new company method has appeared:
|
60
64
|
|
61
65
|
dhh.company #=> "37signals"
|
62
66
|
|
63
67
|
|
68
|
+
== Morph making sample Active Record line via +script_generate+
|
64
69
|
|
65
|
-
|
70
|
+
Time to generate an Active Record model? Get a sample script line like this:
|
66
71
|
|
67
|
-
|
72
|
+
Hubbit.script_generate
|
73
|
+
# => "ruby script/destroy rspec_model Hubbit;
|
74
|
+
# ruby script/generate rspec_model Hubbit blog:string company:string
|
75
|
+
# email:string location:string name:string projects:string"
|
76
|
+
|
77
|
+
or specify the generator:
|
78
|
+
|
79
|
+
Hubbit.script_generate :generator => 'model'
|
80
|
+
# => "ruby script/destroy model Hubbit;
|
81
|
+
# ruby script/generate model Hubbit blog:string company:string
|
82
|
+
# email:string location:string name:string projects:string"
|
83
|
+
|
84
|
+
You'll have to edit this as it currently sets all data types to be string, and
|
85
|
+
doesn't understand associations.
|
86
|
+
|
87
|
+
|
88
|
+
== Morph setting hash of attributes via +morph+
|
68
89
|
|
69
90
|
class Order; include Morph; end
|
70
91
|
order = Order.new
|
92
|
+
|
93
|
+
How about adding a hash of attribute values?
|
94
|
+
|
71
95
|
order.morph :drink => 'tea', :spoons_of_sugar => 2, :milk => 'prefer soya thanks'
|
72
96
|
|
97
|
+
Looks like we got 'em:
|
98
|
+
|
73
99
|
order.drink # => "tea"
|
74
100
|
order.spoons_of_sugar # => 2
|
75
101
|
order.milk # => "prefer soya thanks"
|
76
102
|
|
77
103
|
|
104
|
+
== Morph obtaining hash of attributes via +morph_attributes+
|
78
105
|
|
79
|
-
|
80
|
-
|
81
|
-
class VegieFoxes
|
82
|
-
include Morph
|
106
|
+
Create an item:
|
83
107
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
create_accessors base, attribute
|
88
|
-
end
|
89
|
-
send(symbol, *args)
|
90
|
-
else
|
91
|
-
super
|
92
|
-
end
|
93
|
-
end
|
108
|
+
class Item; include Morph; end
|
109
|
+
item = Item.new
|
110
|
+
item.morph :name => 'spinach', :cost => 0.50
|
94
111
|
|
95
|
-
|
96
|
-
def create_accessors base, attribute
|
97
|
-
base.class_eval "attr_reader :#{attribute}"
|
112
|
+
Now an order:
|
98
113
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
foxes = VegieFoxes.new
|
114
|
+
class Order; include Morph; end
|
115
|
+
order = Order.new
|
116
|
+
order.no = 123
|
117
|
+
order.items = [item]
|
108
118
|
|
109
|
-
|
110
|
-
foxes.inspect # => #<VegieFoxes @chunky="spinach">
|
119
|
+
Want to retrieve all that as a nested hash of values? No problem:
|
111
120
|
|
112
|
-
|
113
|
-
|
121
|
+
order.morph_attributes
|
122
|
+
# => {:items=>[{:name=>"spinach", :cost=>0.5}], :no=>123}
|
114
123
|
|
115
|
-
foxes.pet = 'ham'
|
116
|
-
foxes.inspect # => #<VegieFoxes @pet="spinach", @chunky="cheese">
|
117
124
|
|
118
125
|
== Last bits
|
119
126
|
|
data/lib/morph.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Morph
|
2
|
-
VERSION = "0.
|
2
|
+
VERSION = "0.2.0"
|
3
3
|
|
4
4
|
def self.included(base)
|
5
5
|
base.extend ClassMethods
|
@@ -9,15 +9,15 @@ module Morph
|
|
9
9
|
|
10
10
|
module ClassMethods
|
11
11
|
|
12
|
-
@@adding_morph_method = false
|
13
|
-
@@morph_methods = {}
|
12
|
+
@@adding_morph_method = Hash.new {|hash,klass| hash[klass] = false }
|
13
|
+
@@morph_methods = Hash.new {|hash,klass| hash[klass] = {} }
|
14
14
|
|
15
15
|
def morph_methods
|
16
|
-
@@morph_methods.keys.sort
|
16
|
+
@@morph_methods[self].keys.sort
|
17
17
|
end
|
18
18
|
|
19
19
|
def adding_morph_method= true_or_false
|
20
|
-
@@adding_morph_method = true_or_false
|
20
|
+
@@adding_morph_method[self] = true_or_false
|
21
21
|
end
|
22
22
|
|
23
23
|
def class_def name, &block
|
@@ -33,14 +33,23 @@ module Morph
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
def script_generate options={}
|
37
|
+
name = self.name.to_s.split('::').last
|
38
|
+
name = yield name if block_given?
|
39
|
+
generator = options[:generator] || 'rspec_model'
|
40
|
+
line = ["ruby script/destroy #{generator} #{name}; ruby script/generate #{generator} #{name}"]
|
41
|
+
morph_methods.select{|m| not(m =~ /=$/) }.each {|attribute| line << " #{attribute}:string"}
|
42
|
+
line.join('')
|
43
|
+
end
|
44
|
+
|
36
45
|
protected
|
37
46
|
|
38
47
|
def method_added symbol
|
39
|
-
@@morph_methods[symbol.to_s] = true if @@adding_morph_method
|
48
|
+
@@morph_methods[self][symbol.to_s] = true if @@adding_morph_method[self]
|
40
49
|
end
|
41
50
|
|
42
51
|
def method_removed symbol
|
43
|
-
@@morph_methods.delete symbol.to_s if @@morph_methods.has_key? symbol.to_s
|
52
|
+
@@morph_methods[self].delete symbol.to_s if @@morph_methods[self].has_key? symbol.to_s
|
44
53
|
end
|
45
54
|
|
46
55
|
end
|
@@ -86,7 +95,17 @@ module Morph
|
|
86
95
|
attributes = self.class.morph_methods.inject({}) do |hash, attribute|
|
87
96
|
unless attribute =~ /=\Z/
|
88
97
|
symbol = attribute.to_sym
|
89
|
-
|
98
|
+
value = send(symbol)
|
99
|
+
|
100
|
+
value.each do |key, v|
|
101
|
+
value[key] = v.morph_attributes if v.respond_to?(:morph_attributes)
|
102
|
+
end if value.is_a? Hash
|
103
|
+
|
104
|
+
value = value.collect {|v| v.respond_to?(:morph_attributes) ? v.morph_attributes : v } if value.is_a? Array
|
105
|
+
value = value.morph_attributes if value.respond_to? :morph_attributes
|
106
|
+
|
107
|
+
|
108
|
+
hash[symbol] = value
|
90
109
|
end
|
91
110
|
hash
|
92
111
|
end
|
data/morph.gemspec
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
|
2
|
-
# Gem::Specification for Morph-0.
|
2
|
+
# Gem::Specification for Morph-0.2.0
|
3
3
|
# Originally generated by Echoe
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = %q{morph}
|
7
|
-
s.version = "0.
|
7
|
+
s.version = "0.2.0"
|
8
8
|
|
9
9
|
s.specification_version = 2 if s.respond_to? :specification_version=
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.authors = ["Rob McKinnon"]
|
13
|
-
s.date = %q{2008-
|
13
|
+
s.date = %q{2008-05-01}
|
14
14
|
s.description = %q{Morph allows you to emerge class definitions via calling assignment methods; mix with Hpricot for screen scrapping fun.}
|
15
15
|
s.email = ["rob ~@nospam@~ rubyforge.org"]
|
16
16
|
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README"]
|
data/spec/morph_spec.rb
CHANGED
@@ -19,6 +19,18 @@ describe Morph, "when writer method that didn't exist before is called with non-
|
|
19
19
|
it 'should return hash of attributes when morph_attributes called' do
|
20
20
|
@morph.morph_attributes.should == {@attribute.to_sym => @quack}
|
21
21
|
end
|
22
|
+
|
23
|
+
it 'should generate rails model generator script line, with given model name' do
|
24
|
+
@morphed_class.script_generate {|model_name| 'SomethingDifferent'}.should == "ruby script/destroy rspec_model SomethingDifferent; ruby script/generate rspec_model SomethingDifferent noise:string"
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should generate rails model generator script line' do
|
28
|
+
@morphed_class.script_generate.should == "ruby script/destroy rspec_model ExampleMorph; ruby script/generate rspec_model ExampleMorph noise:string"
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should generate rails model generator script line' do
|
32
|
+
@morphed_class.script_generate(:generator=>'model').should == "ruby script/destroy model ExampleMorph; ruby script/generate model ExampleMorph noise:string"
|
33
|
+
end
|
22
34
|
end
|
23
35
|
|
24
36
|
describe Morph, "when writer method that didn't exist before is called with nil value" do
|
@@ -31,6 +43,61 @@ describe Morph, "when writer method that didn't exist before is called with nil
|
|
31
43
|
it_should_behave_like "class without generated accessor methods added"
|
32
44
|
end
|
33
45
|
|
46
|
+
describe Morph, "when different writer method called on two different morph classes" do
|
47
|
+
include MorphSpecHelperMethods
|
48
|
+
|
49
|
+
before :each do
|
50
|
+
initialize_morph
|
51
|
+
initialize_another_morph
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should have morph_method return appropriate methods for each class' do
|
55
|
+
@morph.every = 'where'
|
56
|
+
@another_morph.no = 'where'
|
57
|
+
|
58
|
+
@morphed_class.morph_methods.size.should == 2
|
59
|
+
@another_morphed_class.morph_methods.size.should == 2
|
60
|
+
|
61
|
+
@morphed_class.morph_methods.should == ['every','every=']
|
62
|
+
@another_morphed_class.morph_methods.should == ['no','no=']
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should call morph_attributes on both objects, when one object has a reference to another' do
|
66
|
+
@morph.every = 'which'
|
67
|
+
@another_morph.way = 'but'
|
68
|
+
@morph.loose = @another_morph
|
69
|
+
|
70
|
+
attributes = @morph.morph_attributes
|
71
|
+
attributes[:every].should == 'which'
|
72
|
+
attributes[:loose].should == {:way => 'but'}
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should call morph_attributes on both objects, when one object has a reference to array of others' do
|
76
|
+
@morph.every = 'which'
|
77
|
+
@another_morph.way = 'but'
|
78
|
+
@morph.loose = [@another_morph]
|
79
|
+
|
80
|
+
attributes = @morph.morph_attributes
|
81
|
+
attributes[:every].should == 'which'
|
82
|
+
attributes[:loose].should == [{:way => 'but'}]
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should call morph_attributes on both objects, when one object has a reference to hash of others' do
|
86
|
+
@morph.every = 'which'
|
87
|
+
@another_morph.way = 'but'
|
88
|
+
@morph.loose = { :honky_tonk => @another_morph}
|
89
|
+
|
90
|
+
attributes = @morph.morph_attributes
|
91
|
+
attributes[:every].should == 'which'
|
92
|
+
attributes[:loose].should == { :honky_tonk => {:way => 'but'} }
|
93
|
+
end
|
94
|
+
|
95
|
+
after :each do
|
96
|
+
remove_morph_methods
|
97
|
+
remove_another_morph_methods
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
34
101
|
describe Morph, "when class definition contains methods and morph is included" do
|
35
102
|
include MorphSpecHelperMethods
|
36
103
|
|
@@ -87,6 +154,14 @@ describe Morph, 'when morph method used to set an attribute value hash' do
|
|
87
154
|
@morph.sugars.should == 2
|
88
155
|
@morph.milk.should == 'yes please'
|
89
156
|
end
|
157
|
+
|
158
|
+
it 'should generate rails model generator script line' do
|
159
|
+
@morphed_class.script_generate.should == "ruby script/destroy rspec_model ExampleMorph; ruby script/generate rspec_model ExampleMorph drink:string milk:string sugars:string"
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should generate rails model generator script line' do
|
163
|
+
@morphed_class.script_generate(:generator=>'model').should == "ruby script/destroy model ExampleMorph; ruby script/generate model ExampleMorph drink:string milk:string sugars:string"
|
164
|
+
end
|
90
165
|
end
|
91
166
|
|
92
167
|
describe Morph, "when morph method used to set unicode attribute name with a value" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: morph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob McKinnon
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-05-01 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|