vcx-elements 0.2.0

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/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2012 Joshua Priddle <jpriddle@me.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person ob-
4
+ taining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without restric-
6
+ tion, including without limitation the rights to use, copy, modi-
7
+ fy, merge, publish, distribute, sublicense, and/or sell copies of
8
+ the Software, and to permit persons to whom the Software is fur-
9
+ nished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONIN-
17
+ FRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,57 @@
1
+ # Gem::Create [![Gem::Create Build Status][Build Icon]][Build Status]
2
+
3
+ > This is my gem template. There are many like it, but this one is mine.
4
+
5
+ Gem::Create provides a `gem create` command which can be used to generate a
6
+ skeleton for a new RubyGem.
7
+
8
+ [Build Icon]: https://secure.travis-ci.org/itspriddle/gem-create.png?branch=master
9
+ [Build Status]: http://travis-ci.org/itspriddle/gem-create
10
+
11
+ ## Usage
12
+
13
+ Usage: gem create GEM_NAME [options]
14
+
15
+ Options:
16
+ --force Overwrite existing files
17
+ --git GIT_PATH The path to git
18
+ --author AUTHOR The author name used in gemspec
19
+ --github-name NAME The Github account that will own the gem
20
+ --email EMAIL The author's email address used in gemspec
21
+ --template-directory DIR A custom template directory to use
22
+
23
+
24
+ Common Options:
25
+ -h, --help Get help on this command
26
+ -V, --[no-]verbose Set the verbose level of output
27
+ -q, --quiet Silence commands
28
+ --config-file FILE Use this config file instead of default
29
+ --backtrace Show stack backtrace on errors
30
+ --debug Turn on Ruby debugging
31
+
32
+
33
+ Summary:
34
+ Creates a new RubyGem skeleton
35
+
36
+ ## Development
37
+
38
+ Gem::Create depends on rake and minitest for testing.
39
+
40
+ git clone git://github.com/itspriddle/gem-create
41
+ cd gem-create
42
+ bundle install
43
+ bundle exec rake spec
44
+
45
+ ## Note on Patches/Pull Requests
46
+
47
+ * Fork the project.
48
+ * Make your feature addition or bug fix.
49
+ * Add tests for it. This is important so I don't break it in a future version
50
+ unintentionally.
51
+ * Commit, do not bump version. (If you want to have your own version, that is
52
+ fine but bump version in a commit by itself I can ignore when I pull).
53
+ * Send me a pull request. Bonus points for topic branches.
54
+
55
+ ## Copyright
56
+
57
+ Copyright (c) 2012 Joshua Priddle. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'rake/testtask'
2
+
3
+ task :default => :spec
4
+
5
+ Rake::TestTask.new :spec do |test|
6
+ test.libs << "spec"
7
+ test.pattern = "spec/*_spec.rb"
8
+ test.verbose = ENV.has_key?('VERBOSE')
9
+ end
@@ -0,0 +1,19 @@
1
+ $:.unshift 'lib'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.platform = Gem::Platform::RUBY
5
+ s.name = "vcx-elements"
6
+ s.version = "0.2.0"
7
+ s.date = Time.now.strftime('%Y-%m-%d')
8
+ s.homepage = "https://github.com/livegamervcxdevteam/elementsapi.git"
9
+ s.authors = ["livegamer"]
10
+ s.email = "todd@livegamer.com"
11
+ s.summary = "Elements Api"
12
+ s.description= " Elements Api"
13
+ s.files = %w[ Gemfile Rakefile README.markdown gem-create.gemspec LICENSE ]
14
+ s.files += Dir['lib/**/*']
15
+ s.test_files = Dir['spec/**/*']
16
+
17
+ s.add_development_dependency 'rake'
18
+ s.add_development_dependency 'minitest'
19
+ end
data/lib/elements.rb ADDED
@@ -0,0 +1,358 @@
1
+ require 'rest_client'
2
+ require 'xmlsimple'
3
+ #Elements module provides a list of all the interfaces for making calls to Elements
4
+ module Elements
5
+ DEFAULTURL = "https://vcxdev.tfelements.com/tfel2rs/v2/"
6
+ V1URL = "https://vcxdev.tfelements.com/starterkit/v1/"
7
+
8
+ #Api class defaults to the V2 of the elements API
9
+ class Api
10
+ public
11
+ @url = DEFAULTURL
12
+ @store_id = 3190
13
+
14
+ #Add_user is a class method of Api class that provides adding users to elements
15
+ def self.add_user(user)
16
+ params = {
17
+ name: user.email.gsub('@','_'),
18
+ emailaddress: user.email,
19
+ namespaceId: '0'
20
+ #gender: user.gender,
21
+ #dateOfBirth: user.dob.strftime("%m/%d/%Y")
22
+ }
23
+ response = post_data 'user', params
24
+ result = XmlSimple.xml_in(response)
25
+ user.update_column(:elements_id, result['id'])
26
+ end
27
+
28
+ #Find_user is a class method of Api class that provides finding users that are added in elements
29
+ def self.find_user(user)
30
+ get_data "user/#{user.elements_id}"
31
+ end
32
+
33
+ #Find Forex Offer is a class method that returns the foreign exchange rate for virtual currencies
34
+ #input: eg. 'AMS', 'AMG'
35
+ #output: xml with attributes eg. exchangeRate="0.011"
36
+ def self.find_forex_offer_by_id(forex_offer_id)
37
+ params = {'id' => forex_offer_id }
38
+ get_data("forexOffer/#{forex_offer_id}", params)
39
+ end
40
+
41
+ #Find Forex Offer is a class method that returns the foreign exchange rate for virtual currencies
42
+ #input: eg. 'AMS', 'AMG'
43
+ #output: xml with attributes eg. exchangeRate="0.011"
44
+ def self.find_forex_offer_by_currency(from_currency, to_currency)
45
+ params = {'fromCurrencyName' => from_currency, 'toCurrencyName' => to_currency }
46
+ get_data("forexOffers", params)
47
+ end
48
+
49
+ #Find Forex Offer is a class method that returns the foreign exchange rate for virtual currencies
50
+ #input: eg. exchange_rate
51
+ #output: xml with attributes eg. exchangeRate="0.011"
52
+ def self.find_active_forex_offer(exchange_rate)
53
+ params = {'fromCurrencyName' => exchange_rate.from_currency.vcx_name, 'toCurrencyName' => exchange_rate.to_currency.vcx_name, 'statuses' => 'ACTIVE' }
54
+ get_data("forexOffers", params)
55
+
56
+ end
57
+
58
+ def self.find_or_create_forex_offer(exchange_rate, ipaddress)
59
+ response = XmlSimple.xml_in find_active_forex_offer(exchange_rate)
60
+ if(!response.nil? and !response['forexOffer'].nil?)
61
+ response['forexOffer'].each do |forex_offer|
62
+ if(forex_offer['externalKey'] == exchange_rate.id.to_s and forex_offer['status']== "ACTIVE") then
63
+ return forex_offer["id"]
64
+ else
65
+ cancel_forex_offer(forex_offer["id"], ipaddress)
66
+ end
67
+ end
68
+ end
69
+ add_forex_offer(exchange_rate)
70
+ #TODO Header info needs to be captured for optimization
71
+ find_or_create_forex_offer(exchange_rate, ipaddress)
72
+ end
73
+
74
+ #Find Forex Offer is a class method that returns the foreign exchange rate for virtual currencies
75
+ #input: eg. exchange_rate
76
+ #output: xml with attributes eg. exchangeRate="0.011"
77
+ def self.find_forex_offer_by_external_key(external_key)
78
+ params = {'externalKey' => external_key}
79
+ get_data("forexOffers", params)
80
+ end
81
+
82
+ #Update Forex Offer to Status CANCELLED
83
+ def self.cancel_forex_offer(forex_offer_id, ipaddress)
84
+ params = {'forexOfferId' => forex_offer_id, 'ipAddress' => ipaddress, 'status' => 'CANCELLED'}
85
+ put_data("forexOffer/#{forex_offer_id}", params)
86
+ end
87
+
88
+ #Add Forex Offer is a class method that add the foreign exchange rate for virtual currencies
89
+ #input: 'AMG', 100, 'AMS', 60
90
+ def self.add_forex_offer(exchange_rate)
91
+ params = {
92
+ storeId: 3190,
93
+ description: exchange_rate.to_s,
94
+ fromCurrencyName: exchange_rate.from_currency.vcx_name,
95
+ toCurrencyName: exchange_rate.to_currency.vcx_name,
96
+ exchangeRate: exchange_rate.exchange_rate,
97
+ externalKey: exchange_rate.id,
98
+ effectiveDate: generate_date(DateTime.now),
99
+ expirationDate: generate_date(DateTime.now + 75.years),
100
+ isDefault: false,
101
+ isSpecial: false,
102
+ status: 'ACTIVE'
103
+ }
104
+ post_data("forexOffer", params)
105
+ end
106
+
107
+ #Create purchase order is a class method that creates a new purchaseOrder in the elements system depending on the order type
108
+ def self.create_purchase_order( order, ipaddress='1.1.1.1' )
109
+ lineItems, payment = send("#{order.order_type}_purchase_info", order, ipaddress)
110
+ elements_ids = Array.new
111
+
112
+
113
+ lineItems.each_with_index do |lineItem, index|
114
+ params = {
115
+ orderCommand: 'AUTHORIZE',
116
+ buyerUser: {'@id' => order.user.elements_id},
117
+ lineItems: lineItem,
118
+ payment: payment[index]
119
+ }
120
+ rs = XmlSimple.xml_in post_xml_data("purchaseOrder", params,"purchaseOrder")
121
+ elements_ids << rs['id']
122
+ end
123
+ save_order_elements(elements_ids, order)
124
+ end
125
+
126
+ #Process purchase order is a class method that processes an already created order
127
+ def self.process_purchase_order( order, ipaddress='1.1.1.1' )
128
+ #elements_id = create_purchase_order(order, ipaddress)
129
+ params = {
130
+ commandType: 'CHARGE'
131
+ }
132
+
133
+ elements_ids = fetch_order_elements(order)
134
+ elements_ids.each do |elements_id|
135
+ XmlSimple.xml_in post_xml_data("purchaseOrder/#{elements_id}/command", params,"purchaseOrderCommand")
136
+ end
137
+ end
138
+
139
+ #Cancel Purchase Order is a class method that cancels an order that has already been created
140
+ def self.cancel_purchase_order( order, ipaddress='1.1.1.1' )
141
+ params = {
142
+ commandType: 'CANCEL'
143
+ }
144
+ XmlSimple.xml_in post_xml_data("purchaseOrder/#{order.elements_id}/command", params,"purchaseOrderCommand")
145
+ end
146
+
147
+ #Find purchase Order is a class method that returns the purchase order
148
+ #output: xml with attributes
149
+ def self.find_purchase_order(purchase_order_id)
150
+ params = {'id' => purchase_order_id }
151
+ get_data("purchaseOrder/#{purchase_order_id}", params)
152
+ end
153
+
154
+
155
+ #Buy Purchase Info is a class method that returns the buy line items and payment information for the order
156
+ def self.buy_purchase_info(order, ipaddress)
157
+ sell_purchase_info(order, ipaddress)
158
+ end
159
+
160
+ #Sell Purchase Info is a class method that returns the sell line items and payment information for the order
161
+ def self.sell_purchase_info(order, ipaddress)
162
+ line_items = Array.new
163
+ line_items << [{ 'forexOffer' => { 'forexOfferRequest' => { '@amountFromCurrency' => order.from_amount.abs, '@id' => find_or_create_forex_offer(ExchangeRate.find(order.exchange_rate_id), ipaddress), '@buyerAccountId' => order.to_account.elements_id } } }]
164
+
165
+ payment = [{
166
+ '@currencyId' => order.from_currency.elements_id,
167
+ 'tfeAccountId' => order.from_account.elements_id
168
+ }]
169
+
170
+ return line_items, payment
171
+ end
172
+
173
+ #Sell Purchase Info is a class method that returns the exchange line items and payment information for the order
174
+ def self.exchange_purchase_info(order, ipaddress)
175
+ vcx_currency = Currency.find_by_currency_type('real')
176
+
177
+ sell_exchange_rate = Forex.find_exchange_rate(Forex.find_by_currency_id(order.from_currency), Forex.find_by_currency_id(vcx_currency))
178
+ buy_exchange_rate = Forex.find_exchange_rate(Forex.find_by_currency_id(vcx_currency), Forex.find_by_currency_id(order.to_currency))
179
+
180
+ line_items = Array.new
181
+ line_items << [{ 'forexOffer' => { 'forexOfferRequest' => { '@amountFromCurrency' => order.from_amount.abs, '@id' => find_or_create_forex_offer(sell_exchange_rate, ipaddress), '@buyerAccountId' => order.user.accounts.find_by_currency_id(vcx_currency).elements_id } } }]
182
+ line_items << [{ 'forexOffer' => { 'forexOfferRequest' => { '@amountFromCurrency' => order.from_amount.abs * sell_exchange_rate.exchange_rate, '@id' => find_or_create_forex_offer(buy_exchange_rate, ipaddress), '@buyerAccountId' => order.to_account.elements_id } } }]
183
+
184
+
185
+ payment = [
186
+ {
187
+ '@currencyId' => order.from_currency.elements_id,
188
+ 'tfeAccountId' => order.from_account.elements_id
189
+ },
190
+ {
191
+ '@currencyId' => vcx_currency.elements_id,
192
+ 'tfeAccountId' => order.user.accounts.find_by_currency_id(vcx_currency).elements_id
193
+ }
194
+ ]
195
+
196
+ return line_items, payment
197
+ end
198
+
199
+
200
+ #Fetch Order Elements is a class method that fetches the elements_id from order table depending on the order type
201
+ def self.fetch_order_elements(order)
202
+ elements_id = order.elements_id
203
+ case order.order_type
204
+ when /['sell'|'buy']/
205
+ [elements_id]
206
+ when 'exchange'
207
+ order.elements_id.split('|')
208
+ end
209
+ end
210
+
211
+ #Save Order Elements is a class method that saves the elements_id from order table depending on the order type
212
+ def self.save_order_elements(elements_ids, order)
213
+ case order.order_type
214
+ when /['sell'|'buy']/
215
+ order.update_column 'elements_id', elements_ids.first
216
+ when 'exchange'
217
+ order.update_column 'elements_id', elements_ids.join('|')
218
+ end
219
+ end
220
+
221
+
222
+ #Find account is a class method that find account via account_id
223
+ #input: eg. Account.find(254)
224
+ #output: eg. "account254"
225
+ def self.find_account_name(account)
226
+ params = {program: "var account = es.findAccountById(#{account.elements_id}, authInfo); '' + account.name;", ipAddress: '123.123.123.123'}
227
+ post_data("batch", params)
228
+ end
229
+
230
+ #Create account is a class method that creates an account in elements from the Account model object
231
+ #input: eg. Account.find(254), '255.255.255.255'
232
+ #output: elements id
233
+ def self.create_account(account, ip_address)
234
+ params ={
235
+ program: "
236
+ var accountId = es.addAccount(#{account.user.elements_id}, 'account#{account.id}', #{account.currency.elements_id}, null, authInfo);
237
+ es.addToAccountBalance(new java.lang.Long(accountId), new java.math.BigDecimal(#{account.balance}), requestContext, authInfo);
238
+ '' + accountId;
239
+ ",
240
+ ipAddress: ip_address
241
+ }
242
+ elements_account_id = post_data("batch", params) + ''
243
+ #account.update_column('elements_id', elements_account_id.to_i)
244
+ elements_account_id
245
+ end
246
+
247
+ #Find balance is a class method that returns the balance of the Account model object from elements
248
+ #input eg. Account.find(254), '255.255.255.255'
249
+ #output: eg. 3214
250
+ def self.find_balance(account, ip_address)
251
+ params = {
252
+ program: "
253
+ var balance = es.balanceInquiry(#{account.elements_id}, authInfo);
254
+ '' + balance.amount;
255
+ ",
256
+ ipAddress: ip_address
257
+ }
258
+ post_data("batch", params)
259
+ end
260
+
261
+ #Add account balance is a class method that adds the account balance to the elements
262
+ #input: eg. Account.find(254), '255.255.255.255'
263
+ #output
264
+ def self.set_account_balance(account, ip_address)
265
+ balance = account.balance.to_f - find_balance(account, ip_address).to_f
266
+ command = balance >=0 ? "addToAccountBalance" : "subtractFromAccountBalance"
267
+ params ={program: "es.#{command}(#{account.elements_id}, new java.math.BigDecimal(#{balance.abs}), requestContext, authInfo);''", ipAddress: ip_address}
268
+ post_data('batch', params)
269
+ end
270
+
271
+
272
+ private
273
+ #Get_default_params are a list of common params required for all the calls made to elements
274
+ def self.get_default_params
275
+ {
276
+ 'auth.partnerId' => '$apiactor',
277
+ 'auth.accessKey' => 'hvTmKSjSdj' ,
278
+ 'auth.appFamilyId' => '1327520603300',
279
+ 'auth.namespaceId' => '0'
280
+ }
281
+ end
282
+
283
+ def self.get_xml_default_params
284
+ newparams={}
285
+ get_default_params.each{|key,value| newparams["@#{key.gsub(/auth./,'')}"]=value}
286
+ newparams
287
+ end
288
+
289
+ #Generate_url method returns the string of the current url used
290
+ def self.generate_url(url)
291
+ @url + url
292
+ end
293
+
294
+ #Get_data method gets data from elements using the get http method
295
+ def self.get_data(api_url, params={} )
296
+ RestClient.get generate_url(api_url), {params: get_default_params.merge(params)}
297
+ end
298
+
299
+ #Post_data method posts data to elements using the post http method
300
+ def self.post_data(api_url, params={}, *content_type )
301
+ RestClient.post( generate_url(api_url), params.merge(get_default_params), content_type)
302
+ end
303
+
304
+ def self.post_xml_data(api_url, params, root_name)
305
+ xml = XmlSimple.xml_out get_xml_default_params.merge(params), { 'AttrPrefix' => true, 'RootName' => root_name, 'XmlDeclaration' => true, 'GroupTags' => { :lineItems => 'lineItem' } }
306
+ response = RestClient.post generate_url(api_url), xml, :content_type => :xml
307
+ end
308
+
309
+
310
+
311
+ #Put_data method posts data to elements using the post http method
312
+ def self.put_data(api_url,params={})
313
+ RestClient.put generate_url(api_url), params.merge(get_default_params )
314
+ end
315
+
316
+ #Delete method makes a call to elements Api using the delete http method
317
+ def self.delete(api_url)
318
+ RestClient.delete generate_url(api_url), DEFAULTAPI
319
+ end
320
+
321
+ #Generate_date method generates date [YYYY]-[MM]-[DD]T[hh]:[mm] as specified by ISO 8601
322
+ def self.generate_date(date_time)
323
+ date_time.strftime "%FT%T%:z"
324
+ end
325
+ end
326
+
327
+ #ApiV1 class uses the older v1 version of the elements Api
328
+ class ApiV1 < Api
329
+ @url = V1URL
330
+ #Update_user method updates the user information using elements API
331
+ def self.update_user(user, ipaddress='123.123.123.123')
332
+ params = {
333
+ 'user.id' => user.elements_id,
334
+ 'ipAddress' => ipaddress,
335
+ 'user.emailAddress' => user.email,
336
+ 'user.gender' => user.gender[0],
337
+ 'user.dateOfBirth' => user.dob.strftime("%Y/%m/%d")
338
+ }
339
+ post_data 'user/update', params
340
+ end
341
+
342
+ #Find Currencies is a class method that returns all the currencies added to Elements
343
+ def self.find_currencies
344
+ get_data('currency')
345
+ end
346
+
347
+ #Find currency is a class method that finds a particular currency depending on the currency name or elements_id
348
+ def self.find_currency(currency)
349
+ params = if(currency.elements_id.blank?)
350
+ {"currency.name" => currency.vcx_name}
351
+ else
352
+ {"currency.id" => currency.elements_id}
353
+ end
354
+ get_data('currency', params)
355
+ end
356
+
357
+ end
358
+ end
@@ -0,0 +1,178 @@
1
+ require 'rubygems/create/builder'
2
+ require 'erb'
3
+ require 'fileutils'
4
+
5
+ # The Gem::Commands::CreateCommand class facilitates the `gem create` command.
6
+ class Gem::Commands::CreateCommand < Gem::Command
7
+
8
+ # Default path to templates provided by this plugin.
9
+ TEMPLATES = File.expand_path('../../create/templates', __FILE__)
10
+
11
+ # Initializes the plugin.
12
+ def initialize
13
+ super "create", "Creates a new RubyGem skeleton"
14
+ add_options!
15
+ end
16
+
17
+ # Creates the gem.
18
+ def execute
19
+ @gem_name = get_one_gem_name
20
+ create_gem!
21
+ end
22
+
23
+ # The usage banner displayed for `gem create --help`.
24
+ def usage
25
+ "gem create GEM_NAME"
26
+ end
27
+
28
+ private
29
+
30
+ # Private: Adds command line switches used by this plugin.
31
+ def add_options!
32
+ add_option "--force", "Overwrite existing files" do |force, options|
33
+ options[:force] = force
34
+ end
35
+
36
+ add_option "--git GIT_PATH", "The path to git" do |git, options|
37
+ options[:git] = git
38
+ end
39
+
40
+ add_option "--author AUTHOR", "The author name used in gemspec" do |author, options|
41
+ options[:author] = author
42
+ end
43
+
44
+ add_option "--github-name NAME", "The Github account that will own the gem" do |github, options|
45
+ options[:github_name] = github
46
+ end
47
+
48
+ add_option "--email EMAIL", "The author's email address used in gemspec" do |email, options|
49
+ options[:email] = email
50
+ end
51
+
52
+ add_option "--template-directory DIR", "A custom template directory to use" do |directory, options|
53
+ if File.directory?(directory)
54
+ options[:template_directory] = directory
55
+ else
56
+ raise "Directory #{directory.inspect} doesn't exist!"
57
+ end
58
+ end
59
+ end
60
+
61
+ # Private: Creates the gem skeleton.
62
+ #
63
+ # First any requires directories are created. Then, templates are rendered
64
+ # via ERB and written as new files.
65
+ #
66
+ # When creating directories and files, any occurrence of 'gem_name' is
67
+ # replaced with the name of the gem to be created.
68
+ def create_gem!
69
+ manifest[:directories].each do |dir|
70
+ FileUtils.mkdir_p dir.gsub('gem_name', builder.name)
71
+ end
72
+
73
+ manifest[:files].each do |file|
74
+ dest = file.gsub('gem_name', builder.name).gsub(/\.erb$/, '')
75
+ write_template_file(file, dest)
76
+ end
77
+ end
78
+
79
+ # Private: Returns true if files should be overwritten when creating the new
80
+ # gem.
81
+ #
82
+ # Returns true or false.
83
+ def force?
84
+ !! options[:force]
85
+ end
86
+
87
+ # Private: The directory that contains template files to use when creating
88
+ # the new gem. By default, this is TEMPLATES. A user can specify their own
89
+ # directory with the `--template-directory` command line option.
90
+ #
91
+ # If a block is supplied, it is called within the template directory (i.e.
92
+ # Dir.pwd in the block will be set to the template directory), and the value
93
+ # of this block is returned.
94
+ #
95
+ # If no block is supplied, the String template directory is returned.
96
+ def template_dir
97
+ dir = options[:template_directory] || TEMPLATES
98
+ Dir.chdir(dir) { return yield } if block_given?
99
+ dir
100
+ end
101
+
102
+ # Private: A Hash containing :files and :directories to create.
103
+ #
104
+ # :files - An Array of files that will be created.
105
+ # :directories - An Array of directories that will be created.
106
+ #
107
+ # Returns a Hash.
108
+ def manifest
109
+ @manifest ||= Hash.new.tap do |h|
110
+ template_dir do
111
+ templates = Dir.glob("**/*", File::FNM_DOTMATCH).reject { |t| t =~ /\.\.?$/ }
112
+ h[:files] = templates.reject { |t| File.directory?(t) }
113
+ h[:directories] = templates.select { |t| File.directory?(t) }
114
+ end
115
+ end
116
+ end
117
+
118
+ # Private: Writes a new file from a template.
119
+ #
120
+ # source - Path to the source template.
121
+ # dest - Path to the destination file.
122
+ def write_template_file(source, dest)
123
+ if can_write_file?(dest)
124
+ s = render_file(source)
125
+ File.open(dest, "w") { |file| file.puts s }
126
+ else
127
+ raise "Can't create #{dest.inspect} as it already exists!"
128
+ end
129
+ end
130
+
131
+ # Private: Returns true if the given file can be written.
132
+ #
133
+ # A file can be written if the user specified `--force` via the command
134
+ # line, or the file does not yet exist.
135
+ #
136
+ # file - Path to the file to check.
137
+ #
138
+ # Returns true or false.
139
+ def can_write_file?(file)
140
+ force? || ! File.exists?(file)
141
+ end
142
+
143
+ # Private: Renders a file via ERB within the context of a
144
+ # Gem::Create::Builder instance. This makes methods in that class available
145
+ # in the template.
146
+ #
147
+ # file - Path to the template file.
148
+ #
149
+ # Returns the rendered template as a String.
150
+ def render_file(file)
151
+ ERB.new(read_file(file)).result(builder.get_binding)
152
+ end
153
+
154
+ # Private: Gets the content from the specified file.
155
+ #
156
+ # file - Path to the file to read.
157
+ #
158
+ # Raises RuntimeError if the file doesn't exist.
159
+ #
160
+ # Returns a String.
161
+ def read_file(file)
162
+ template_dir do
163
+ if File.exists?(file)
164
+ File.read(file)
165
+ else
166
+ raise "Template #{file.inspect} doesnt exist!"
167
+ end
168
+ end
169
+ end
170
+
171
+ # Private: Creates/returns a Gem::Create::Builder instance. This will be
172
+ # used to provide variables in template files.
173
+ #
174
+ # Returns a Gem::Create::Builder instance.
175
+ def builder
176
+ @builder ||= Gem::Create::Builder.new(@gem_name, options)
177
+ end
178
+ end
@@ -0,0 +1,63 @@
1
+ module Gem::Create
2
+ # The Builder class is used to provide variables in ERB templates.
3
+ class Builder
4
+ # The name of the gem.
5
+ attr_reader :name
6
+
7
+ # The options supplied to the command line.
8
+ attr_reader :options
9
+
10
+ # Creates a new Builder
11
+ #
12
+ # name - The name of the gem.
13
+ # options - The options used to create the gem.
14
+ def initialize(name, options = {})
15
+ @options = options
16
+ @name = name
17
+ end
18
+
19
+ # Returns the binding of this object.
20
+ def get_binding
21
+ binding
22
+ end
23
+
24
+ # Returns the gem author's name.
25
+ def author
26
+ options[:author] || git_config('user.name')
27
+ end
28
+
29
+ # Returns the gem author's email address.
30
+ def email
31
+ options[:email] || git_config('user.email')
32
+ end
33
+
34
+ # Returns the gem author's Github username.
35
+ def github_name
36
+ options[:github_name] || git_config('github.user')
37
+ end
38
+
39
+ # Returns the given variable from `git config`
40
+ #
41
+ # key - The key to query.
42
+ #
43
+ # Returns a String.
44
+ def git_config(key)
45
+ %x{#{git} config --global #{key} 2> /dev/null}.chomp.strip
46
+ end
47
+
48
+ # The path to git.
49
+ def git
50
+ options[:git] || "git"
51
+ end
52
+
53
+ # The path of the gem.
54
+ def path
55
+ name.gsub('-', '/')
56
+ end
57
+
58
+ # The class name of the gem in CamelCase.
59
+ def gem_class
60
+ name.split('-').map { |seg| seg.gsub(/(?:^|_| )(.)/) { $1.upcase } }.join('::')
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,21 @@
1
+ Copyright (c) <%= Time.now.year %> <%= author %> <<%= email %>>
2
+
3
+ Permission is hereby granted, free of charge, to any person ob-
4
+ taining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without restric-
6
+ tion, including without limitation the rights to use, copy, modi-
7
+ fy, merge, publish, distribute, sublicense, and/or sell copies of
8
+ the Software, and to permit persons to whom the Software is fur-
9
+ nished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONIN-
17
+ FRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,20 @@
1
+ # <%= gem_class %> [![<%= gem_class %> Build Status][Build Icon]][Build Status]
2
+
3
+ Description Here
4
+
5
+ [Build Icon]: https://secure.travis-ci.org/<%= github_name %>/<%= name %>.png?branch=master
6
+ [Build Status]: http://travis-ci.org/<%= github_name %>/<%= name %>
7
+
8
+ ## Note on Patches/Pull Requests
9
+
10
+ * Fork the project.
11
+ * Make your feature addition or bug fix.
12
+ * Add tests for it. This is important so I don't break it in a future version
13
+ unintentionally.
14
+ * Commit, do not bump version. (If you want to have your own version, that is
15
+ fine but bump version in a commit by itself I can ignore when I pull).
16
+ * Send me a pull request. Bonus points for topic branches.
17
+
18
+ ## Copyright
19
+
20
+ Copyright (c) <%= Time.now.year %> <%= author %>. See LICENSE for details.
@@ -0,0 +1,11 @@
1
+ $:.unshift 'lib'
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new :spec
6
+ rescue LoadError
7
+ puts "Please install rspec (bundle install)"
8
+ exit
9
+ end
10
+
11
+ task :default => :spec
@@ -0,0 +1,28 @@
1
+ $:.unshift "lib"
2
+
3
+ require "<%= name %>/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.platform = Gem::Platform::RUBY
7
+ s.name = "<%= path %>"
8
+ s.version = <%= gem_class %>::Version
9
+ s.date = Time.now.strftime("%Y-%m-%d")
10
+ s.summary = "<%= gem_class %>: Description here"
11
+ s.homepage = "https://github.com/<%= github_name %>/<%= name %>"
12
+ s.authors = ["<%= author %>"]
13
+ s.email = "<%= email %>"
14
+
15
+ s.files = %w[ Rakefile README.markdown ]
16
+ s.files += Dir["bin/**/*"] if File.exists? "bin"
17
+ s.files += Dir["lib/**/*", "spec/**/*"]
18
+
19
+ # s.executables = ["templates"]
20
+
21
+ # s.add_dependency("gem", "= 0.0.0")
22
+
23
+ s.add_development_dependency "rspec"
24
+ s.add_development_dependency "rake"
25
+
26
+ s.extra_rdoc_files = ["README.markdown"]
27
+ s.rdoc_options = ["--charset=UTF-8"]
28
+ end
@@ -0,0 +1,3 @@
1
+ module <%= gem_class %>
2
+ VERSION = Version = '0.0.0'
3
+ end
@@ -0,0 +1 @@
1
+ require "<%= path %>/version"
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe <%= gem_class %> do
4
+ it "has some specs"
5
+ end
@@ -0,0 +1,8 @@
1
+ require 'rspec'
2
+ require '<%= path %>'
3
+
4
+ RSpec.configure do |config|
5
+ config.color = true
6
+ config.order = 'rand'
7
+ config.formatter = 'progress'
8
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems/command_manager'
2
+
3
+ Gem::CommandManager.instance.register_command :create
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gem::Commands::CreateCommand do
4
+ it "prints help" do
5
+ out, err = run_command('--help')
6
+ err.must_equal "", "should not write to STDERR"
7
+
8
+ out.must_match "Usage: gem create GEM_NAME [options]"
9
+ out.must_match "--force"
10
+ out.must_match "--git"
11
+ out.must_match "--author"
12
+ out.must_match "--github-name"
13
+ out.must_match "--email"
14
+ out.must_match "--template-directory"
15
+ end
16
+
17
+ describe "generated files" do
18
+ before do
19
+ run_command *%W(
20
+ some_gem
21
+ --author Bender\ Rodriguez
22
+ --email bender@planex.com
23
+ --github bender
24
+ )
25
+ end
26
+
27
+ it_renders "README.markdown" do |data|
28
+ data.must_match "# SomeGem [![SomeGem Build Status"
29
+ data.must_match "https://secure.travis-ci.org/bender/some_gem.png?branch=master"
30
+ data.must_match "http://travis-ci.org/bender/some_gem"
31
+ data.must_match "Copyright (c) #{Time.now.year} Bender Rodriguez"
32
+ end
33
+
34
+ it_renders "LICENSE" do |data|
35
+ data.must_match "Copyright (c) #{Time.now.year} Bender Rodriguez <bender@planex.com>"
36
+ end
37
+
38
+ it_renders "some_gem.gemspec" do |data|
39
+ data.must_match %r{require "some_gem/version}
40
+ data.must_match %r{s\.version\s*= SomeGem::Version}
41
+ data.must_match %r{s\.name\s*= "some_gem"}
42
+ data.must_match %r{s\.summary\s*= "SomeGem: Description here"}
43
+ data.must_match %r{s\.homepage\s*= "https://github\.com/bender/some_gem"}
44
+ data.must_match %r{s\.authors\s*= \["Bender Rodriguez"\]}
45
+ data.must_match %r{s\.email\s*= "bender@planex\.com"}
46
+ end
47
+
48
+ it_renders "lib/some_gem.rb" do |data|
49
+ data.must_match 'require "some_gem/version"'
50
+ end
51
+
52
+ it_renders "lib/some_gem/version.rb" do |data|
53
+ data.must_match "module SomeGem"
54
+ data.must_match " VERSION = Version = '0.0.0'"
55
+ end
56
+
57
+ it_renders "spec/spec_helper.rb"
58
+
59
+ it_renders "spec/some_gem_spec.rb"
60
+
61
+ it_renders "Rakefile"
62
+
63
+ it_renders "Gemfile"
64
+
65
+ it_renders ".travis.yml" do |data|
66
+ data.must_match "recipients:\n - bender@planex.com"
67
+ end
68
+ end
69
+
70
+ describe "custom template directory" do
71
+ it "raises with a non-existing directory" do
72
+ proc { run_command *%W(some_gem --template-dir /dev/null/asdf) }.
73
+ must_raise RuntimeError, 'Directory "/dev/null/asdf" doesn\'t exist!'
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,73 @@
1
+ require "rubygems"
2
+ require "rubygems/mock_gem_ui"
3
+ require "minitest/spec"
4
+ require "tmpdir"
5
+ require "fileutils"
6
+
7
+ class Gem::Create::TestCase < MiniTest::Spec
8
+ # Apply this TestCase to any specs with
9
+ # `describe Gem::Commands::CreateCommand`
10
+ register_spec_type /Gem::Commands::CreateCommand/, Gem::Create::TestCase
11
+
12
+ # Clear the tmpdir if needed.
13
+ before { self.class.rm_tmpdir }
14
+
15
+ # Create a temporary directory.
16
+ def self.tmpdir
17
+ @tmpdir ||= Dir.mktmpdir
18
+ end
19
+
20
+ # Remove the temporary directory.
21
+ def self.rm_tmpdir
22
+ FileUtils.rm_r(tmpdir) if File.exists?(tmpdir)
23
+ ensure
24
+ @tmpdir = nil
25
+ end
26
+
27
+ # Shortcut for specs dealing with generated files.
28
+ #
29
+ # Asserts that the file exists within the temporary directory.
30
+ #
31
+ # path - Path to the subject file
32
+ #
33
+ # If a block is given, it yields the contents of the file.
34
+ #
35
+ # Examples:
36
+ #
37
+ # it_renders "README" do |data|
38
+ # data.must_match /Hello World!/
39
+ # end
40
+ #
41
+ # it_renders "Gemspec"
42
+ def self.it_renders(path)
43
+ it "renders #{path}" do
44
+ file = File.join(self.class.tmpdir, path)
45
+ File.exists?(file).must_equal true, "Expected #{path.inspect} to exist"
46
+
47
+ yield File.read(file) if block_given?
48
+ end
49
+ end
50
+
51
+ # Returns a Gem::MockGemUI. This allows us to work with IO in tests.
52
+ def ui
53
+ @ui ||= Gem::MockGemUi.new
54
+ end
55
+
56
+ # Run the CreateCommand with the specified arguments.
57
+ #
58
+ # Returns an Array, [0] is the output of the command, [1] is the error
59
+ # output.
60
+ def run_command(*args)
61
+ cmd = Gem::Commands::CreateCommand.new
62
+
63
+ Dir.chdir(self.class.tmpdir) do
64
+ Gem::DefaultUserInteraction.use_ui(ui) do
65
+ capture_io { cmd.invoke *args }
66
+ end
67
+ end
68
+
69
+ return ui.output, ui.error
70
+ end
71
+ end
72
+
73
+ MiniTest::Unit.after_tests { Gem::Create::TestCase.rm_tmpdir }
@@ -0,0 +1,4 @@
1
+ require "rubygems"
2
+ require "rubygems/commands/create_command"
3
+ require "minitest/autorun"
4
+ require "minitest/gem_command_test_case"
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vcx-elements
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - livegamer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: minitest
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: ! ' Elements Api'
47
+ email: todd@livegamer.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - Gemfile
53
+ - Rakefile
54
+ - README.markdown
55
+ - gem-create.gemspec
56
+ - LICENSE
57
+ - lib/elements.rb
58
+ - lib/rubygems/commands/create_command.rb
59
+ - lib/rubygems/create/builder.rb
60
+ - lib/rubygems/create/templates/gem_name.gemspec.erb
61
+ - lib/rubygems/create/templates/Gemfile
62
+ - lib/rubygems/create/templates/lib/gem_name/version.rb.erb
63
+ - lib/rubygems/create/templates/lib/gem_name.rb.erb
64
+ - lib/rubygems/create/templates/LICENSE.erb
65
+ - lib/rubygems/create/templates/Rakefile
66
+ - lib/rubygems/create/templates/README.markdown.erb
67
+ - lib/rubygems/create/templates/spec/gem_name_spec.rb.erb
68
+ - lib/rubygems/create/templates/spec/spec_helper.rb.erb
69
+ - lib/rubygems_plugin.rb
70
+ - spec/create_command_spec.rb
71
+ - spec/minitest/gem_command_test_case.rb
72
+ - spec/spec_helper.rb
73
+ homepage: https://github.com/livegamervcxdevteam/elementsapi.git
74
+ licenses: []
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 1.8.24
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: Elements Api
97
+ test_files:
98
+ - spec/create_command_spec.rb
99
+ - spec/minitest/gem_command_test_case.rb
100
+ - spec/spec_helper.rb