morph 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,5 @@
1
+ v0.3.5. retain morph_methods when inheriting class and parent both include Morph
2
+
1
3
  v0.3.4. return instance morph_attributes ordered by original addition of attribute
2
4
 
3
5
  v0.3.3. removed show_ruby() method; updated script_generate() to utilise new rails commands
data/Manifest CHANGED
@@ -1,10 +1,5 @@
1
1
  CHANGELOG
2
- examples/forger.rb
3
- examples/hubbit.rb
4
2
  lib/morph.rb
5
3
  LICENSE
6
4
  README
7
- spec/lib/morph_spec.rb
8
- spec/morph_spec_helper.rb
9
- spec/spec_helper.rb
10
5
  Manifest
data/README CHANGED
@@ -1,44 +1,50 @@
1
- Morph mixin allows you to emerge class definitions via calling assignment methods; mix with Nokogiri for screen scraping fun.
1
+ Morph mixin allows you to emerge Ruby class definitions from data via calling assignment methods.
2
2
 
3
3
 
4
+ == Installing Morph
5
+
6
+ gem install morph
7
+
8
+ To use Morph:
9
+
10
+ require 'morph'
11
+
4
12
  == Morph creating classes +from_csv+
5
13
 
6
14
  Here's example code showing Morph playing with CSV (comma-separated values):
7
15
 
8
- require 'rubygems'; require 'morph'
9
-
10
16
  csv = %Q[name,party\nTed Roe,red\nAli Davidson,blue\nSue Smith,green]
11
17
 
12
18
  people = Morph.from_csv(csv, 'person')
19
+
13
20
  # => [#<Morph::Person @name="Ted Roe", @party="red">,
14
21
  #<Morph::Person @name="Ali Davidson", @party="blue">,
15
22
  #<Morph::Person @name="Sue Smith", @party="green">]
16
23
 
17
24
  people.last.party
25
+
18
26
  # => "green"
19
27
 
20
28
  == Morph creating classes +from_tsv+
21
29
 
22
30
  Here's example code showing Morph playing with TSV (tab-separated values):
23
31
 
24
- require 'rubygems'; require 'morph'
25
-
26
32
  tsv = %Q[name\tparty\nTed Roe\tred\nAli Davidson\tblue\nSue Smith\tgreen]
27
33
 
28
34
  people = Morph.from_tsv(tsv, 'person')
35
+
29
36
  # => [#<Morph::Person @name="Ted Roe", @party="red">,
30
37
  #<Morph::Person @name="Ali Davidson", @party="blue">,
31
38
  #<Morph::Person @name="Sue Smith", @party="green">]
32
39
 
33
40
  people.last.party
41
+
34
42
  # => "green"
35
43
 
36
44
  == Morph creating classes +from_xml+
37
45
 
38
46
  Here's example code showing Morph playing with XML:
39
47
 
40
- require 'rubygems'; require 'morph'
41
-
42
48
  xml = %Q[<?xml version="1.0" encoding="UTF-8"?>
43
49
  <councils type="array">
44
50
  <council code='1'>
@@ -50,18 +56,20 @@ Here's example code showing Morph playing with XML:
50
56
  </councils>]
51
57
 
52
58
  councils = Morph.from_xml(xml)
59
+
53
60
  # => [#<Morph::Council @code="1", @name="Aberdeen City Council">,
54
61
  #<Morph::Council @code="2", @name="Allerdale Borough Council">]
55
62
 
56
63
  councils.first.name
64
+
57
65
  # => "Aberdeen City Council"
58
66
 
59
67
  == Morph playing with +Nokogiri+
60
68
 
61
69
  Here's example code showing Morph playing with Nokogiri in Ruby 1.9.2:
62
70
 
63
- require 'rubygems'; require 'nokogiri'; require 'open-uri'
64
- require 'morph'
71
+ require 'morph'; require 'nokogiri'; require 'open-uri'
72
+
65
73
 
66
74
  class Hubbit
67
75
  include Morph # allows class to morph
@@ -93,6 +101,7 @@ The model emerges from the data. Let's start by looking up 'why':
93
101
  What new methods do we have?
94
102
 
95
103
  Hubbit.morph_methods.map {|m| m.to_s}
104
+
96
105
  #=> ["location", "location=", "member_since", "member_since=", "name", "name="]
97
106
 
98
107
  Ah-ha, so we have a name attribute now:
@@ -112,6 +121,7 @@ Let's add some of why's projects:
112
121
  That why's a productive fellow! Note new accessor methods have been added:
113
122
 
114
123
  Hubbit.morph_methods.map {|m| m.to_s}
124
+
115
125
  #=> ["location", "location=", "member_since", "member_since=", "name", "name=",
116
126
  # "projects", "projects="]
117
127
 
@@ -123,6 +133,7 @@ Let's do some more morphing:
123
133
  Do we have more methods now?
124
134
 
125
135
  Hubbit.morph_methods.map {|m| m.to_s}
136
+
126
137
  #=> ["company", "company=", "email", "email=", "location", "location=",
127
138
  # "member_since", "member_since=", "name", "name=", "projects", "projects=",
128
139
  # "website_blog", "website_blog="]
@@ -137,6 +148,7 @@ So, a new company method has appeared:
137
148
  Time to generate an Active Record model? Get a sample script line like this:
138
149
 
139
150
  Hubbit.script_generate
151
+
140
152
  #=> "rails destroy model Hubbit;
141
153
  # rails generate model Hubbit company:string email:string location:string
142
154
  # member_since:string name:string projects:string website_blog:string"
