vcx-elements 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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