adaptation 0.1.10 → 1.0.1
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 +7 -0
- data/README +90 -12
- data/helpers/publish.rb +1 -1
- data/helpers/test_helper.rb +4 -0
- data/lib/adaptation.rb +2 -1
- data/lib/adaptation/adaptor.rb +25 -8
- data/lib/adaptation/base.rb +4 -9
- data/lib/adaptation/message.rb +140 -244
- data/lib/adaptation/test/test_help.rb +28 -47
- data/lib/adaptation/validateable.rb +112 -12
- data/lib/adaptation/version.rb +3 -3
- data/lib/rails_generator/generators/components/adaptor/templates/functional_test.rb +3 -4
- data/lib/rails_generator/generators/components/message/templates/unit_test.rb +2 -10
- metadata +7 -7
data/CHANGELOG
CHANGED
@@ -65,3 +65,10 @@
|
|
65
65
|
- bug: test environment not set properly since 0.1.7
|
66
66
|
* 0.1.10
|
67
67
|
- generated mock publish.rb bug corrected
|
68
|
+
-------------------
|
69
|
+
* 1.0.0
|
70
|
+
- Migrated from ROXML to XmlSimple. Messages don't need to be defined any more, so
|
71
|
+
has_many, has_one... and partials are deprecated.
|
72
|
+
* 1.0.1
|
73
|
+
- Fixed problems with activerecord > 2.2.2
|
74
|
+
- Requires activerecord >= 2.3.3
|
data/README
CHANGED
@@ -40,8 +40,7 @@ Adaptation is available as a ruby gem, so the easiest way should be:
|
|
40
40
|
|
41
41
|
This will generate a an adaptor file tree under folder _myadaptor_.
|
42
42
|
|
43
|
-
2. If no message oriented middleware has been already set,
|
44
|
-
and start the <b>mom</b>:
|
43
|
+
2. If no message oriented middleware (mom) has been already set, you can start one typing:
|
45
44
|
|
46
45
|
> mom
|
47
46
|
|
@@ -50,14 +49,14 @@ Adaptation is available as a ruby gem, so the easiest way should be:
|
|
50
49
|
3. Subscribe your adaptor to the <b>mom</b>, so it will be executed when a message is received on
|
51
50
|
a topic your adaptor is interested in:
|
52
51
|
|
53
|
-
> script/subscribe
|
52
|
+
> ruby script/subscribe
|
54
53
|
|
55
54
|
By default this will try to subscribe to a *mom* listening on <em>localhost:8080</em>, using port
|
56
55
|
<em>8081</em> to subscribe (subscribing means starting a new server that listens for
|
57
56
|
message publication notifications). These values can be changed editing <em>config/mom.yml</em>. In <em>mom.yml</em>
|
58
57
|
you can also specify wich topics your adaptor is interested in.
|
59
58
|
|
60
|
-
4. Right now you should have a <b>mom</b>
|
59
|
+
4. Right now you should have a <b>mom</b> listening for messages on <em>localhost:8080</em>, and an _adaptor_
|
61
60
|
subscribed to that *mom* and listening on <em>localhost:8081</em>, and interested in all topics available.
|
62
61
|
|
63
62
|
This environment can be tested by executing the following from _myadaptor_ folder:
|
@@ -68,8 +67,8 @@ Adaptation is available as a ruby gem, so the easiest way should be:
|
|
68
67
|
This message should be displayed in the subscriber terminal when delivered by the *mom*.
|
69
68
|
Nothing would be executed, because a _Helloworld_ message[link:../rdoc/classes/Adaptation/Message.html] to
|
70
69
|
map this xml message and a _HelloworldAdaptor_[link:../rdoc/classes/Adaptation/Adaptor.html] to process it don't
|
71
|
-
exist yet. Since these classes aren't implemented, Adaptation will pass the message as
|
72
|
-
default _ApplicationAdaptor_ adaptor, but its _process_ method is still empty, so nothing will happen.
|
70
|
+
exist yet. Since these classes aren't implemented, Adaptation will pass the message as an Adaptation::Message object
|
71
|
+
to the default _ApplicationAdaptor_ adaptor, but its _process_ method is still empty, so nothing will happen.
|
73
72
|
|
74
73
|
To see something happening the _process_ method in the default _ApplicationAdaptor_ could be implemented,
|
75
74
|
editing file <em>myadaptor/app/adaptors/application.rb</em>:
|
@@ -109,8 +108,7 @@ Adaptation is available as a ruby gem, so the easiest way should be:
|
|
109
108
|
create app/adaptors/helloworld_adaptor.rb
|
110
109
|
create test/functional/helloworld_adaptor_test.rb
|
111
110
|
|
112
|
-
and to edit <em>app/adaptors/helloworld_adaptor</em> to make something happen
|
113
|
-
when a message is received:
|
111
|
+
and to edit <em>app/adaptors/helloworld_adaptor</em> to make something happen when a message is received:
|
114
112
|
|
115
113
|
class HelloworldAdaptor < ApplicationAdaptor
|
116
114
|
|
@@ -120,8 +118,8 @@ Adaptation is available as a ruby gem, so the easiest way should be:
|
|
120
118
|
|
121
119
|
end
|
122
120
|
|
123
|
-
We can notice that _helloworld_ variable is
|
124
|
-
has been able to map it to a Adaptation::Message object, and that the _HelloworldAdaptor_
|
121
|
+
We can notice that _helloworld_ variable is an instance of _Helloworld_ class (because Adaptation
|
122
|
+
has been able to map it to a subclass of Adaptation::Message object), and that the _HelloworldAdaptor_
|
125
123
|
inherits from _ApplicationAdaptor_, so functionality repeated in different _Adaptors_[link:../rdoc/classes/Adaptation/Adaptor.html]
|
126
124
|
can be placed in _ApplicationAdaptor_.
|
127
125
|
|
@@ -186,7 +184,87 @@ test
|
|
186
184
|
|
187
185
|
|
188
186
|
== Debugging
|
189
|
-
|
187
|
+
|
188
|
+
Adaptation includes a console from wich we can access Adaptation::Message and ActiveRecord classes defined in
|
189
|
+
the <em>adaptor</em> we are working on.
|
190
|
+
|
191
|
+
To open the console type:
|
192
|
+
|
193
|
+
> ruby script/console [environment]
|
194
|
+
|
195
|
+
From the command prompt that should appear, we can instantiate ActiveRecord objects defined in app/models and
|
196
|
+
Adaptation::Message objects defined in app/messages.
|
197
|
+
With the previous example, where an Adaptation::Message subclass called Helloworld was defined in app/messages,
|
198
|
+
we could do:
|
199
|
+
|
200
|
+
> ruby script/console test
|
201
|
+
$ >> Loading test environment (Adaptation X.X.X)
|
202
|
+
$ hw = HelloWorld.new("<helloworld>hello</helloworld>")
|
203
|
+
$ hw.content
|
204
|
+
$ >> "hello"
|
205
|
+
$ hw.to_xml
|
206
|
+
$ >> "<helloworld>hello</helloworld>"
|
207
|
+
|
208
|
+
We could edit app/messages/hellworld.rb to add a validation:
|
209
|
+
|
210
|
+
class Helloworld < Adaptation::Message
|
211
|
+
validates_presence_of :atr
|
212
|
+
end
|
213
|
+
|
214
|
+
and check if it works with the console:
|
215
|
+
|
216
|
+
> ruby script/console
|
217
|
+
$ >> Loading test environment (Adaptation X.X.X)
|
218
|
+
$ hw = HelloWorld.new("<helloworld>hello</helloworld>")
|
219
|
+
$ hw.valid?
|
220
|
+
$ >> false
|
221
|
+
$ hw = HelloWorld.new("<helloworld atr="something">hello</helloworld>")
|
222
|
+
$ hw.valid?
|
223
|
+
$ >> true
|
224
|
+
|
225
|
+
If we define ActiveRecord::Base subclasses in app/models we can do the same mapping
|
226
|
+
database rows instead of xml messages, if config/database.yml is properly configured
|
227
|
+
to access the database.
|
228
|
+
If we had a <em>users</em> table in our database, we could generate a model to access
|
229
|
+
it with ActiveRecord:
|
230
|
+
|
231
|
+
> ruby script/generate model user
|
232
|
+
exists app/models/
|
233
|
+
exists test/fixtures/
|
234
|
+
create app/models/user.rb
|
235
|
+
|
236
|
+
and use it from the console:
|
237
|
+
|
238
|
+
> ruby script/console
|
239
|
+
$ >> Loading test environment (Adaptation X.X.X)
|
240
|
+
$ u = User.find(:first)
|
241
|
+
|
190
242
|
|
191
243
|
== Testing
|
192
|
-
|
244
|
+
|
245
|
+
As it can be seen when generating adaptors and messages, adaptation automatically generates empty functional
|
246
|
+
tests for adaptors and empty unit tests for messages.
|
247
|
+
|
248
|
+
Tests can be run typing:
|
249
|
+
|
250
|
+
> ruby test.rb
|
251
|
+
|
252
|
+
Tests can use fixtures stored in <em>test/fixtures</em> folder. There are two kind of fixtures:
|
253
|
+
|
254
|
+
- <b>database fixtures</b>: the same database fixtures a {rails}[http://www.rubyonrails.org] application uses to fill its tables in tests. These fixtures are usually stored in <em>*.yml</em> files, and are used to reset database contents before each test, so it is important to configure the test database properly in config/database.yml. More about ActiveRecord fixtures {here}[http://api.rubyonrails.org/classes/Fixtures.html].
|
255
|
+
|
256
|
+
- <b>xml fixtures</b>: these fixtures are plain xml strored in <em>*.xml</em>, and are used to build Adaptation::Message objects and probably process them with our adaptor in the tests. These fixtures can also be created dynamically with Erb templetes. This is an example of a xml fixture built with Erb:
|
257
|
+
|
258
|
+
<20_people>
|
259
|
+
<% 20.times do |c| %>
|
260
|
+
<person num="<%= c %>"/>
|
261
|
+
<% end %>
|
262
|
+
</20_people>
|
263
|
+
|
264
|
+
For the _HellworldAdaptor_ in our example, we should find a functional test in <em>test/functional/helloworld_adaptor_test.rb</em>, and for the _Helloworld_ message a unit test in <em>test/unit/helloworld_test.rb</em>.
|
265
|
+
|
266
|
+
Tests usually perfrom {assertions}[link:../rdoc/classes/ActiveSupport/TestCase.html]. There are a couple of methods that may be useful when testing _adaptors_, {*get_message_form_fixture*}[link:../rdoc/classes/ActiveSupport/TestCase.html#M000044] and {*message*}[link:../rdoc/classes/ActiveSupport/TestCase.html#M000043]:
|
267
|
+
|
268
|
+
- *get_message_from_fixture*: Returns an Adaptation::Message object from a fixture, without processing it (or an instance of the corresponding subclass, if it's defined).
|
269
|
+
|
270
|
+
- *message*: Builds a message from a xml fixture file and processes it the same way messages from the mom are processed by Adaptation, but using the test environment. Messages published with {publish}[link:../rdoc/classes/Adaptation/Adaptor.html#M000170] will be published to a mocked MOM (and can be checked with _assert_message_published_).
|
data/helpers/publish.rb
CHANGED
@@ -9,7 +9,7 @@ class Adaptation::Adaptor
|
|
9
9
|
xml_message = options.first
|
10
10
|
message_type = xml_message[1..(xml_message.index(/(>| )/) - 1)]
|
11
11
|
message_class = Adaptation::Message.get_class_object(message_type.capitalize)
|
12
|
-
message_object = message_class.
|
12
|
+
message_object = message_class.new(xml_message)
|
13
13
|
end
|
14
14
|
|
15
15
|
mom = File.new(ADAPTOR_ROOT + '/test/mocks/test/mom.txt', "a")
|
data/helpers/test_helper.rb
CHANGED
data/lib/adaptation.rb
CHANGED
data/lib/adaptation/adaptor.rb
CHANGED
@@ -10,22 +10,39 @@ module Adaptation
|
|
10
10
|
#
|
11
11
|
class Adaptor
|
12
12
|
|
13
|
-
def process message
|
13
|
+
def process message #:nodoc:
|
14
14
|
end
|
15
15
|
|
16
|
+
# Returns the logger to output results in the current environment log file.
|
17
|
+
# Example:
|
18
|
+
# > logger.info "this is going to log/development.log"
|
16
19
|
def logger
|
17
20
|
Adaptation::Base.logger
|
18
21
|
end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
|
23
|
+
# Publishes a message to the MOM. The message can be an instance of Adaptation::Message or a String.
|
24
|
+
#
|
25
|
+
# When executed in test environment messages are not published to the MOM. They are written to a mocked MOM
|
26
|
+
# and their publication can be asserted in tests with assert_message_published[link:/classes/ActiveSupport/TestCase.html#M000038].
|
27
|
+
#
|
28
|
+
# By default it uses <b>script/publish</b> ito publish. This can be overwritten specifying the
|
29
|
+
# <b>oappublish</b> instruction in configuration file <b>config/settings.yml</b>.
|
30
|
+
#
|
31
|
+
# By default it publishes in topic <b>ADAPTATION</b>. This can be overwritten specifying the <b>application</b> setting
|
32
|
+
# in <b>config/settings.yml</b> file.
|
33
|
+
#
|
34
|
+
# Example settings file:
|
35
|
+
# oappublish: /bin/echo
|
36
|
+
# application: MY_TOPIC
|
37
|
+
def publish *options
|
38
|
+
message_object = nil
|
39
|
+
if options.first.is_a?(Message)
|
40
|
+
message_object = options.first
|
24
41
|
elsif options.first.is_a?(String)
|
25
42
|
xml_message = options.first
|
26
43
|
message_type = xml_message[1..(xml_message.index(/(>| )/) - 1)]
|
27
44
|
message_class = Adaptation::Message.get_class_object(message_type.capitalize)
|
28
|
-
message_object = message_class.
|
45
|
+
message_object = message_class.new(xml_message)
|
29
46
|
end
|
30
47
|
|
31
48
|
xml = message_object.to_xml.to_s.gsub("'", "\"")
|
@@ -37,7 +54,7 @@ module Adaptation
|
|
37
54
|
|
38
55
|
end
|
39
56
|
|
40
|
-
def self.get_class_object(adaptor_class)
|
57
|
+
def self.get_class_object(adaptor_class) #:nodoc:
|
41
58
|
Object.const_get(adaptor_class) rescue nil
|
42
59
|
end
|
43
60
|
|
data/lib/adaptation/base.rb
CHANGED
@@ -61,19 +61,14 @@ module Adaptation
|
|
61
61
|
adaptor = message = nil
|
62
62
|
|
63
63
|
message_class = Adaptation::Message.get_class_object(message_type.capitalize)
|
64
|
-
message = message_class.nil? ? xml_message : message_class.
|
65
|
-
# TODO: the xml is returned as a String if a class to map it is not found;
|
66
|
-
# in future versions Adaptation may build a valid Adaptation::Message even
|
67
|
-
# without implementation for this type of message
|
64
|
+
message = message_class.nil? ? Adaptation::Message.new(xml_message) : message_class.new(xml_message)
|
68
65
|
|
69
66
|
adaptor_class = Adaptation::Adaptor.get_class_object("#{message_type.capitalize}Adaptor")
|
70
67
|
adaptor = adaptor_class.nil? ? ApplicationAdaptor.new : adaptor_class.new rescue Adaptation::Adaptor.new
|
71
68
|
|
72
|
-
unless message.
|
73
|
-
|
74
|
-
|
75
|
-
return
|
76
|
-
end
|
69
|
+
unless message.valid?
|
70
|
+
@@logger.info "WARNING:Message doesn't validate!"
|
71
|
+
return
|
77
72
|
end
|
78
73
|
|
79
74
|
adaptor.process message
|
data/lib/adaptation/message.rb
CHANGED
@@ -2,102 +2,44 @@ module Adaptation
|
|
2
2
|
|
3
3
|
#= Adaptation::Message -- XML to classes mapping.
|
4
4
|
#
|
5
|
-
#Adaptation::Message
|
6
|
-
#
|
7
|
-
#to
|
8
|
-
#management.
|
5
|
+
#Adaptation::Message maps xml data into a ruby object. It also provides validators
|
6
|
+
#(inspired by ActiveRecord[http://api.rubyonrails.org/classes/ActiveRecord/Validations.html] ORM)
|
7
|
+
#to check xml format.
|
9
8
|
#
|
10
|
-
#
|
11
|
-
#standalone classes. It offers a set of macros to specify wich structures are part of a bigger one and
|
12
|
-
#to allow validation of the different parts.
|
9
|
+
#Examples:
|
13
10
|
#
|
14
|
-
#
|
11
|
+
# contact = Adaptation::Message.new('<contact><name kind="surname">Name</name></contact>')
|
15
12
|
#
|
16
|
-
|
13
|
+
# contact.name.content # -> "Name"
|
14
|
+
# contact.names.first.content # -> "Name"
|
15
|
+
# contact.names.length # -> 1
|
16
|
+
# contact.name.kind # -> "surname"
|
17
17
|
#
|
18
|
-
#
|
19
|
-
# has_one :text, :name
|
20
|
-
# end
|
18
|
+
#Let's add some validations:
|
21
19
|
#
|
22
|
-
#
|
20
|
+
# class Contact < Adaptation::Message
|
21
|
+
# validates_presence_of :name
|
22
|
+
# end
|
23
23
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# </contact>
|
24
|
+
# contact = Contact.new('<contact><name kind="surname">Name</name></contact>')
|
25
|
+
# contact.valid? # -> true
|
27
26
|
#
|
28
|
-
#
|
27
|
+
# contact = Contact.new('<contact><phone>555</phone></contact>')
|
28
|
+
# contact.valid? # -> false
|
29
29
|
#
|
30
30
|
#
|
31
|
-
|
31
|
+
# class SeriousContact < Adaptation::Message
|
32
|
+
# maps_xml :contact # tell Adaptation that xml data like <contact>...</contact> is mapped by this class
|
33
|
+
# validates_value_of :kind, "surname", :in => :names
|
34
|
+
# end
|
32
35
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# has_one :text, :owner
|
36
|
-
# has_many :contacts
|
37
|
-
# end
|
36
|
+
# contact = SeriousContact.new('<contact><name kind="surname">Name</name></contact>')
|
37
|
+
# contact.valid? # -> true
|
38
38
|
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
# end
|
42
|
-
#
|
43
|
-
# Agenda class would be mapping the following xml structure:
|
44
|
-
#
|
45
|
-
# <agenda type="...">
|
46
|
-
# <owner>...</owner>
|
47
|
-
# <contact>...</contact>
|
48
|
-
# <contact>...</contact>
|
49
|
-
# ...
|
50
|
-
# </agenda>
|
51
|
-
#
|
52
|
-
# while the _Contact_ class would map:
|
53
|
-
#
|
54
|
-
# <contact>
|
55
|
-
# <name>...</name>
|
56
|
-
# </contact>
|
57
|
-
#
|
58
|
-
# The Contact class is a partial, a structure included in a bigger structure, so its
|
59
|
-
# file name starts with an underscore: _contact.rb
|
60
|
-
#
|
61
|
-
# We could have wrote Agenda like this, to change the contacts container name:
|
62
|
-
#
|
63
|
-
# class Agenda < Adaptation::Message
|
64
|
-
# has_one :attribute, :type
|
65
|
-
# has_one :text, :owner
|
66
|
-
# has_many :contacts, :in => :contact_list
|
67
|
-
# end
|
68
|
-
#
|
69
|
-
# and Contact like:
|
70
|
-
#
|
71
|
-
# class Contact < Adaptation::Message
|
72
|
-
# has_one :text, :name
|
73
|
-
# end
|
74
|
-
#
|
75
|
-
# Then the mapping in Agenda would be:
|
76
|
-
#
|
77
|
-
# <agenda type="...">
|
78
|
-
# <owner>...</owner>
|
79
|
-
# <contact_list>
|
80
|
-
# <contact>...</contact>
|
81
|
-
# </contact_list>
|
82
|
-
# </agenda>
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#* Validation rules.
|
86
|
-
#
|
87
|
-
# Adaptation::Message uses {ActiveRecord::Validations}[http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html].
|
88
|
-
# This means that {ActiveRecord validations}[http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html]
|
89
|
-
# can be used in an Adaptation::Message object and that custom validations can be easily implemented.
|
39
|
+
# contact = SeriousContact.new('<contact><name kind="alias">Alias</name></contact>')
|
40
|
+
# contact.valid? # -> false
|
90
41
|
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
# Validations usage example:
|
94
|
-
#
|
95
|
-
# class Agenda < Adaptation::Message
|
96
|
-
# has_one :attribute, :type
|
97
|
-
# has_one :text, :owner
|
98
|
-
# validates_presence_of :owner, :type
|
99
|
-
# validates_value_of :type, "indexed"
|
100
|
-
# end
|
42
|
+
#More on validations here[link:../rdoc/classes/ActiveRecord/Validations/ClassMethods.html].
|
101
43
|
#
|
102
44
|
#
|
103
45
|
class Message
|
@@ -109,167 +51,86 @@ module Adaptation
|
|
109
51
|
cattr_reader :objects
|
110
52
|
|
111
53
|
include Validateable
|
112
|
-
include ROXML
|
113
54
|
|
55
|
+
# Constructor. Transforms xml passsed as a <em>String</em> to an object wich methods map the input xml elements and attributes.
|
56
|
+
def initialize xml_string
|
57
|
+
@hash_with_root = XmlSimple.xml_in("<adaptation_wrapper>" + xml_string + "</adaptation_wrapper>", 'ForceArray' => false, 'AttrPrefix' => true)
|
58
|
+
|
59
|
+
first_value = @hash_with_root.values.first
|
60
|
+
hash = first_value.is_a?(String) ? {"content" => first_value} : first_value
|
61
|
+
array = hash.is_a?(Array) ? hash : [hash]
|
114
62
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
# class Xml < Adaptation::Message
|
141
|
-
# has_one :object, :element
|
142
|
-
# end
|
143
|
-
#
|
144
|
-
# The element xml structure would be described in a separate partial file <em>_element.rb</em>:
|
145
|
-
# class Element < Adaptation::Message
|
146
|
-
# has_one :text, :subelement
|
147
|
-
# end
|
148
|
-
#
|
149
|
-
def self.has_one *symbols
|
150
|
-
xml_tag = symbols[0]
|
151
|
-
case xml_tag
|
152
|
-
when :object
|
153
|
-
@objects = [] if @objects.nil?
|
154
|
-
unless @objects.include?(symbols[1])
|
155
|
-
@objects << symbols[1]
|
156
|
-
|
157
|
-
klass = get_class_object(symbols[1])
|
158
|
-
if klass.nil?
|
159
|
-
require "#{ADAPTOR_ROOT}/app/messages/_#{symbols[1].to_s}.rb"
|
160
|
-
klass = get_class_object(symbols[1])
|
63
|
+
array.each do |h|
|
64
|
+
if end_of_tree?(h)
|
65
|
+
h.each_pair do |k, v|
|
66
|
+
if !v.is_a?(Array)
|
67
|
+
is_attribute = k.include?("@") ? true : false
|
68
|
+
var = k.gsub("@","")
|
69
|
+
self.class_eval "attr_accessor :#{var}"
|
70
|
+
eval "@#{var} = v"
|
71
|
+
var2 = pluralize(var)
|
72
|
+
if !is_attribute and var != var2
|
73
|
+
self.class_eval "attr_accessor :#{var2}"
|
74
|
+
eval "@#{var2} = []; @#{var2} << '#{var}'"
|
75
|
+
end
|
76
|
+
else
|
77
|
+
var = pluralize(k.gsub("@",""))
|
78
|
+
self.class_eval "attr_accessor :#{var}"
|
79
|
+
eval "@#{var} = []"
|
80
|
+
v.each do |val|
|
81
|
+
if is_attribute?(val)
|
82
|
+
xml_substring = XmlSimple.xml_out(val, 'NoIndent' => true, 'RootName' => k, 'AttrPrefix' => true)
|
83
|
+
eval "@#{var} << Adaptation::Message.new('#{xml_substring}')"
|
84
|
+
else
|
85
|
+
eval "@#{var} << '#{val}'"
|
86
|
+
end
|
87
|
+
end
|
161
88
|
end
|
162
|
-
|
163
|
-
xml_object symbols[1], klass
|
164
|
-
validates_associated symbols[1]
|
165
89
|
end
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
90
|
+
else
|
91
|
+
h.each_pair do |k,v|
|
92
|
+
if k[0..0] == "@"
|
93
|
+
var = k.gsub("@","")
|
94
|
+
self.class_eval "attr_accessor :#{var}"
|
95
|
+
eval "@#{var} = '#{v}'"
|
96
|
+
else
|
97
|
+
self.class_eval "attr_accessor :#{k}"
|
98
|
+
xml_substring = ""
|
99
|
+
if !v.is_a?(Array)
|
100
|
+
xml_substring = XmlSimple.xml_out(v, 'NoIndent' => true, 'RootName' => k, 'AttrPrefix' => true)
|
101
|
+
eval "@#{k} = Adaptation::Message.new('#{xml_substring}')"
|
102
|
+
k2 = pluralize(k)
|
103
|
+
if k != k2
|
104
|
+
self.class_eval "attr_accessor :#{k2}"
|
105
|
+
eval "@#{k2} = []; @#{k2} << @#{k}"
|
106
|
+
end
|
107
|
+
else
|
108
|
+
k2 = pluralize(k)
|
109
|
+
self.class_eval "attr_accessor :#{k2}"
|
110
|
+
eval "@#{k2} = [];"
|
111
|
+
v.each do |val|
|
112
|
+
xml_substring = XmlSimple.xml_out(val, 'NoIndent' => true, 'RootName' => k, 'AttrPrefix' => true)
|
113
|
+
eval "@#{k} = Adaptation::Message.new('#{xml_substring}')"
|
114
|
+
eval "@#{k2} << @#{k}"
|
115
|
+
end
|
116
|
+
end
|
173
117
|
end
|
174
|
-
xml_attribute symbols[1]
|
175
|
-
end
|
176
|
-
when :text
|
177
|
-
@texts = [] if @texts.nil?
|
178
|
-
unless @texts.include?(symbols[1])
|
179
|
-
@texts << symbols[1]
|
180
|
-
xml_text symbols[1]
|
181
118
|
end
|
119
|
+
end
|
182
120
|
end
|
121
|
+
|
183
122
|
end
|
184
123
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
#
|
192
|
-
# <xml>
|
193
|
-
# <element attr="something">something more</element>
|
194
|
-
# </xml>
|
195
|
-
#
|
196
|
-
# class Xml < Adaptation::Message
|
197
|
-
# has_one :object, :element
|
198
|
-
# end
|
199
|
-
#
|
200
|
-
# In this case element cannot be declared just like <em>has_one :text</em>, because it also has
|
201
|
-
# an attribute. It must be declared like <em>has_one :object</em>. Then the element declares itself
|
202
|
-
# in a file called <em>_element.rb</em> like this:
|
203
|
-
#
|
204
|
-
# class Element < Adaptation::Message
|
205
|
-
# has_one :attribute, :attr
|
206
|
-
# has_text
|
207
|
-
# end
|
208
|
-
#
|
209
|
-
def self.has_text
|
210
|
-
if @has_text.nil?
|
211
|
-
@has_text = true
|
212
|
-
xml_text :text, nil, ROXML::TEXT_CONTENT
|
213
|
-
end
|
124
|
+
def self.has_one *symbols #:nodoc:
|
125
|
+
logger.info "has_one is deprecated and not necessary"
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.has_text #:nodoc:
|
129
|
+
logger.info "has_text is deprecated and not necessary"
|
214
130
|
end
|
215
131
|
|
216
|
-
|
217
|
-
|
218
|
-
# Example 1:
|
219
|
-
#
|
220
|
-
# <xml>
|
221
|
-
# <subelement>...</subelement>
|
222
|
-
# <subelement>...</subelement>
|
223
|
-
# <subelement>...</subelement>
|
224
|
-
# </xml>
|
225
|
-
#
|
226
|
-
# class Xml < Adaptation::Message
|
227
|
-
# has_many :subelements
|
228
|
-
# end
|
229
|
-
#
|
230
|
-
# Example 2:
|
231
|
-
#
|
232
|
-
# <xml>
|
233
|
-
# <subelement_list>
|
234
|
-
# <subelement>...</subelement>
|
235
|
-
# <subelement>...</subelement>
|
236
|
-
# <subelement>...</subelement>
|
237
|
-
# </subelement_list>
|
238
|
-
# </xml>
|
239
|
-
#
|
240
|
-
# class Xml < Adaptation::Message
|
241
|
-
# has_many :subelements, :in => :subelement_list
|
242
|
-
# end
|
243
|
-
#
|
244
|
-
def self.has_many *options
|
245
|
-
configuration = {}
|
246
|
-
configuration.update(options.pop) if options.last.is_a?(Hash)
|
247
|
-
|
248
|
-
class_with_container = nil
|
249
|
-
if configuration[:in]
|
250
|
-
class_with_container = options[0].to_s.capitalize[0..-2] + ":#{configuration[:in].to_s}"
|
251
|
-
else
|
252
|
-
class_with_container = options[0].to_s.capitalize[0..-2] + ":#{options[0].to_s}"
|
253
|
-
end
|
254
|
-
unless @@classes_with_brothers.include?(class_with_container)
|
255
|
-
@@classes_with_brothers << class_with_container
|
256
|
-
end
|
257
|
-
|
258
|
-
@has_many = [] if @has_many.nil?
|
259
|
-
unless @has_many.include?(options[0])
|
260
|
-
@has_many << options[0]
|
261
|
-
|
262
|
-
load "#{ADAPTOR_ROOT}/app/messages/_#{options[0].to_s[0..-2]}.rb"
|
263
|
-
klass = get_class_object(options[0].to_s.capitalize[0..-2])
|
264
|
-
|
265
|
-
if configuration[:in]
|
266
|
-
xml_object configuration[:in], klass, ROXML::TAG_ARRAY, configuration[:in].to_s
|
267
|
-
validates_associated configuration[:in]
|
268
|
-
else
|
269
|
-
xml_object options[0], klass, ROXML::TAG_ARRAY #, options[0].to_s
|
270
|
-
validates_associated options[0]
|
271
|
-
end
|
272
|
-
end
|
132
|
+
def self.has_many *options #:nodoc:
|
133
|
+
logger.info "has_many is deprecated and not necessary"
|
273
134
|
end
|
274
135
|
|
275
136
|
# Defines the xml element that this class is mapping. This is useful to avoid class
|
@@ -302,7 +163,6 @@ module Adaptation
|
|
302
163
|
#
|
303
164
|
def self.maps_xml element
|
304
165
|
@mapped_xml = element
|
305
|
-
xml_name element.to_s
|
306
166
|
end
|
307
167
|
|
308
168
|
# Returns the xml element this class is mapping
|
@@ -321,21 +181,57 @@ module Adaptation
|
|
321
181
|
klass
|
322
182
|
end
|
323
183
|
|
324
|
-
#
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
#
|
329
|
-
def self.to_object xml_message
|
330
|
-
parse xml_message
|
184
|
+
# <em>Deprecated</em>, use <em>new</em> instead.
|
185
|
+
def self.to_object xml_message #:nodoc:
|
186
|
+
logger.info "to_object is deprecated, use new instead"
|
187
|
+
self.new(xml_message)
|
331
188
|
end
|
332
189
|
|
333
|
-
# Alias for {Adaptation::Message#valid?}[http://api.rubyonrails.org/classes/ActiveRecord/Validations.html#M002099]
|
334
190
|
# <em>Deprecated</em>, use <em>valid?</em> instead.
|
335
|
-
def check
|
191
|
+
def check #:nodoc:
|
192
|
+
logger.info "check is deprecated, use valid? instead"
|
336
193
|
valid?
|
337
194
|
end
|
338
195
|
|
196
|
+
def self.logger#:nodoc:#
|
197
|
+
Adaptation::Base.logger rescue Logger.new(STDOUT)
|
198
|
+
end
|
199
|
+
|
200
|
+
def to_xml
|
201
|
+
xml_out(@hash_with_root).gsub("\"","'").gsub(/(<|<\/)content(>| *\/>)/,"")
|
202
|
+
end
|
203
|
+
|
204
|
+
def to_hash
|
205
|
+
@hash_with_root
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
|
210
|
+
def end_of_tree?(v) #:nodoc:
|
211
|
+
return true if v.has_key? "content"
|
212
|
+
return true if v.values.length == 1 and v.values.first.is_a?(Array) and v.values.first.reject{|val| val.is_a?(String) or is_attribute?(val)}.length == 0
|
213
|
+
false
|
214
|
+
end
|
215
|
+
|
216
|
+
def xml_in(xml_string)
|
217
|
+
XmlSimple.xml_in(xml_string, 'ForceArray' => false, 'AttrPrefix' => true, 'KeepRoot' => true)
|
218
|
+
end
|
219
|
+
|
220
|
+
def xml_out(xml_hash)
|
221
|
+
XmlSimple.xml_out(xml_hash, 'NoIndent' => true, 'RootName' => k, 'AttrPrefix' => true)
|
222
|
+
end
|
223
|
+
|
224
|
+
# TODO: improve this
|
225
|
+
def pluralize(v) #:nodoc:
|
226
|
+
v[(v.length - 1)..v.length] == "s" ? v : v + "s"
|
227
|
+
end
|
228
|
+
|
229
|
+
def is_attribute?(h) #:nodoc:
|
230
|
+
return false unless h.is_a?(Hash)
|
231
|
+
return true if h.length == 1 and h.values.first.is_a?(String)
|
232
|
+
false
|
233
|
+
end
|
234
|
+
|
339
235
|
end
|
340
236
|
|
341
237
|
end
|
@@ -5,58 +5,37 @@ require 'adaptation'
|
|
5
5
|
|
6
6
|
Adaptation::Initializer.run
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
Test::Unit::TestCase.fixture_path = 'test/fixtures'
|
8
|
+
begin
|
9
|
+
require 'active_record/test_case'
|
10
|
+
require 'active_record/fixtures'
|
11
|
+
rescue Exception => e
|
12
|
+
puts "Problem with database fixtures: #{e}"
|
13
|
+
raise e
|
15
14
|
end
|
16
15
|
|
17
16
|
require 'erb'
|
18
17
|
|
19
|
-
class
|
18
|
+
class ActiveSupport::TestCase
|
19
|
+
|
20
|
+
include ActiveRecord::TestFixtures
|
21
|
+
self.fixture_path = "#{ADAPTOR_ROOT}/test/fixtures/"
|
22
|
+
self.use_instantiated_fixtures = false
|
23
|
+
self.use_transactional_fixtures = false
|
20
24
|
|
21
25
|
# Asserts that a message[link:/classes/Adaptation/Message.html] in a xml
|
22
26
|
# fixture file is converted into an Adaptation::Message that if serialized
|
23
27
|
# again to xml is equivalent to the xml data in the initial fixture file.
|
24
|
-
# An Adaptation::Message object cretaed from a xml fixture, will only
|
25
|
-
# have the xml tags specified in its class definition (using has_one,
|
26
|
-
# has_many, has_text...) so this assertion can be useful to check that
|
27
|
-
# the class is defined correctly.
|
28
28
|
def assert_parsed message_symbol
|
29
29
|
data, message_object = load_message_fixture message_symbol
|
30
|
-
|
31
|
-
parsed_data =
|
30
|
+
|
31
|
+
#parsed_data = Adaptation::Message.new(data)
|
32
32
|
error = build_message error,
|
33
33
|
"? not parsed ok:\n initial: ?\n parsed: ?",
|
34
34
|
message_symbol.to_s,
|
35
|
-
|
36
|
-
message_object.to_xml
|
37
|
-
assert_block error do
|
38
|
-
compare_xml_elements parsed_data.root, message_object.to_xml
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# Asserts that a message[link:/classes/Adaptation/Message.html] in a xml
|
43
|
-
# fixture file is converted into an Adaptation::Message that if serialized
|
44
|
-
# again to xml is not equivalent to the xml data in the initial fixture file.
|
45
|
-
# An Adaptation::Message object cretaed from a xml fixture, will only
|
46
|
-
# have the xml tags specified in its class definition (using has_one,
|
47
|
-
# has_many, has_text...) so this assertion can be useful to check that
|
48
|
-
# undesired xml tags are filtered.
|
49
|
-
def assert_not_parsed message_symbol
|
50
|
-
data, message_object = load_message_fixture message_symbol
|
51
|
-
|
52
|
-
parsed_data = REXML::Document.new data
|
53
|
-
error = build_message error,
|
54
|
-
"? shouldn't be parsed ok:\n data: ?\n real: ?",
|
55
|
-
message_symbol.to_s,
|
56
|
-
parsed_data.to_s,
|
57
|
-
message_object.to_xml.to_s
|
35
|
+
data,
|
36
|
+
message_object.to_xml
|
58
37
|
assert_block error do
|
59
|
-
|
38
|
+
compare_xml_elements data, message_object.to_xml
|
60
39
|
end
|
61
40
|
end
|
62
41
|
|
@@ -100,7 +79,7 @@ class Test::Unit::TestCase
|
|
100
79
|
# build Message object with xml_data
|
101
80
|
message_type = xml_message[1..(xml_message.index(/(>| )/) - 1)]
|
102
81
|
message_class = Adaptation::Message.get_class_object(message_type.capitalize)
|
103
|
-
message_object = message_class.
|
82
|
+
message_object = message_class.nil? ? Adaptation::Message.new(xml_message) : message_class.new(xml_message)
|
104
83
|
end
|
105
84
|
|
106
85
|
# check for all messages "published" in the mom (that's file /tmp/mom.txt),
|
@@ -108,10 +87,9 @@ class Test::Unit::TestCase
|
|
108
87
|
message_found = false
|
109
88
|
expected = published = ""
|
110
89
|
File.open(ADAPTOR_ROOT + '/test/mocks/test/mom.txt', 'r').each{ |line|
|
111
|
-
mom_message = REXML::Document.new line
|
112
90
|
published = line.chop
|
113
91
|
expected = message_object.to_xml.to_s
|
114
|
-
if compare_xml_elements
|
92
|
+
if compare_xml_elements published, message_object.to_xml
|
115
93
|
message_found = true
|
116
94
|
break
|
117
95
|
end
|
@@ -219,9 +197,10 @@ class Test::Unit::TestCase
|
|
219
197
|
end
|
220
198
|
|
221
199
|
# Builds a message[link:/classes/Adaptation/Message.html] from a xml fixture
|
222
|
-
# file and processes it the same way
|
223
|
-
# adaptation, but using a test environment.
|
224
|
-
#
|
200
|
+
# file and processes it the same way messages from the mom are processed by
|
201
|
+
# adaptation, but using a test environment. Messages published with
|
202
|
+
# {publish}[link:/classes/Adaptation/Adaptor.html#M000170] will be published
|
203
|
+
# to a mocked MOM (and can be checked with _assert_message_published_)
|
225
204
|
def message message_symbol
|
226
205
|
# build a message object from fixture
|
227
206
|
message_xml, message_object = load_message_fixture message_symbol
|
@@ -241,8 +220,8 @@ class Test::Unit::TestCase
|
|
241
220
|
|
242
221
|
end
|
243
222
|
|
244
|
-
#
|
245
|
-
#
|
223
|
+
# Returns an Adaptation::Message object from a fixture, without processing it
|
224
|
+
# (or an instance of the corresponding subclass, if it's defined).
|
246
225
|
def get_message_from_fixture message_symbol
|
247
226
|
load_message_fixture(message_symbol)[1]
|
248
227
|
end
|
@@ -264,11 +243,13 @@ class Test::Unit::TestCase
|
|
264
243
|
data = get_message_fixture(fixture_symbol.to_s)
|
265
244
|
class_name = data[1..(data.index(/(>| )/) - 1)].capitalize
|
266
245
|
message_class = Adaptation::Message.get_class_object(class_name)
|
267
|
-
message_object = message_class.nil? ? data : message_class.
|
246
|
+
message_object = message_class.nil? ? Adaptation::Message.new(data) : message_class.new(data)
|
268
247
|
[data, message_object]
|
269
248
|
end
|
270
249
|
|
271
250
|
def compare_xml_elements element1, element2 #:nodoc:
|
251
|
+
element1 = REXML::Document.new(element1) if element1.is_a?(String)
|
252
|
+
element2 = REXML::Document.new(element2) if element2.is_a?(String)
|
272
253
|
if element1.has_attributes?
|
273
254
|
if !element2.has_attributes?
|
274
255
|
return false
|
@@ -21,7 +21,7 @@ module Validateable
|
|
21
21
|
module ClassMethods
|
22
22
|
# Define class methods here.
|
23
23
|
|
24
|
-
def self_and_descendents_from_active_record#nodoc:
|
24
|
+
def self_and_descendents_from_active_record # :nodoc:
|
25
25
|
klass = self
|
26
26
|
classes = [klass]
|
27
27
|
while klass != klass.base_class
|
@@ -45,10 +45,97 @@ module Validateable
|
|
45
45
|
|
46
46
|
end
|
47
47
|
|
48
|
+
#= Adaptation::Message Validations
|
49
|
+
# {ActiveRecord validations}[http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html] should work
|
50
|
+
# the same way, except those that have been overwritten here.
|
51
|
+
#
|
48
52
|
module ActiveRecord
|
49
53
|
module Validations
|
50
54
|
module ClassMethods
|
51
55
|
|
56
|
+
# Validates whether the specified xml attribute/element is present (not nil or blank).
|
57
|
+
#
|
58
|
+
# Example 1:
|
59
|
+
#
|
60
|
+
# class Leftwing < Adaptation::Message
|
61
|
+
# validates_presence_of :side
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# lw = Leftwing.new("<leftwing side=\"left\"/>")
|
65
|
+
# lw.valid? # -> true
|
66
|
+
# lw = Leftwing.new("<leftwing noside=\"left\"/>")
|
67
|
+
# lw.valid? # -> false
|
68
|
+
#
|
69
|
+
# Example 2:
|
70
|
+
#
|
71
|
+
# class Bird < Adaptation::Message
|
72
|
+
# validates_presence_of :side, :in => "birds.wings"
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# b = Bired.new('<birds><bird><wings><wing side="left"/><wing side="right"/></wings></bird></birds>')
|
76
|
+
# b.valid? # -> true
|
77
|
+
# b = Bired.new('<birds><bird><wings><wing side="left"/><wing noside="right"/></wings></bird></birds>')
|
78
|
+
# b.valid? # -> false
|
79
|
+
#
|
80
|
+
def validates_presence_of(*attr_names)
|
81
|
+
configuration = {
|
82
|
+
:message => 'cannot be blank'
|
83
|
+
}
|
84
|
+
configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
|
85
|
+
|
86
|
+
if configuration[:in].nil?
|
87
|
+
validates_each(attr_names, configuration) do |record, attr_name, value|
|
88
|
+
string = record.send(attr_names[0].to_sym)
|
89
|
+
unless string.nil?
|
90
|
+
string = string.content if string.is_a?(Adaptation::Message)
|
91
|
+
end
|
92
|
+
if string.blank?
|
93
|
+
record.errors.add(attr_name, configuration[:message])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
else
|
97
|
+
validates_each(attr_names, configuration) do |record, attr_name, value|
|
98
|
+
missing = false
|
99
|
+
configuration_in = configuration[:in].to_s
|
100
|
+
elements = configuration_in.to_s.split('.')
|
101
|
+
subelement = record
|
102
|
+
while elements.length > 1
|
103
|
+
subelement = record.send(elements[0].to_sym)
|
104
|
+
elements.slice!(0)
|
105
|
+
end
|
106
|
+
|
107
|
+
if !subelement.is_a?(Array)
|
108
|
+
subelement.send(elements[0].to_sym).each do |s|
|
109
|
+
string = s.send(attr_names[0].to_sym)
|
110
|
+
unless string.nil?
|
111
|
+
string = string.content unless string.is_a?(String)
|
112
|
+
end
|
113
|
+
if string.blank?
|
114
|
+
missing = true
|
115
|
+
break
|
116
|
+
end
|
117
|
+
end
|
118
|
+
else
|
119
|
+
subelement.each do |sub|
|
120
|
+
sub.send(elements[0].to_sym).each do |s|
|
121
|
+
string = s.send(attr_names[0].to_sym)
|
122
|
+
unless string.nil?
|
123
|
+
string = string.content unless string.is_a?(String)
|
124
|
+
end
|
125
|
+
if string.blank?
|
126
|
+
missing = true
|
127
|
+
break
|
128
|
+
end
|
129
|
+
end
|
130
|
+
break if missing
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
record.errors.add(attr_name, configuration[:message]) if missing
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
52
139
|
# Validates whether the value of the specified xml attribute/element is the expected one.
|
53
140
|
#
|
54
141
|
# Example 1:
|
@@ -56,8 +143,6 @@ module ActiveRecord
|
|
56
143
|
# <leftwing side="left"/>
|
57
144
|
#
|
58
145
|
# class Leftwing < Adaptation::Message
|
59
|
-
# has_one :attribute, :side
|
60
|
-
#
|
61
146
|
# validates_value_of :side, "left"
|
62
147
|
# end
|
63
148
|
#
|
@@ -65,8 +150,6 @@ module ActiveRecord
|
|
65
150
|
# <bird><wings><wing side="left"/><wing side="right"/></wings></bird>
|
66
151
|
#
|
67
152
|
# class Bird < Adaptation::Message
|
68
|
-
# has_many :wings
|
69
|
-
#
|
70
153
|
# validates_value_of :side, "left", :in => :wings
|
71
154
|
# end
|
72
155
|
#
|
@@ -78,15 +161,30 @@ module ActiveRecord
|
|
78
161
|
|
79
162
|
if configuration[:in].nil?
|
80
163
|
validates_each(attr_names, configuration) do |record, attr_name, value|
|
81
|
-
|
164
|
+
string = record.send(attr_names[0].to_sym)
|
165
|
+
unless string.nil?
|
166
|
+
string = string.content unless string.is_a?(String)
|
167
|
+
end
|
168
|
+
if (attr_names[1].to_s != string)
|
82
169
|
record.errors.add(attr_name, configuration[:message])
|
83
170
|
end
|
84
171
|
end
|
85
172
|
else
|
86
173
|
validates_each(attr_names, configuration) do |record, attr_name, value|
|
87
174
|
found = false
|
88
|
-
|
89
|
-
|
175
|
+
configuration_in = configuration[:in].to_s
|
176
|
+
elements = configuration_in.to_s.split('.')
|
177
|
+
subelement = record
|
178
|
+
while elements.length > 1
|
179
|
+
subelement = record.send(elements[0].to_sym)
|
180
|
+
elements.slice!(0)
|
181
|
+
end
|
182
|
+
subelement.send(elements[0].to_sym).each do |s|
|
183
|
+
string = s.send(attr_names[0].to_sym)
|
184
|
+
unless string.nil?
|
185
|
+
string = string.content unless string.is_a?(String)
|
186
|
+
end
|
187
|
+
if (attr_names[1].to_s == string)
|
90
188
|
found = true
|
91
189
|
break
|
92
190
|
end
|
@@ -99,13 +197,15 @@ module ActiveRecord
|
|
99
197
|
# Validates whether the value of the specified xml attribute/element has a valid email format.
|
100
198
|
#
|
101
199
|
# Example:
|
102
|
-
# <contact email="mail@xample.com">...</contact>
|
103
200
|
#
|
104
201
|
# class Contact < Adaptation::Message
|
105
|
-
# has_one :attribute, :email
|
106
|
-
#
|
107
202
|
# validates_as_email :email
|
108
|
-
# end
|
203
|
+
# end
|
204
|
+
#
|
205
|
+
# c = Contact.new('<contact email="mail@xample.com">...</contact>')
|
206
|
+
# c.valid? # -> true
|
207
|
+
# c.email = "nomail"
|
208
|
+
# c.valid? # -> false
|
109
209
|
#
|
110
210
|
def validates_as_email(*attr_names)
|
111
211
|
configuration = {
|
data/lib/adaptation/version.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
|
2
2
|
|
3
|
-
class <%= class_name %>AdaptorTest <
|
4
|
-
|
5
|
-
#fixtures :your_table_name_here
|
3
|
+
class <%= class_name %>AdaptorTest < ActiveSupport::TestCase
|
6
4
|
|
7
5
|
def setup
|
8
6
|
end
|
9
7
|
|
10
8
|
# Replace this with your real tests.
|
11
|
-
|
9
|
+
test "should be true" do
|
12
10
|
assert true
|
13
11
|
end
|
12
|
+
|
14
13
|
end
|
@@ -1,24 +1,16 @@
|
|
1
1
|
require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
|
2
2
|
|
3
|
-
class <%= class_name %>Test <
|
3
|
+
class <%= class_name %>Test < ActiveSupport::TestCase
|
4
4
|
|
5
5
|
# Replace this with your real tests.
|
6
|
-
|
6
|
+
test "should be true" do
|
7
7
|
assert true
|
8
8
|
end
|
9
9
|
|
10
|
-
# assert the message is defined correctly comparing the initial xml
|
11
|
-
# from the fixture with the xml obtained from the Adaptation::Message
|
12
|
-
# object created with that fixture
|
13
|
-
#def test_not_parsed
|
14
|
-
# assert_parsed :<%= file_name %>
|
15
|
-
#end
|
16
|
-
|
17
10
|
# assert message passes our validations
|
18
11
|
#def test_validates
|
19
12
|
# assert_validates :<%= file_name %>
|
20
13
|
# assert_not_validates :<%= file_name %>_incorrect
|
21
14
|
#end
|
22
15
|
|
23
|
-
|
24
16
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adaptation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xavi Vila Morell
|
@@ -9,18 +9,18 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-07-24 00:00:00 +02:00
|
13
13
|
default_executable: adaptation
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: xml-simple
|
17
17
|
type: :runtime
|
18
18
|
version_requirement:
|
19
19
|
version_requirements: !ruby/object:Gem::Requirement
|
20
20
|
requirements:
|
21
|
-
- - "
|
21
|
+
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
23
|
+
version: 1.0.12
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: activerecord
|
@@ -28,9 +28,9 @@ dependencies:
|
|
28
28
|
version_requirement:
|
29
29
|
version_requirements: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 2.
|
33
|
+
version: 2.3.3
|
34
34
|
version:
|
35
35
|
description: Adaptation is a framework for building "adaptors" for web-applications, so they can interact with other web-applications publishing messages and being subscribed to a message queue.
|
36
36
|
email: xavi@oaproject.net
|