morph 0.2.8 → 0.2.9
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/CHANGELOG +2 -0
- data/README +40 -1
- data/Rakefile +1 -0
- data/lib/morph.rb +31 -6
- data/morph.gemspec +6 -6
- data/spec/lib/morph_spec.rb +63 -22
- metadata +23 -11
data/CHANGELOG
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
v0.2.9. added from_csv(); require fastercsv; added morph_attributes() class method
|
2
|
+
|
1
3
|
v0.2.8. added from_xml() and from_tsv(); updated for active_support; fixed from_hash() when hash root is an array
|
2
4
|
|
3
5
|
v0.2.7. handle dash when converting to method name, reported by danwrong
|
data/README
CHANGED
@@ -1,12 +1,51 @@
|
|
1
1
|
Morph allows you to emerge class definitions via calling assignment methods; mix with Hpricot for screen scrapping fun.
|
2
2
|
|
3
3
|
|
4
|
+
== Morph creating classes +from_xml+
|
5
|
+
|
6
|
+
Here's example code showing Morph playing with XML:
|
7
|
+
|
8
|
+
require 'rubygems'; require 'morph'
|
9
|
+
|
10
|
+
xml = %Q[<?xml version="1.0" encoding="UTF-8"?>
|
11
|
+
<councils type="array">
|
12
|
+
<council code='1'>
|
13
|
+
<name>Aberdeen City Council</name>
|
14
|
+
</council>
|
15
|
+
<council code='2'>
|
16
|
+
<name>Allerdale Borough Council</name>
|
17
|
+
</council>
|
18
|
+
</councils>]
|
19
|
+
|
20
|
+
councils = Morph.from_xml(xml)
|
21
|
+
# => [#<Morph::Council @code="1", @name="Aberdeen City Council">,
|
22
|
+
#<Morph::Council @code="2", @name="Allerdale Borough Council">]
|
23
|
+
|
24
|
+
councils.first.name
|
25
|
+
# => "Aberdeen City Council"
|
26
|
+
|
27
|
+
== Morph creating classes +from_tsv+
|
28
|
+
|
29
|
+
Here's example code showing Morph playing with TSV (tab-separated values):
|
30
|
+
|
31
|
+
require 'rubygems'; require 'morph'
|
32
|
+
|
33
|
+
tsv = %Q[name\tparty\nTed Roe\tred\nAli Davidson\tblue\nSue Smith\tgreen]
|
34
|
+
|
35
|
+
people = Morph.from_tsv(tsv, 'person')
|
36
|
+
# => [#<Morph::Person @name="Ted Roe", @party="red">,
|
37
|
+
#<Morph::Person @name="Ali Davidson", @party="blue">,
|
38
|
+
#<Morph::Person @name="Sue Smith", @party="green">]
|
39
|
+
|
40
|
+
people.last.party
|
41
|
+
# => "green"
|
4
42
|
|
5
43
|
== Morph playing with +Hpricot+
|
6
44
|
|
7
45
|
Here's example code showing Morph playing with Hpricot:
|
8
46
|
|
9
|
-
require '
|
47
|
+
require 'rubygems'; require 'hpricot'; require 'open-uri'
|
48
|
+
require 'morph'
|
10
49
|
|
11
50
|
class Hubbit
|
12
51
|
include Morph # allows class to morph
|
data/Rakefile
CHANGED
data/lib/morph.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'fastercsv'
|
1
2
|
begin
|
2
3
|
require 'active_support/core_ext/object/blank'
|
3
4
|
require 'active_support/inflector'
|
@@ -13,7 +14,7 @@ rescue Exception => e
|
|
13
14
|
end
|
14
15
|
|
15
16
|
module Morph
|
16
|
-
VERSION = "0.2.
|
17
|
+
VERSION = "0.2.9"
|
17
18
|
|
18
19
|
class << self
|
19
20
|
def generate_migrations object, options={}
|
@@ -24,6 +25,18 @@ module Morph
|
|
24
25
|
add_migration name, object.morph_attributes, migrations, options
|
25
26
|
end
|
26
27
|
|
28
|
+
def from_csv csv, class_name, namespace=Morph
|
29
|
+
objects = []
|
30
|
+
FasterCSV.parse(csv, { :headers => true }) do |row|
|
31
|
+
object = object_from_name class_name, namespace
|
32
|
+
row.each do |key, value|
|
33
|
+
object.morph(key, value)
|
34
|
+
end
|
35
|
+
objects << object
|
36
|
+
end
|
37
|
+
objects
|
38
|
+
end
|
39
|
+
|
27
40
|
def from_tsv tsv, class_name, namespace=Morph
|
28
41
|
lines = tsv.split("\n")
|
29
42
|
attributes = lines[0].split("\t")
|
@@ -85,8 +98,7 @@ module Morph
|
|
85
98
|
type = attribute_name[/date$/] ? 'date' : 'string'
|
86
99
|
attribute_def = "#{attribute}:#{type}"
|
87
100
|
migration.sub!(migration, "#{migration} #{attribute_def}")
|
88
|
-
end
|
89
|
-
when Array
|
101
|
+
end when Array
|
90
102
|
options[:belongs_to_id] = " #{name}_id:integer"
|
91
103
|
migrations = add_migration(attribute, '', migrations, options)
|
92
104
|
when Hash
|
@@ -155,6 +167,11 @@ module Morph
|
|
155
167
|
|
156
168
|
@@adding_morph_method = Hash.new {|hash,klass| hash[klass] = false }
|
157
169
|
@@morph_methods = Hash.new {|hash,klass| hash[klass] = {} }
|
170
|
+
@@morph_attributes = Hash.new {|hash,klass| hash[klass] = [] }
|
171
|
+
|
172
|
+
def morph_attributes
|
173
|
+
@@morph_attributes[self] + []
|
174
|
+
end
|
158
175
|
|
159
176
|
def morph_methods
|
160
177
|
@@morph_methods[self].keys.sort
|
@@ -189,11 +206,19 @@ module Morph
|
|
189
206
|
protected
|
190
207
|
|
191
208
|
def method_added symbol
|
192
|
-
|
209
|
+
if @@adding_morph_method[self]
|
210
|
+
@@morph_methods[self][symbol.to_s] = true
|
211
|
+
is_writer = symbol.to_s =~ /=$/
|
212
|
+
@@morph_attributes[self] << symbol unless is_writer
|
213
|
+
end
|
193
214
|
end
|
194
215
|
|
195
216
|
def method_removed symbol
|
196
|
-
|
217
|
+
if @@morph_methods[self].has_key? symbol.to_s
|
218
|
+
@@morph_methods[self].delete symbol.to_s
|
219
|
+
is_writer = symbol.to_s =~ /=$/
|
220
|
+
@@morph_attributes[self].delete(symbol) unless is_writer
|
221
|
+
end
|
197
222
|
end
|
198
223
|
|
199
224
|
end
|
@@ -282,7 +307,7 @@ module Morph
|
|
282
307
|
end
|
283
308
|
|
284
309
|
def convert_to_morph_method_name label
|
285
|
-
name = label.to_s.downcase.tr('()\-*',' ').gsub('%','percentage').strip.chomp(':').strip.gsub(/\s/,'_').squeeze('_')
|
310
|
+
name = label.to_s.downcase.tr('()\-*',' ').gsub("'",' ').gsub('/',' ').gsub('%','percentage').strip.chomp(':').strip.gsub(/\s/,'_').squeeze('_')
|
286
311
|
name = '_'+name if name =~ /^\d/
|
287
312
|
name
|
288
313
|
end
|
data/morph.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{morph}
|
5
|
-
s.version = "0.2.
|
5
|
+
s.version = "0.2.9"
|
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 = %q{2010-
|
9
|
+
s.date = %q{2010-04-04}
|
10
10
|
s.description = %q{Morph allows you to emerge class definitions via calling assignment methods; mix with Hpricot for screen scrapping fun.
|
11
11
|
}
|
12
12
|
s.email = ["rob ~@nospam@~ rubyforge.org"]
|
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
|
|
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 = %q{morph}
|
19
|
-
s.rubygems_version = %q{1.3.
|
19
|
+
s.rubygems_version = %q{1.3.6}
|
20
20
|
s.summary = %q{Morph allows you to emerge class definitions via calling assignment methods; mix with Hpricot for screen scrapping fun.}
|
21
21
|
|
22
22
|
if s.respond_to? :specification_version then
|
@@ -24,11 +24,11 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.specification_version = 3
|
25
25
|
|
26
26
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
-
s.add_runtime_dependency(%q<
|
27
|
+
s.add_runtime_dependency(%q<fastercsv>, [">= 1.5.0"])
|
28
28
|
else
|
29
|
-
s.add_dependency(%q<
|
29
|
+
s.add_dependency(%q<fastercsv>, [">= 1.5.0"])
|
30
30
|
end
|
31
31
|
else
|
32
|
-
s.add_dependency(%q<
|
32
|
+
s.add_dependency(%q<fastercsv>, [">= 1.5.0"])
|
33
33
|
end
|
34
34
|
end
|
data/spec/lib/morph_spec.rb
CHANGED
@@ -91,6 +91,15 @@ describe Morph do
|
|
91
91
|
attributes = @morph.morph_attributes
|
92
92
|
attributes[:every].should == 'which'
|
93
93
|
attributes[:loose].should == { :honky_tonk => {:way => 'but'} }
|
94
|
+
attributes.delete(:every)
|
95
|
+
attributes = @morph.morph_attributes
|
96
|
+
attributes[:every].should == 'which'
|
97
|
+
|
98
|
+
attributes = @morph.class.morph_attributes
|
99
|
+
attributes.should == [:every, :loose]
|
100
|
+
attributes.delete(:every)
|
101
|
+
attributes = @morph.class.morph_attributes
|
102
|
+
attributes.should == [:every, :loose]
|
94
103
|
end
|
95
104
|
|
96
105
|
after :each do
|
@@ -424,9 +433,15 @@ describe Morph do
|
|
424
433
|
|
425
434
|
company_details = Morph.from_hash(h, Company::House)
|
426
435
|
company_details.class.name.should == 'Company::House::CompanyDetails'
|
427
|
-
company_details.class.morph_methods
|
428
|
-
|
429
|
-
|
436
|
+
morph_methods = company_details.class.morph_methods
|
437
|
+
morph_methods.include?('last_full_mem_date').should be_true
|
438
|
+
morph_methods.include?('accounts').should be_true
|
439
|
+
|
440
|
+
morph_methods.delete('accounts')
|
441
|
+
morph_methods.include?('accounts').should be_false
|
442
|
+
morph_methods = company_details.class.morph_methods
|
443
|
+
morph_methods.include?('accounts').should be_true
|
444
|
+
|
430
445
|
company_details.accounts.class.name.should == 'Company::House::Accounts'
|
431
446
|
company_details.accounts.overdue.should == 'NO'
|
432
447
|
company_details.last_full_mem_date.should == "2002-03-25"
|
@@ -512,19 +527,19 @@ xsi_schema_location: xmlgwdev.companieshouse.gov.uk/v1-0/schema/CompanyDetails.x
|
|
512
527
|
def xml
|
513
528
|
%Q[<?xml version="1.0" encoding="UTF-8"?>
|
514
529
|
<councils type="array">
|
515
|
-
<council>
|
530
|
+
<council code='1'>
|
516
531
|
<name>Aberdeen City Council</name>
|
517
532
|
</council>
|
518
|
-
<council>
|
533
|
+
<council code='2'>
|
519
534
|
<name>Allerdale Borough Council</name>
|
520
535
|
</council>
|
521
536
|
</councils>]
|
522
537
|
end
|
523
538
|
end
|
524
539
|
|
525
|
-
describe 'creating from
|
540
|
+
describe 'creating from' do
|
526
541
|
|
527
|
-
def check_councillors councillors, class_name
|
542
|
+
def check_councillors councillors, class_name, nil_value=''
|
528
543
|
councillors.class.should == Array
|
529
544
|
councillors.size.should == 2
|
530
545
|
councillor = councillors.first
|
@@ -538,31 +553,57 @@ xsi_schema_location: xmlgwdev.companieshouse.gov.uk/v1-0/schema/CompanyDetails.x
|
|
538
553
|
councillor = councillors.last
|
539
554
|
councillor.name.should == 'Ali Davidson'
|
540
555
|
councillor.party.should == 'labour'
|
541
|
-
councillor.councillors.should ==
|
556
|
+
councillor.councillors.should == nil_value
|
542
557
|
councillor.councils.should == 'Basildon District Council'
|
543
558
|
councillor.respond_to?(:council_experience).should be_false
|
544
559
|
end
|
545
560
|
|
546
|
-
describe '
|
547
|
-
|
548
|
-
|
549
|
-
|
561
|
+
describe 'tsv (tab separated value)' do
|
562
|
+
describe 'when class name is supplied' do
|
563
|
+
it 'should create classes and object instances' do
|
564
|
+
councillors = Morph.from_tsv(tsv, 'Councillor')
|
565
|
+
check_councillors councillors, 'Morph::Councillor'
|
566
|
+
end
|
550
567
|
end
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
568
|
+
|
569
|
+
describe 'when class name and module name is supplied' do
|
570
|
+
it 'should create classes and object instances' do
|
571
|
+
Object.const_set 'Ppc', Module.new
|
572
|
+
councillors = Morph.from_tsv(tsv, 'Councillor', Ppc)
|
573
|
+
check_councillors councillors, 'Ppc::Councillor'
|
574
|
+
end
|
558
575
|
end
|
559
|
-
end
|
560
576
|
|
561
|
-
|
562
|
-
%Q[name party councillors councils council_experience
|
577
|
+
def tsv
|
578
|
+
%Q[name party councillors councils council_experience
|
563
579
|
Ted Roe labour Councillor for Stretford Ward Trafford Council
|
564
580
|
Ali Davidson labour Basildon District Council
|
565
581
|
]
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
describe 'csv (comma separated value)' do
|
586
|
+
describe 'when class name is supplied' do
|
587
|
+
it 'should create classes and object instances' do
|
588
|
+
councillors = Morph.from_csv(csv, 'Councillor')
|
589
|
+
check_councillors councillors, 'Morph::Councillor', nil
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
593
|
+
describe 'when class name and module name is supplied' do
|
594
|
+
it 'should create classes and object instances' do
|
595
|
+
Object.const_set 'Ppc', Module.new
|
596
|
+
councillors = Morph.from_csv(csv, 'Councillor', Ppc)
|
597
|
+
check_councillors councillors, 'Ppc::Councillor', nil
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
def csv
|
602
|
+
%Q[name,party,councillors,councils,council_experience
|
603
|
+
Ted Roe,labour,Councillor for Stretford Ward,Trafford Council,
|
604
|
+
Ali Davidson,labour,,Basildon District Council,
|
605
|
+
]
|
606
|
+
end
|
566
607
|
end
|
567
608
|
end
|
568
609
|
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: morph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 9
|
9
|
+
version: 0.2.9
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Rob McKinnon
|
@@ -9,19 +14,23 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-04-04 00:00:00 +01:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
name: fastercsv
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 5
|
30
|
+
- 0
|
31
|
+
version: 1.5.0
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
25
34
|
description: |
|
26
35
|
Morph allows you to emerge class definitions via calling assignment methods; mix with Hpricot for screen scrapping fun.
|
27
36
|
|
@@ -67,18 +76,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
67
76
|
requirements:
|
68
77
|
- - ">="
|
69
78
|
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 0
|
70
81
|
version: "0"
|
71
|
-
version:
|
72
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
83
|
requirements:
|
74
84
|
- - ">="
|
75
85
|
- !ruby/object:Gem::Version
|
86
|
+
segments:
|
87
|
+
- 1
|
88
|
+
- 2
|
76
89
|
version: "1.2"
|
77
|
-
version:
|
78
90
|
requirements: []
|
79
91
|
|
80
92
|
rubyforge_project: morph
|
81
|
-
rubygems_version: 1.3.
|
93
|
+
rubygems_version: 1.3.6
|
82
94
|
signing_key:
|
83
95
|
specification_version: 3
|
84
96
|
summary: Morph allows you to emerge class definitions via calling assignment methods; mix with Hpricot for screen scrapping fun.
|