@@ -144,6 +156,7 @@ Time to generate an Active Record model? Get a sample script line like this:
144
156
  or specify the generator:
145
157
 
146
158
  Hubbit.script_generate :generator => 'rspec_model'
159
+
147
160
  #=> "rails destroy rspec_model Hubbit;
148
161
  # rails generate rspec_model Hubbit company:string email:string
149
162
  # location:string member_since:string name:string projects:string
@@ -187,6 +200,7 @@ Now an order:
187
200
  Want to retrieve all that as a nested hash of values? No problem:
188
201
 
189
202
  order.morph_attributes
203
+
190
204
  # => {:items=>[{:name=>"spinach", :cost=>0.5}], :no=>123}
191
205
 
192
206
 
data/lib/morph.rb CHANGED
@@ -18,7 +18,7 @@ rescue Exception => e
18
18
  end
19
19
 
20
20
  module Morph
21
- VERSION = "0.3.4" unless defined? Morph::VERSION
21
+ VERSION = "0.3.5" unless defined? Morph::VERSION
22
22
 
23
23
  class << self
24
24
  def generate_migrations object, options={}
@@ -183,20 +183,29 @@ module Morph
183
183
 
184
184
  module ClassMethods
185
185
 
186
- @@adding_morph_method = Hash.new {|hash,klass| hash[klass] = false }
187
- @@morph_methods = Hash.new {|hash,klass| hash[klass] = {} }
188
- @@morph_attributes = Hash.new {|hash,klass| hash[klass] = [] }
186
+ @@adding_morph_method = Hash.new {|hash,klass| hash[klass] = false } unless defined?(@@adding_morph_method)
187
+ @@morph_methods = Hash.new {|hash,klass| hash[klass] = {} } unless defined?(@@morph_methods)
188
+ @@morph_attributes = Hash.new {|hash,klass| hash[klass] = [] } unless defined?(@@morph_attributes)
189
189
 
190
190
  def morph_attributes
191
- @@morph_attributes[self] + []
191
+ if superclass.respond_to?(:morph_attributes)
192
+ @@morph_attributes[self] + superclass.morph_attributes
193
+ else
194
+ @@morph_attributes[self] + []
195
+ end
192
196
  end
193
197
 
194
198
  def morph_methods
195
- if RUBY_VERSION >= "1.9"
199
+ methods = if RUBY_VERSION >= "1.9"
196
200
  @@morph_methods[self].keys.sort.map(&:to_sym)
197
201
  else
198
202
  @@morph_methods[self].keys.sort
199
203
  end
204
+
205
+ if superclass.respond_to?(:morph_attributes)
206
+ methods += superclass.morph_methods
207
+ end
208
+ methods
200
209
  end
201
210
 
202
211
  def adding_morph_method= true_or_false
data/morph.gemspec CHANGED
@@ -2,21 +2,21 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "morph"
5
- s.version = "0.3.4"
5
+ s.version = "0.3.5"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Rob McKinnon"]
9
- s.date = "2012-06-15"
10
- s.description = "Morph mixin allows you to emerge class definitions via calling assignment methods; mix with Nokogiri for screen scraping fun.\n"
9
+ s.date = "2012-08-31"
10
+ s.description = "Morph mixin allows you to emerge Ruby class definitions from data via calling assignment methods.\n"
11
11
  s.email = ["rob ~@nospam@~ rubyforge.org"]
12
12
  s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README"]
13
- s.files = ["CHANGELOG", "examples/forger.rb", "examples/hubbit.rb", "lib/morph.rb", "LICENSE", "README", "spec/lib/morph_spec.rb", "spec/morph_spec_helper.rb", "spec/spec_helper.rb", "Manifest", "morph.gemspec", "Rakefile"]
13
+ s.files = ["CHANGELOG", "lib/morph.rb", "LICENSE", "README", "Manifest", "morph.gemspec", "Rakefile"]
14
14
  s.homepage = "https://github.com/robmckinnon/morph"
15
15
  s.post_install_message = "Read usage examples at: https://github.com/robmckinnon/morph#readme"
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Morph", "--main", "README", "--inline-source"]
17
17
  s.require_paths = ["lib"]
18
18
  s.rubyforge_project = "morph"
19
- s.rubygems_version = "1.8.18"
19
+ s.rubygems_version = "1.8.24"
20
20
  s.summary = "Morph mixin allows you to emerge class definitions via calling assignment methods."
21
21
 
22
22
  if s.respond_to? :specification_version then
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.3.4
4
+ version: 0.3.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-15 00:00:00.000000000 Z
12
+ date: 2012-08-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -59,8 +59,8 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
- description: ! 'Morph mixin allows you to emerge class definitions via calling assignment
63
- methods; mix with Nokogiri for screen scraping fun.
62
+ description: ! 'Morph mixin allows you to emerge Ruby class definitions from data
63
+ via calling assignment methods.
64
64
 
65
65
  '
66
66
  email:
@@ -73,14 +73,9 @@ extra_rdoc_files:
73
73
  - README
74
74
  files:
75
75
  - CHANGELOG
76
- - examples/forger.rb
77
- - examples/hubbit.rb
78
76
  - lib/morph.rb
79
77
  - LICENSE
80
78
  - README
81
- - spec/lib/morph_spec.rb
82
- - spec/morph_spec_helper.rb
83
- - spec/spec_helper.rb
84
79
  - Manifest
85
80
  - morph.gemspec
86
81
  - Rakefile
@@ -111,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
106
  version: '1.2'
