morph 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|