isomorphic 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fb66cf9f00f2000d639046e108691ee363a55597
4
+ data.tar.gz: 8a48219b9e729e869346d7a69cb11f894986ca0b
5
+ SHA512:
6
+ metadata.gz: 56fc30f14036d40d50ab7b5e57cda670b6e032a31efd6b783c6d64b8b68b02cd1027f1a9b9b3fdca8856a88add40386ce2457ecd4ead14d0f56214484cc8387d
7
+ data.tar.gz: 4d9764956509e58bfb72feebcb887cf716b5316b3646a0dfcf2247c72bb956363af6018fb40fcd3716c4c6cea47c2b59554225063be4396066c7578e68b841d0
data/.gitignore ADDED
@@ -0,0 +1,53 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ # Ignore Byebug command history file.
17
+ .byebug_history
18
+
19
+ ## Specific to RubyMotion:
20
+ .dat*
21
+ .repl_history
22
+ build/
23
+ *.bridgesupport
24
+ build-iPhoneOS/
25
+ build-iPhoneSimulator/
26
+
27
+ ## Specific to RubyMotion (use of CocoaPods):
28
+ #
29
+ # We recommend against adding the Pods directory to your .gitignore. However
30
+ # you should judge for yourself, the pros and cons are mentioned at:
31
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
+ #
33
+ # vendor/Pods/
34
+
35
+ ## Documentation cache and generated files:
36
+ /.yardoc/
37
+ /_yardoc/
38
+ /doc/
39
+ /rdoc/
40
+
41
+ ## Environment normalization:
42
+ /.bundle/
43
+ /vendor/bundle
44
+ /lib/bundler/man/
45
+
46
+ # for a library or gem, you might want to ignore these files since the code is
47
+ # intended to run in multiple environments; otherwise, check them in:
48
+ # Gemfile.lock
49
+ # .ruby-version
50
+ # .ruby-gemset
51
+
52
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in isomorphic.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,32 @@
1
+ isomorphic
2
+
3
+ Copyright (c) 2019, Battelle Memorial Institute
4
+ All rights reserved.
5
+
6
+ 1. Battelle Memorial Institute (hereinafter Battelle) hereby grants permission
7
+ to any person or entity lawfully obtaining a copy of this software and
8
+ associated documentation files (hereinafter "the Software") to redistribute
9
+ and use the Software in source and binary forms, with or without
10
+ modification. Such person or entity may use, copy, modify, merge, publish,
11
+ distribute, sublicense, and/or sell copies of the Software, and may permit
12
+ others to do so, subject to the following conditions:
13
+
14
+ * Redistributions of source code must retain the above copyright notice, this
15
+ list of conditions and the following disclaimers.
16
+ * Redistributions in binary form must reproduce the above copyright notice,
17
+ this list of conditions and the following disclaimer in the documentation
18
+ and/or other materials provided with the distribution.
19
+ * Other than as used herein, neither the name Battelle Memorial Institute or
20
+ Battelle may be used in any form whatsoever without the express written
21
+ consent of Battelle.
22
+
23
+ 2. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
+ DISCLAIMED. IN NO EVENT SHALL BATTELLE OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,228 @@
1
+ # isomorphic
2
+
3
+ Isomorphic is a Ruby library for specifying isomorphisms between Ruby objects.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'isomorphic'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install isomorphic
20
+
21
+ ## Usage
22
+
23
+ In this example, we demonstrate how to use Isomorphic to specify an isomorphism between a Ruby on Rails model and a non-trivial `module`/`class` definition: [BuildingSync](https://buildingsync.net), an XML schema for building energy audit data.
24
+
25
+ We begin with the definition of the Ruby on Rails model:
26
+ ```ruby
27
+ class Address < ActiveRecord::Base
28
+ validates_presence_of :street_address, :city, :state, :postal_code
29
+ end
30
+ ```
31
+
32
+ Our goal is to map instances of the Ruby on Rails model to/from the `<auc:Address>` XML element in [BuildingSync](https://buildingsync.net).
33
+
34
+ The [`soap4r`](https://github.com/rubyjedi/soap4r) gem provides the [`xsd2ruby.rb`](https://github.com/rubyjedi/soap4r/blob/master/bin/xsd2ruby.rb) binary for auto-generating Ruby code from an XML schema document.
35
+
36
+ An excerpt of the auto-generated Ruby code for [BuildingSync](https://buildingsync.net) is as follows:
37
+ ```ruby
38
+ module BuildingSync
39
+ # {http://buildingsync.net/schemas/bedes-auc/2019}Address
40
+ # streetAddressDetail - BuildingSync::Address::StreetAddressDetail
41
+ # city - SOAP::SOAPString
42
+ # state - BuildingSync::State
43
+ # postalCode - SOAP::SOAPString
44
+ # postalCodePlus4 - SOAP::SOAPString
45
+ # county - SOAP::SOAPString
46
+ # country - SOAP::SOAPString
47
+ class Address
48
+
49
+ # inner class for member: StreetAddressDetail
50
+ # {http://buildingsync.net/schemas/bedes-auc/2019}StreetAddressDetail
51
+ # simplified - BuildingSync::Address::StreetAddressDetail::Simplified
52
+ # complex - BuildingSync::Address::StreetAddressDetail::Complex
53
+ class StreetAddressDetail
54
+
55
+ # inner class for member: Simplified
56
+ # {http://buildingsync.net/schemas/bedes-auc/2019}Simplified
57
+ # streetAddress - SOAP::SOAPString
58
+ # streetAdditionalInfo - SOAP::SOAPString
59
+ class Simplified
60
+ attr_accessor :streetAddress
61
+ attr_accessor :streetAdditionalInfo
62
+
63
+ def initialize(streetAddress = nil, streetAdditionalInfo = nil)
64
+ @streetAddress = streetAddress
65
+ @streetAdditionalInfo = streetAdditionalInfo
66
+ end
67
+ end
68
+
69
+ # inner class for member: Complex
70
+ # {http://buildingsync.net/schemas/bedes-auc/2019}Complex
71
+ # streetNumberPrefix - SOAP::SOAPString
72
+ # streetNumberNumeric - BuildingSync::Address::StreetAddressDetail::Complex::StreetNumberNumeric
73
+ # streetNumberSuffix - SOAP::SOAPString
74
+ # streetDirPrefix - SOAP::SOAPString
75
+ # streetName - SOAP::SOAPString
76
+ # streetAdditionalInfo - SOAP::SOAPString
77
+ # streetSuffix - SOAP::SOAPString
78
+ # streetSuffixModifier - SOAP::SOAPString
79
+ # streetDirSuffix - SOAP::SOAPString
80
+ # subaddressType - SOAP::SOAPString
81
+ # subaddressIdentifier - SOAP::SOAPString
82
+ class Complex
83
+
84
+ # inner class for member: StreetNumberNumeric
85
+ # {http://buildingsync.net/schemas/bedes-auc/2019}StreetNumberNumeric
86
+ # xmlattr_Source - SOAP::SOAPString
87
+ class StreetNumberNumeric < ::String
88
+ AttrSource = XSD::QName.new("http://buildingsync.net/schemas/bedes-auc/2019", "Source")
89
+
90
+ def __xmlattr
91
+ @__xmlattr ||= {}
92
+ end
93
+
94
+ def xmlattr_Source
95
+ __xmlattr[AttrSource]
96
+ end
97
+
98
+ def xmlattr_Source=(value)
99
+ __xmlattr[AttrSource] = value
100
+ end
101
+
102
+ def initialize(*arg)
103
+ super
104
+ @__xmlattr = {}
105
+ end
106
+ end
107
+
108
+ attr_accessor :streetNumberPrefix
109
+ attr_accessor :streetNumberNumeric
110
+ attr_accessor :streetNumberSuffix
111
+ attr_accessor :streetDirPrefix
112
+ attr_accessor :streetName
113
+ attr_accessor :streetAdditionalInfo
114
+ attr_accessor :streetSuffix
115
+ attr_accessor :streetSuffixModifier
116
+ attr_accessor :streetDirSuffix
117
+ attr_accessor :subaddressType
118
+ attr_accessor :subaddressIdentifier
119
+
120
+ def initialize(streetNumberPrefix = nil, streetNumberNumeric = nil, streetNumberSuffix = nil, streetDirPrefix = nil, streetName = nil, streetAdditionalInfo = nil, streetSuffix = nil, streetSuffixModifier = nil, streetDirSuffix = nil, subaddressType = nil, subaddressIdentifier = nil)
121
+ @streetNumberPrefix = streetNumberPrefix
122
+ @streetNumberNumeric = streetNumberNumeric
123
+ @streetNumberSuffix = streetNumberSuffix
124
+ @streetDirPrefix = streetDirPrefix
125
+ @streetName = streetName
126
+ @streetAdditionalInfo = streetAdditionalInfo
127
+ @streetSuffix = streetSuffix
128
+ @streetSuffixModifier = streetSuffixModifier
129
+ @streetDirSuffix = streetDirSuffix
130
+ @subaddressType = subaddressType
131
+ @subaddressIdentifier = subaddressIdentifier
132
+ end
133
+ end
134
+
135
+ attr_accessor :simplified
136
+ attr_accessor :complex
137
+
138
+ def initialize(simplified = nil, complex = nil)
139
+ @simplified = simplified
140
+ @complex = complex
141
+ end
142
+ end
143
+
144
+ attr_accessor :streetAddressDetail
145
+ attr_accessor :city
146
+ attr_accessor :state
147
+ attr_accessor :postalCode
148
+ attr_accessor :postalCodePlus4
149
+ attr_accessor :county
150
+ attr_accessor :country
151
+
152
+ def initialize(streetAddressDetail = nil, city = nil, state = nil, postalCode = nil, postalCodePlus4 = nil, county = nil, country = nil)
153
+ @streetAddressDetail = streetAddressDetail
154
+ @city = city
155
+ @state = state
156
+ @postalCode = postalCode
157
+ @postalCodePlus4 = postalCodePlus4
158
+ @county = county
159
+ @country = country
160
+ end
161
+ end
162
+ end
163
+ ```
164
+
165
+ First, we define a factory:
166
+ ```ruby
167
+ class BuildingSyncFactory < Isomorphic::Factory::AbstractFactory
168
+ include Singleton
169
+
170
+ def initialize
171
+ super(BuildingSync)
172
+ end
173
+ end
174
+ ```
175
+
176
+ Next, we define an inflector:
177
+ ```ruby
178
+ class BuildingSyncInflector < Isomorphic::Factory::AbstractInflector
179
+ include Singleton
180
+
181
+ def initialize
182
+ super(BuildingSync)
183
+ end
184
+ end
185
+ ```
186
+
187
+ Finally, we declare the isomorphism using the domain-specific language:
188
+ ```ruby
189
+ class Address < ActiveRecord::Base
190
+ validates_presence_of :street_address, :city, :state, :postal_code
191
+
192
+ include Isomorphic::Model
193
+
194
+ isomorphism_for(BuildingSyncFactory.instance, BuildingSyncInflector.instance, BuildingSync::Address) do
195
+ member :streetAddressDetail, BuildingSync::Address::StreetAddressDetail do
196
+ member :simplified, BuildingSync::Address::StreetAddressDetail::Simplified do
197
+ attribute_for reflect_on_attribute(:street_address), :streetAddress
198
+ end
199
+ end
200
+ attribute_for reflect_on_attribute(:city), :city
201
+ attribute_for reflect_on_attribute(:state), :state
202
+ attribute_for reflect_on_attribute(:postal_code), :postalCode
203
+ end
204
+ end
205
+ ```
206
+
207
+ Now, we can map instances of the Ruby on Rails model to/from the `<auc:Address>` XML element in [BuildingSync](https://buildingsync.net):
208
+ ```ruby
209
+ orig_record = Address.new(street_address: '123 Fake Street', city: 'York', state: 'PA', postal_code: '17402')
210
+
211
+ building_sync_address = orig_record.to_building_sync_address
212
+
213
+ new_record = Address.from_building_sync_address(building_sync_address)
214
+ ```
215
+
216
+ ## Development
217
+
218
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
219
+
220
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
221
+
222
+ ## License
223
+
224
+ [The 2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause)
225
+
226
+ ## Contributing
227
+
228
+ Bug reports and pull requests are welcome on GitHub at https://github.com/pnnl/isomorphic.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/WARRANTY.txt ADDED
@@ -0,0 +1,22 @@
1
+ This material was prepared as an account of work sponsored by an agency of the
2
+ United States Government. Neither the United States Government nor the United
3
+ States Department of Energy, nor Battelle, nor any of their employees, nor any
4
+ jurisdiction or organization that has cooperated in the development of these
5
+ materials, makes any warranty, express or implied, or assumes any legal
6
+ liability or responsibility for the accuracy, completeness, or usefulness or any
7
+ information, apparatus, product, software, or process disclosed, or represents
8
+ that its use would not infringe privately owned rights.
9
+
10
+ Reference herein to any specific commercial product, process, or service by
11
+ trade name, trademark, manufacturer, or otherwise does not necessarily
12
+ constitute or imply its endorsement, recommendation, or favoring by the United
13
+ States Government or any agency thereof, or Battelle Memorial Institute. The
14
+ views and opinions of authors expressed herein do not necessarily state or
15
+ reflect those of the United States Government or any agency thereof.
16
+
17
+ PACIFIC NORTHWEST NATIONAL LABORATORY
18
+ operated by
19
+ BATTELLE
20
+ for the
21
+ UNITED STATES DEPARTMENT OF ENERGY
22
+ under Contract DE-AC05-76RL01830
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "isomorphic"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,38 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "isomorphic/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "isomorphic"
8
+ spec.version = Isomorphic::VERSION
9
+ spec.authors = ["Mark Borkum"]
10
+ spec.email = ["mark.borkum@pnnl.gov"]
11
+
12
+ spec.summary = %q{Reversible morphisms between Ruby objects.}
13
+ spec.description = %q{Isomorphic is a Ruby library for specifying isomorphisms between Ruby objects.}
14
+ spec.homepage = "https://github.com/pnnl/isomorphic"
15
+
16
+ # # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ # if spec.respond_to?(:metadata)
19
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
20
+ # else
21
+ # raise "RubyGems 2.0 or newer is required to protect against " \
22
+ # "public gem pushes."
23
+ # end
24
+
25
+ # Specify which files should be added to the gem when it is released.
26
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
28
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
29
+ end
30
+ spec.bindir = "exe"
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ["lib"]
33
+
34
+ spec.add_dependency "activesupport", "~> 4.2.11"
35
+
36
+ spec.add_development_dependency "bundler", "~> 1.16"
37
+ spec.add_development_dependency "rake", "~> 10.0"
38
+ end
data/lib/isomorphic.rb ADDED
@@ -0,0 +1,13 @@
1
+ require "isomorphic/version"
2
+
3
+ module Isomorphic
4
+ extend ::ActiveSupport::Autoload
5
+
6
+ autoload :Factory, "isomorphic/factory"
7
+ autoload :HashWithIndifferentAccess, "isomorphic/hash_with_indifferent_access"
8
+ autoload :Inflector, "isomorphic/inflector"
9
+ autoload :Lens, "isomorphic/lens"
10
+ autoload :Memoization, "isomorphic/memoization"
11
+ autoload :Model, "isomorphic/model"
12
+ autoload :Node, "isomorphic/node"
13
+ end
@@ -0,0 +1,20 @@
1
+ module Isomorphic
2
+ # Generic base class for all Isomorphic errors.
3
+ #
4
+ # @abstract
5
+ class IsomorphicError < ::StandardError
6
+ # @!attribute [r] base
7
+ # @return [Module] the base module
8
+ attr_reader :base
9
+
10
+ # Default constructor.
11
+ #
12
+ # @param message [String] the message
13
+ # @param base [Module] the base module
14
+ def initialize(message = nil, base)
15
+ @base = base
16
+
17
+ super(message)
18
+ end
19
+ end
20
+ end