112
107
  requirements: []
113
108
  rubyforge_project: morph
114
- rubygems_version: 1.8.18
109
+ rubygems_version: 1.8.24
115
110
  signing_key:
116
111
  specification_version: 3
117
112
  summary: Morph mixin allows you to emerge class definitions via calling assignment
data/examples/forger.rb DELETED
@@ -1,31 +0,0 @@
1
- require 'rubygems'; require 'hpricot'; require 'open-uri'; require 'morph'
2
-
3
- # An example of Morph playing with Hpricot
4
- class Forger
5
-
6
- include Morph
7
-
8
- def initialize name
9
- begin
10
- doc = Hpricot open("http://rubyforge.org/users/#{name}")
11
-
12
- table = doc.at('td[text() = "Personal Information"]').parent.parent
13
- values = table/'tr/td/strong'
14
-
15
- values.collect do |node|
16
- value = node.inner_text.strip
17
- label = node.at('../../td[1]').inner_text
18
- morph(label, value)
19
- end
20
- rescue
21
- raise "Couldn't find forger with name: #{name}"
22
- end
23
- end
24
- end
25
-
26
- def Forger name
27
- Forger.new name
28
- end
29
-
30
- #> why = Forger 'why'
31
-
data/examples/hubbit.rb DELETED
@@ -1,32 +0,0 @@
1
- require 'morph'
2
-
3
- require 'rubygems'; require 'nokogiri'; require 'open-uri'
4
-
5
- # An example of Morph playing with Nokogiri
6
- class Hubbit
7
- include Morph # allows class to morph
8
-
9
- def initialize name
10
- doc = Nokogiri::HTML open("https://github.com/#{name}")
11
-
12
- profile_fields = doc.search('.vcard dt')
13
-
14
- profile_fields.each do |node|
15
- label = node.inner_text
16
- value = node.next_element.inner_text.strip
17
-
18
- morph(label, value) # morph magic adds accessor methods!
19
- end
20
- end
21
-
22
- def member_since_date
23
- Date.parse member_since
24
- end
25
- end
26
-
27
- def Hubbit name
28
- Hubbit.new name
29
- end
30
-
31
- # why = Hubbit 'why'
32
- # dhh = Hubbit 'dhh'
@@ -1,642 +0,0 @@
1
- # encoding: utf-8
2
- require File.dirname(__FILE__) + '/../morph_spec_helper'
3
-
4
- describe Morph do
5
- include MorphSpecHelperMethods
6
-
7
- describe "when writer method that didn't exist before is called with non-nil value" do
8
- before :all do initialize_morph; end
9
- after :all do remove_morph_methods; end
10
-
11
- before :each do
12
- remove_morph_methods
13
- @quack = 'quack'
14
- @morph.noise= @quack
15
- @attribute = 'noise'
16
- @expected_morph_methods_count = 2
17
- end
18
-
19
- it_should_behave_like "class with generated accessor methods added"
20
-
21
- it 'should return assigned value when reader method called' do
22
- @morph.noise.should == @quack
23
- end
24
-
25
- it 'should return hash of attributes when morph_attributes called' do
26
- @morph.morph_attributes.should == {@attribute.to_sym => @quack}
27
- end
28
-
29
- it 'should generate rails model generator script line, with given model name' do
30
- @morphed_class.script_generate {|model_name| 'SomethingDifferent'}.should == "rails destroy model SomethingDifferent; rails generate model SomethingDifferent noise:string"
31
- end
32
-
33
- it 'should generate rails model generator script line' do
34
- @morphed_class.script_generate.should == "rails destroy model ExampleMorph; rails generate model ExampleMorph noise:string"
35
- end
36
-
37
- it 'should generate rails model generator script line' do
38
- @morphed_class.script_generate(:generator=>'model').should == "rails destroy model ExampleMorph; rails generate model ExampleMorph noise:string"
39
- end
40
- end
41
-
42
- describe "when writer method that didn't exist before is called with nil value" do
43
- before :each do
44
- remove_morph_methods
45
- @morph.noise= nil
46
- @attribute = 'noise'
47
- end
48
-
49
- it_should_behave_like "class without generated accessor methods added"
50
- end
51
-
52
- describe "when different writer method called on two different morph classes" do
53
- include MorphSpecHelperMethods
54
-
55
- before :each do
56
- initialize_morph
57
- initialize_another_morph
58
- end
59
-
60
- it 'should have morph_method return appropriate methods for each class' do
61
- @morph.every = 'where'
62
- @another_morph.no = 'where'
63
-
64
- @morphed_class.morph_methods.size.should == 2
65
- @another_morphed_class.morph_methods.size.should == 2
66
-
67
- if RUBY_VERSION >= "1.9"
68
- @morphed_class.morph_methods.should == [:every,:every=]
69
- @another_morphed_class.morph_methods.should == [:no,:no=]
70
- else
71
- @morphed_class.morph_methods.should == ['every','every=']
72
- @another_morphed_class.morph_methods.should == ['no','no=']
73
- end
74
- end
75
-
76
- it 'should call morph_attributes on both objects, when one object has a reference to another' do
77
- @morph.every = 'which'
78
- @another_morph.way = 'but'
79
- @morph.loose = @another_morph
80
-
81
- attributes = @morph.morph_attributes
82
- attributes[:every].should == 'which'
83
- attributes[:loose].should == {:way => 'but'}
84
- end
85
-
86
- it 'should call morph_attributes on both objects, when one object has a reference to array of others' do
87
- @morph.every = 'which'
88
- @another_morph.way = 'but'
89
- @morph.loose = [@another_morph]
90
-
91
- attributes = @morph.morph_attributes
92
- attributes[:every].should == 'which'
93
- attributes[:loose].should == [{:way => 'but'}]
94
- end
95
-
96
- it 'should call morph_attributes on both objects, when one object has a reference to hash of others' do
97
- @morph.every = 'which'
98
- @another_morph.way = 'but'
99
- @morph.loose = { :honky_tonk => @another_morph}
100
-
101
- attributes = @morph.morph_attributes
102
- attributes[:every].should == 'which'
103
- attributes[:loose].should == { :honky_tonk => {:way => 'but'} }
104
- attributes.delete(:every)
105
- attributes = @morph.morph_attributes
106
- attributes[:every].should == 'which'
107
-
108
- attributes = @morph.class.morph_attributes
109
- attributes.should == [:every, :loose]
110
- attributes.delete(:every)
111
- attributes = @morph.class.morph_attributes
112
- attributes.should == [:every, :loose]
113
- end
114
-
115
- after :each do
116
- remove_morph_methods
117
- remove_another_morph_methods
118
- end
119
- end
120
-
121
- describe "when class definition contains methods and morph is included" do
122
- include MorphSpecHelperMethods
123
-
124
- after :all do
125
- remove_morph_methods
126
- @morphed_class.class_eval "remove_method :happy" if @morphed_class
127
- end
128
-
129
- it 'should not return methods defined in class in morph_methods list' do
130
- initialize_morph "class ExampleMorph\n include Morph\n def happy\n 'happy, joy, joy'\n end\n end"
131
- morph_methods.should be_empty
132
- end
133
- end
134
-
135
- describe "when writer method that didn't exist before is called with blank space attribute value" do
136
- before :each do
137
- remove_morph_methods
138
- @morph.noise= ' '
139
- @attribute = 'noise'
140
- end
141
-
142
- it_should_behave_like "class without generated accessor methods added"
143
- end
144
-
145
- describe 'when morph method used to set attribute value' do
146
- before :all do initialize_morph; end
147
- after :all do remove_morph_methods; end
148
-
149
- before :each do
150
- remove_morph_methods
151
- @value = '20 Mar 2008'
152
- @morph.morph('Reading', @value)
153
- @attribute = 'reading'
154
- @expected_morph_methods_count = 2
155
- end
156
-
157
- it_should_behave_like "class with generated accessor methods added"
158
-
159
- it 'should return assigned value when reader method called' do
160
- @morph.reading.should == @value
161
- end
162
- end
163
-
164
- describe 'when morph method used to set an attribute value hash' do
165
- before :all do initialize_morph; end
166
- after :all do remove_morph_methods; end
167
-
168
- before :each do
169
- remove_morph_methods
170
- @attributes = [:drink,:sugars,:milk]
171
- @morph.morph :drink => 'tea', :sugars => 2, :milk => 'yes please'
172
- @expected_morph_methods_count = 6
173
- end
174
-
175
- it_should_behave_like "class with generated accessor methods added"
176
-
177
- it 'should return assigned value when reader method called' do
178
- @morph.drink.should == 'tea'
179
- @morph.sugars.should == 2
180
- @morph.milk.should == 'yes please'
181
- end
182
-
183
- it 'should generate rails model generator script line' do
184
- @morphed_class.script_generate.should == "rails destroy model ExampleMorph; rails generate model ExampleMorph drink:string milk:string sugars:string"
185
- end
186
-
187
- it 'should generate rails model generator script line' do
188
- @morphed_class.script_generate(:generator=>'model').should == "rails destroy model ExampleMorph; rails generate model ExampleMorph drink:string milk:string sugars:string"
189
- end
190
- end
191
-
192
- =begin
193
- describe "when morph method used to set unicode attribute name with a value" do
194
- before :all do initialize_morph; end
195
- after :all do remove_morph_methods; end
196
-
197
- before :each do
198
- $KCODE = "u" unless RUBY_VERSION >= "1.9"
199
- remove_morph_methods
200
- @age = 19
201
- @attribute = "年龄"
202
- @morph.morph(@attribute, @age)
203
- @expected_morph_methods_count = 2
204
- end
205
-
206
- after :all do
207
- $KCODE = "NONE" unless RUBY_VERSION >= "1.9"
208
- end
209
-
210
- it_should_behave_like "class with generated accessor methods added"
211
-
212
- it 'should return assigned value when reader method called' do
213
- @morph.send(@attribute.to_sym) == @age
214
- end
215
- end
216
- describe "when morph method used to set japanese and latin unicode attribute name with a value" do
217
- before :all do initialize_morph; end
218
- after :all do remove_morph_methods; end
219
-
220
- before :each do
221
- $KCODE = "u" unless RUBY_VERSION >= "1.9"
222
- remove_morph_methods
223
- @age = 19
224
- @attribute = "ページビュー_graph"
225
- @morph.morph(@attribute, @age)
226
- @expected_morph_methods_count = 2
227
- end
228
-
229
- after :all do
230
- $KCODE = "NONE" unless RUBY_VERSION >= "1.9"
231
- end
232
-
233
- it_should_behave_like "class with generated accessor methods added"
234
-
235
- it 'should return assigned value when reader method called' do
236
- @morph.send(@attribute.to_sym) == @age
237
- end
238
- end
239
- =end
240
- describe 'when morph method used to set blank space attribute value' do
241
- before :each do
242
- remove_morph_methods
243
- @morph.morph('Pizza', ' ')
244
- @attribute = 'pizza'
245
- end
246
-
247
- it_should_behave_like "class without generated accessor methods added"
248
- end
249
-
250
- describe 'when morph method used to set nil attribute value' do
251
- before :each do
252
- remove_morph_methods
253
- @morph.morph('Pizza', nil)
254
- @attribute = 'pizza'
255
- end
256
-
257
- it_should_behave_like "class without generated accessor methods added"
258
- end
259
-
260
-
261
- describe "when reader method that didn't exist before is called" do
262
-
263
- include MorphSpecHelperMethods
264
-
265
- it 'should raise NoMethodError' do
266
- initialize_morph
267
- lambda { @morph.noise }.should raise_error(/undefined method `noise'/)
268
- end
269
- end
270
-
271
- describe "when reader method called that didn't exist before is a class method" do
272
-
273
- include MorphSpecHelperMethods
274
-
275
- it 'should raise NoMethodError' do
276
- initialize_morph
277
- lambda { @morph.name }.should raise_error(/undefined method `name'/)
278
- end
279
- end
280
-
281
- describe "when writer method called matches a class reader method" do
282
-
283
- before :all do initialize_morph; end
284
- after :all do remove_morph_methods; end
285
-
286
- before :each do
287
- remove_morph_methods
288
- @value = 'Morph'
289
- @morph.name = @value
290
- @attribute = 'name'
291
- @expected_morph_methods_count = 2
292
- end
293
-
294
- it_should_behave_like "class with generated accessor methods added"
295
-
296
- it 'should return assigned value when reader method called' do
297
- @morph.name.should == @value
298
- end
299
- end
300
-
301
-
302
- describe "when class= is called" do
303
-
304
- include MorphSpecHelperMethods
305
- before :all do initialize_morph; end
306
- after :all do remove_morph_methods; end
307
-
308
- it 'should throw exception if non nil object is passed' do
309
- lambda { @morph.class = 'Red' }.should raise_error(/cannot create accessor methods/)
310
- end
311
-
312
- it 'should throw exception if nil object is passed' do
313
- lambda { @morph.class = nil }.should raise_error(/cannot create accessor methods/)
314
- end
315
- end
316
-
317
- describe 'when passing block to morph_method_missing' do
318
-
319
- include MorphSpecHelperMethods
320
- before :all do initialize_morph; end
321
- after :each do remove_morph_methods; end
322
-
323
- it 'should class_eval the block' do
324
- @morph.morph_method_missing(:chunky, 'bacon') do |base, attribute|
325
- base.class_eval "def #{attribute}; 'spinach'; end"
326
- end
327
- @morph.respond_to?(:chunky).should == true
328
- @morph.chunky.should == 'spinach'
329
- @morphed_class.class_eval "remove_method :chunky"
330
- lambda { @morph.chunky }.should raise_error
331
- end
332
-
333
- it 'should class_eval the block' do
334
- @morph.morph_method_missing :chunky, 'bacon' do |base, attribute|
335
- base.class_def(attribute) { 'spinach' }
336
- end
337
- @morph.respond_to?(:chunky).should == true
338
- @morph.chunky.should == 'spinach'
339
- @morphed_class.class_eval "remove_method :chunky"
340
- lambda { @morph.chunky }.should raise_error
341
- end
342
-
343
- end
344
-
345
- describe "when converting label text to morph method name" do
346
-
347
- include MorphSpecHelperMethods
348
-
349
- it 'should covert dash to underscore' do
350
- check_convert_to_morph_method_name 'hi-time', 'hi_time'
351
- end
352
- it 'should upper case to lower case' do
353
- check_convert_to_morph_method_name 'CaSe', 'case'
354
- end
355
- it 'should convert single space to underscorce' do
356
- check_convert_to_morph_method_name 'First reading', 'first_reading'
357
- end
358
- it 'should convert multiple spaces to single underscorce' do
359
- check_convert_to_morph_method_name "First reading", 'first_reading'
360
- end
361
- it 'should convert tabs to single underscorce' do
362
- check_convert_to_morph_method_name "First\t\treading", 'first_reading'
363
- end
364
- it 'should convert new line chars to single underscorce' do
365
- check_convert_to_morph_method_name "First\r\nreading", 'first_reading'
366
- end
367
- it 'should remove leading and trailing whitespace new line chars to single underscorce' do
368
- check_convert_to_morph_method_name " \t\r\nFirst reading \t\r\n", 'first_reading'
369
- end
370
- it 'should remove trailing colon surrounded by whitespace' do
371
- check_convert_to_morph_method_name "First reading : ", 'first_reading'
372
- end
373
- it 'should remove parenthesis' do
374
- check_convert_to_morph_method_name 'Nav(GBX)', 'nav_gbx'
375
- end
376
- it 'should remove *' do
377
- check_convert_to_morph_method_name 'Change**', 'change'
378
- end
379
- it 'should convert % character to the text "percentage"' do
380
- check_convert_to_morph_method_name '% Change', 'percentage_change'
381
- end
382
- it 'should precede leading digit with an underscore character' do
383
- check_convert_to_morph_method_name '52w_high', '_52w_high'
384
- end
385
- it 'should handle unicode name' do
386
- check_convert_to_morph_method_name '年龄', '年龄'
387
- end
388
- end
389
-
390
- describe 'creating from hash' do
391
- it 'should create classes and object instances with array of hashes' do
392
- h = {
393
- "CompanyDetails"=> {
394
- "SearchItems"=> [
395
- { "CompanyDate"=> '',
396
- "CompanyIndexStatus"=> '',
397
- "DataSet"=>"LIVE",
398
- "CompanyName"=>"CANONGROVE LIMITED",
399
- "CompanyNumber"=>"SC244777" },
400
- { "CompanyDate"=>"",
401
- "CompanyIndexStatus"=>"",
402
- "DataSet"=>"LIVE",
403
- "CompanyName"=>"CANONHALL ACCOUNTANCY LTD",
404
- "CompanyNumber"=>"05110715" }
405
- ]
406
- }
407
- }
408
- company_details = Morph.from_hash(h)
409
- company_details.search_items.first.class.name.should == 'Morph::SearchItem'
410
- company_details.search_items.first.data_set.should == 'LIVE'
411
- company_details.search_items.first.company_name.should == 'CANONGROVE LIMITED'
412
- end
413
-
414
- it 'should create classes and object instances' do
415
- h = {
416
- "CompanyDetails"=> {
417
- :RegAddress=> {
418
- "AddressLine"=>["ST DAVID'S HOUSE", "WEST WING", "WOOD STREET", "CARDIFF CF10 1ES"]},
419
- "LastFullMemDate"=>"2002-03-25",
420
- "xsi:schemaLocation"=>"xmlgwdev.companieshouse.gov.uk/v1-0/schema/CompanyDetails.xsd",
421
- "HasBranchInfo"=>"0",
422
- "Mortgages"=> {
423
- "NumMortSatisfied"=>"0",
424
- "MortgageInd"=>"LT300",
425
- "NumMortOutstanding"=>"7",
426
- "NumMortPartSatisfied"=>"0",
427
- "NumMortCharges"=>"7"},
428
- "CompanyCategory"=>"Public Limited Company",
429
- "HasAppointments"=>"1",
430
- "SICCodes"=> {
431
- "SicText"=>"stadiums"},
432
- "Returns"=> {
433
- "Overdue"=>"NO",
434
- "DocumentAvailable"=>"1",
435
- "NextDueDate"=>"2003-04-22",
436
- "LastMadeUpDate"=>"2002-03-25"
437
- },
438
- "CountryOfOrigin"=>"United Kingdom",
439
- "CompanyStatus"=>"Active",
440
- "CompanyName"=>"MILLENNIUM STADIUM PLC",
441
- "InLiquidation"=>"0",
442
- "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
443
- "Accounts"=>{
444
- "Overdue"=>"NO",
445
- "DocumentAvailable"=>"1",
446
- "AccountCategory"=>"FULL",
447
- "NextDueDate"=>"2002-11-30",
448
- "LastMadeUpDate"=>"2001-04-30",
449
- "AccountRefDate"=>"0000-30-04"},
450
- "IncorporationDate"=>"1996-03-25",
451
- "CompanyNumber"=>"03176906",
452
- "xmlns"=>"http://xmlgw.companieshouse.gov.uk/v1-0"
453
- }
454
- }
455
- Object.const_set 'Company', Module.new
456
- Company.const_set 'House', Module.new
457
-
458
- company_details = Morph.from_hash(h, Company::House)
459
- company_details.class.name.should == 'Company::House::CompanyDetails'
460
- morph_methods = company_details.class.morph_methods
461
- if RUBY_VERSION >= "1.9"
462
- morph_methods.include?(:last_full_mem_date).should be_true
463
- morph_methods.include?(:accounts).should be_true
464
- morph_methods.delete(:accounts)
465
- morph_methods.include?(:accounts).should be_false
466
- morph_methods = company_details.class.morph_methods
467
- morph_methods.include?(:accounts).should be_true
468
- else
469
- morph_methods.include?('last_full_mem_date').should be_true
470
- morph_methods.include?('accounts').should be_true
471
- morph_methods.delete('accounts')
472
- morph_methods.include?('accounts').should be_false
473
- morph_methods = company_details.class.morph_methods
474
- morph_methods.include?('accounts').should be_true
475
- end
476
-
477
- company_details.accounts.class.name.should == 'Company::House::Accounts'
478
- company_details.accounts.overdue.should == 'NO'
479
- company_details.last_full_mem_date.should == "2002-03-25"
480
- company_details.sic_codes.sic_text.should == 'stadiums'
481
- company_details.reg_address.address_lines.should == ["ST DAVID'S HOUSE", "WEST WING", "WOOD STREET", "CARDIFF CF10 1ES"]
482
-
483
- list = Morph.generate_migrations company_details, :ignore=>['xmlns','xmlns_xsi','xsi_schema_location']
484
- list.size.should == 7
485
- list[0].should == "./script/generate model company_details company_category:string company_name:string company_number:string company_status:string country_of_origin:string has_appointments:string has_branch_info:string in_liquidation:string incorporation_date:date last_full_mem_date:date"
486
- list[1].should == './script/generate model accounts company_details_id:integer account_category:string account_ref_date:date document_available:string last_made_up_date:date next_due_date:date overdue:string'
487
- list[2].should == './script/generate model mortgages company_details_id:integer mortgage_ind:string num_mort_charges:string num_mort_outstanding:string num_mort_part_satisfied:string num_mort_satisfied:string'
488
- list[3].should == './script/generate model reg_address company_details_id:integer'
489
- list[4].should == './script/generate model address_lines reg_address_id:integer'
490
- list[5].should == './script/generate model returns company_details_id:integer document_available:string last_made_up_date:date next_due_date:date overdue:string'
491
- list[6].should == './script/generate model sic_codes company_details_id:integer sic_text:string'
492
-
493
- yaml = %Q|--- !ruby/object:Company::House::CompanyDetails
494
- accounts: !ruby/object:Company::House::Accounts
495
- account_category: FULL
496
- account_ref_date: "0000-30-04"
497
- document_available: "1"
498
- last_made_up_date: "2001-04-30"
499
- next_due_date: "2002-11-30"
500
- overdue: "NO"
501
- company_category: Public Limited Company
502
- company_name: MILLENNIUM STADIUM PLC
503
- company_number: 03176906
504
- company_status: Active
505
- country_of_origin: United Kingdom
506
- has_appointments: "1"
507
- has_branch_info: "0"
508
- in_liquidation: "0"
509
- incorporation_date: "1996-03-25"
510
- last_full_mem_date: "2002-03-25"
511
- mortgages: !ruby/object:Company::House::Mortgages
512
- mortgage_ind: LT300
513
- num_mort_charges: "7"
514
- num_mort_outstanding: "7"
515
- num_mort_part_satisfied: "0"
516
- num_mort_satisfied: "0"
517
- reg_address: !ruby/object:Company::House::RegAddress
518
- address_lines:
519
- - ST DAVID'S HOUSE
520
- - WEST WING
521
- - WOOD STREET
522
- - CARDIFF CF10 1ES
523
- returns: !ruby/object:Company::House::Returns
524
- document_available: "1"
525
- last_made_up_date: "2002-03-25"
526
- next_due_date: "2003-04-22"
527
- overdue: "NO"
528
- sic_codes: !ruby/object:Company::House::SICCodes
529
- sic_text: stadiums
530
- xmlns: http://xmlgw.companieshouse.gov.uk/v1-0
531
- xmlns_xsi: http://www.w3.org/2001/XMLSchema-instance
532
- xsi_schema_location: xmlgwdev.companieshouse.gov.uk/v1-0/schema/CompanyDetails.xsd|
533
- end
534
- end
535
-
536
- describe 'creating from xml' do
537
-
538
- def check_councils councils, class_name
539
- councils.class.should == Array
540
- councils.size.should == 2
541
- councils.first.class.name.should == class_name
542
- councils.first.name.should == 'Aberdeen City Council'
543
- councils.last.name.should == 'Allerdale Borough Council'
544
- end
545
-
546
- it 'should create classes and object instances' do
547
- councils = Morph.from_xml(xml)
548
- check_councils councils, 'Morph::Council'
549
- end
550
-
551
- describe 'when module name is supplied' do
552
- it 'should create classes and object instances' do
553
- Object.const_set 'Ppc', Module.new
554
- councils = Morph.from_xml(xml, Ppc)
555
- check_councils councils, 'Ppc::Council'
556
- end
557
- end
558
-
559
- def xml
560
- %Q[<?xml version="1.0" encoding="UTF-8"?>
561
- <councils type="array">
562
- <council code='1'>
563
- <name>Aberdeen City Council</name>
564
- </council>
565
- <council code='2'>
566
- <name>Allerdale Borough Council</name>
567
- </council>
568
- </councils>]
569
- end
570
- end
571
-
572
- describe 'creating from' do
573
-
574
- def check_councillors councillors, class_name, nil_value=''
575
- councillors.class.should == Array
576
- councillors.size.should == 2
577
- councillor = councillors.first
578
- councillor.class.name.should == class_name
579
- councillor.name.should == 'Ted Roe'
580
- councillor.party.should == 'labour'
581
- councillor.councillors.should == 'Councillor for Stretford Ward'
582
- councillor.councils.should == 'Trafford Council'
583
- councillor.respond_to?(:council_experience).should be_false
584
-
585
- councillor = councillors.last
586
- councillor.name.should == 'Ali Davidson'
587
- councillor.party.should == 'labour'
588
- councillor.councillors.should == nil_value
589
- councillor.councils.should == 'Basildon District Council'
590
- councillor.respond_to?(:council_experience).should be_false
591
- end
592
-
593
- describe 'tsv (tab separated value)' do
594
- describe 'when class name is supplied' do
595
- it 'should create classes and object instances' do
596
- councillors = Morph.from_tsv(tsv, 'Councillor')
597
- check_councillors councillors, 'Morph::Councillor'
598
- end
599
- end
600
-
601
- describe 'when class name and module name is supplied' do
602
- it 'should create classes and object instances' do
603
- Object.const_set 'Ppc', Module.new unless defined? Ppc
604
- councillors = Morph.from_tsv(tsv, 'Councillor', Ppc)
605
- check_councillors councillors, 'Ppc::Councillor'
606
- end
607
- end
608
-
609
- def tsv
610
- %Q[name party councillors councils council_experience
611
- Ted Roe labour Councillor for Stretford Ward Trafford Council
612
- Ali Davidson labour Basildon District Council
613
- ]
614
- end
615
- end
616
-
617
- describe 'csv (comma separated value)' do
618
- describe 'when class name is supplied' do
619
- it 'should create classes and object instances' do
620
- councillors = Morph.from_csv(csv, 'Councillor')
621
- check_councillors councillors, 'Morph::Councillor', nil
622
- end
623
- end
624
-
625
- describe 'when class name and module name is supplied' do
626
- it 'should create classes and object instances' do
627
- Object.const_set 'Ppc', Module.new unless defined? Ppc
628
- councillors = Morph.from_csv(csv, 'Councillor', Ppc)
629
- check_councillors councillors, 'Ppc::Councillor', nil
630
- end
631
- end
632
-
633
- def csv
634
- %Q[name,party,councillors,councils,council_experience
635
- Ted Roe,labour,Councillor for Stretford Ward,Trafford Council,
636
- Ali Davidson,labour,,Basildon District Council,
637
- ]
638
- end
639
- end
640
- end
641
-
642
- end
@@ -1,147 +0,0 @@
1
- # encoding: utf-8
2
- require File.dirname(__FILE__) + '/../lib/morph'
3
-
4
- module MorphSpecHelperMethods
5
-
6
- def initialize_morph_class code=nil
7
- code = 'class ExampleMorph; include Morph; end' unless code
8
- eval code
9
- @morphed_class = ExampleMorph
10
- end
11
-
12
- def initialize_second_morph_class code=nil
13
- code = 'class AnotherMorph; include Morph; end' unless code
14
- eval code
15
- @another_morphed_class = AnotherMorph
16
- end
17
-
18
- def initialize_morph code=nil
19
- initialize_morph_class code
20
- @original_instance_methods = @morphed_class.instance_methods
21
- @morph = @morphed_class.new
22
- end
23
-
24
- def initialize_another_morph
25
- initialize_second_morph_class
26
- @more_original_instance_methods = @another_morphed_class.instance_methods
27
- @another_morph = @another_morphed_class.new
28
- end
29
-
30
- def remove_morph_methods
31
- @morphed_class.instance_methods.each do |method|
32
- begin
33
- unless method.to_s[/received_message\?|should_not_receive|rspec_verify|unstub|rspec_reset|should_receive|as_null_object|stub_chain|stub\!|null_object?|stub/]
34
- remove_cmd = "remove_method :#{method}"
35
- @morphed_class.class_eval remove_cmd unless @original_instance_methods.include?(method)
36
- end
37
- rescue Exception => e
38
- raise e.to_s + '------' + @original_instance_methods.sort.inspect
39
- end
40
-
41
- end if @morphed_class
42
- end
43
-
44
- def remove_another_morph_methods
45
- @another_morphed_class.instance_methods.each do |method|
46
- @another_morphed_class.class_eval "remove_method :#{method}" unless @more_original_instance_methods.include?(method)
47
- end
48
- end
49
-
50
- def instance_methods
51
- @morphed_class.instance_methods
52
- end
53
-
54
- def morph_methods
55
- @morphed_class.morph_methods
56
- end
57
-
58
- def check_convert_to_morph_method_name label, method_name
59
- code = 'class ExampleMorph; include Morph; def convert_to_morph_method_name label; super; end; end'
60
- eval code
61
- ExampleMorph.new.convert_to_morph_method_name(label).should == method_name
62
- end
63
-
64
- def each_attribute
65
- if @attribute
66
- yield @attribute
67
- elsif @attributes
68
- @attributes.each {|a| yield a }
69
- end
70
- end
71
- end
72
-
73
- shared_examples_for "class with generated accessor methods added" do
74
-
75
- include MorphSpecHelperMethods
76
- before :all do initialize_morph; end
77
- after :all do remove_morph_methods; end
78
-
79
- it 'should add reader method to class instance_methods list' do
80
- if RUBY_VERSION >= "1.9"
81
- each_attribute { |a| instance_methods.should include(a.to_s.to_sym) }
82
- else
83
- each_attribute { |a| instance_methods.should include(a.to_s) }
84
- end
85
- end
86
-
87
- it 'should add writer method to class instance_methods list' do
88
- if RUBY_VERSION >= "1.9"
89
- each_attribute { |a| instance_methods.should include("#{a}=".to_sym) }
90
- else
91
- each_attribute { |a| instance_methods.should include("#{a}=") }
92
- end
93
- end
94
-
95
- it 'should add reader method to class morph_methods list' do
96
- if RUBY_VERSION >= "1.9"
97
- each_attribute { |a| morph_methods.should include(a.to_s.to_sym) }
98
- else
99
- each_attribute { |a| morph_methods.should include(a.to_s) }
100
- end
101
- end
102
-
103
- it 'should add writer method to class morph_methods list' do
104
- if RUBY_VERSION >= "1.9"
105
- each_attribute { |a| morph_methods.should include("#{a}=".to_sym) }
106
- else
107
- each_attribute { |a| morph_methods.should include("#{a}=") }
108
- end
109
- end
110
-
111
- it 'should only have generated accessor methods in morph_methods list' do
112
- morph_methods.size.should == @expected_morph_methods_count
113
- end
114
-
115
- end
116
-
117
- shared_examples_for "class without generated accessor methods added" do
118
- include MorphSpecHelperMethods
119
-
120
- before :all do
121
- initialize_morph
122
- end
123
-
124
- after :all do
125
- remove_morph_methods
126
- end
127
-
128
- it 'should not add reader method to class instance_methods list' do
129
- instance_methods.should_not include(@attribute)
130
- end
131
-
132
- it 'should not add writer method to class instance_methods list' do
133
- instance_methods.should_not include("#{@attribute}=")
134
- end
135
-
136
- it 'should not add reader method to class morph_methods list' do
137
- morph_methods.should_not include(@attribute)
138
- end
139
-
140
- it 'should not add writer method to class morph_methods list' do
141
- morph_methods.should_not include("#{@attribute}=")
142
- end
143
-
144
- it 'should have empty morph_methods list' do
145
- morph_methods.size.should == 0
146
- end
147
- end
data/spec/spec_helper.rb DELETED
@@ -1,3 +0,0 @@
1
- RSpec.configure do |config|
2
- config.mock_with :rspec
3
- end