octopart-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+
9
+ gem "httparty", "0.9.0"
10
+ gem "fakeweb", "1.3.0"
11
+
12
+ group :development do
13
+ gem "shoulda", ">= 0"
14
+ gem "rdoc", "~> 3.12"
15
+ gem "bundler", "~> 1.0"
16
+ gem "jeweler", "~> 1.8.4"
17
+ gem "simplecov"
18
+ end
@@ -0,0 +1,51 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.2.9)
5
+ i18n (~> 0.6)
6
+ multi_json (~> 1.0)
7
+ bourne (1.1.2)
8
+ mocha (= 0.10.5)
9
+ fakeweb (1.3.0)
10
+ git (1.2.5)
11
+ httparty (0.9.0)
12
+ multi_json (~> 1.0)
13
+ multi_xml
14
+ i18n (0.6.1)
15
+ jeweler (1.8.4)
16
+ bundler (~> 1.0)
17
+ git (>= 1.2.5)
18
+ rake
19
+ rdoc
20
+ json (1.7.5)
21
+ metaclass (0.0.1)
22
+ mocha (0.10.5)
23
+ metaclass (~> 0.0.1)
24
+ multi_json (1.5.0)
25
+ multi_xml (0.5.1)
26
+ rake (10.0.3)
27
+ rdoc (3.12)
28
+ json (~> 1.4)
29
+ shoulda (3.3.2)
30
+ shoulda-context (~> 1.0.1)
31
+ shoulda-matchers (~> 1.4.1)
32
+ shoulda-context (1.0.1)
33
+ shoulda-matchers (1.4.2)
34
+ activesupport (>= 3.0.0)
35
+ bourne (~> 1.1.2)
36
+ simplecov (0.7.1)
37
+ multi_json (~> 1.0)
38
+ simplecov-html (~> 0.7.1)
39
+ simplecov-html (0.7.1)
40
+
41
+ PLATFORMS
42
+ ruby
43
+
44
+ DEPENDENCIES
45
+ bundler (~> 1.0)
46
+ fakeweb (= 1.3.0)
47
+ httparty (= 0.9.0)
48
+ jeweler (~> 1.8.4)
49
+ rdoc (~> 3.12)
50
+ shoulda
51
+ simplecov
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Parker Boundy
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ 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 OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,37 @@
1
+ = Octopart-ruby
2
+
3
+ Octopart-ruby is a simple Ruby wrapper for the Octopart.com API
4
+
5
+ == Getting Started
6
+
7
+ To install Octopart-ruby you can either add it to your Gemfile:
8
+
9
+ gem "octopart-ruby"
10
+
11
+ or you can install it from the command line:
12
+
13
+ $ gem install octopart-ruby
14
+
15
+
16
+ To create a new instance of the client you will need to register for an API key at http://octopart.com/api/register. Once you have an API key you can use Octopart-ruby as follows:
17
+
18
+ @client = Octopart::Client.new(api_key)
19
+
20
+ == Contributing to Octopart-ruby
21
+
22
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
23
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
24
+ * Fork the project.
25
+ * Start a feature/bugfix branch.
26
+ * Commit and push until you are happy with your contribution.
27
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
28
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
29
+
30
+ == Copyright
31
+
32
+ Octopart-ruby is released under the MIT license.
33
+
34
+ See LICENSE.txt or http://opensource.org/licenses/MIT for further details.
35
+
36
+ Copyright (c) 2012 Parker Boundy.
37
+
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "octopart-ruby"
18
+ gem.homepage = "http://github.com/parkerboundy/octopart-ruby"
19
+ gem.license = "MIT"
20
+ gem.summary = "Ruby wrapper for the Octopart API"
21
+ gem.description = "Ruby wrapper for the Octopart API"
22
+ gem.email = "parkerboundy@gmail.com"
23
+ gem.authors = ["Parker Boundy"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+
36
+ task :default => :test
37
+
38
+ require 'rdoc/task'
39
+ Rake::RDocTask.new do |rdoc|
40
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
+
42
+ rdoc.rdoc_dir = 'rdoc'
43
+ rdoc.title = "octopart-ruby #{version}"
44
+ rdoc.rdoc_files.include('README*')
45
+ rdoc.rdoc_files.include('lib/**/*.rb')
46
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,37 @@
1
+ require "rubygems"
2
+ require 'octopart-ruby'
3
+
4
+ @octopart = Octopart::Client.new('02566ff6')
5
+
6
+ # Fetch a category object by its id
7
+ puts @octopart.category(4174)
8
+
9
+ # Fetch multiple category objects by their ids
10
+ puts @octopart.categories([4215,4174,4780])
11
+
12
+ # Execute search over category objects
13
+ puts @octopart.search_categories('resistor')
14
+
15
+ # Fetch a part object by its id
16
+ puts @octopart.part(39619421)
17
+
18
+ # Fetch multiple part objects by their ids
19
+ puts @octopart.parts([39619421,29035751,31119928])
20
+
21
+ # Execute search over part objects
22
+ puts @octopart.search_parts('resistor')
23
+
24
+ # Suggest a part search query string
25
+ puts @octopart.suggest_parts('sn74f')
26
+
27
+ # Match (manufacturer,mpn) to part uids
28
+ puts @octopart.match_part('texas instruments', 'SN74LS240N')
29
+
30
+ # Fetch a partattribute object by its id
31
+ puts @octopart.part_attribute('capacitance')
32
+
33
+ # Fetch multiple partattribute objects by their ids
34
+ puts @octopart.part_attributes(["capacitance","resistance"])
35
+
36
+ # Match lines of a BOM to parts
37
+ puts @octopart.bom_match({"mpn_or_sku"=> "60K6871", "manufacturer"=> "Texas Instruments"})
@@ -0,0 +1,23 @@
1
+ require 'httparty'
2
+
3
+ # APIKeyNotSet is called when a client is instantiated without an api_key
4
+ class APIKeyNotSet < StandardError; end
5
+
6
+ module Octopart
7
+
8
+ # api_key - The API key to use
9
+ def self.api_key
10
+ raise APIKeyNotSet if @api_key.nil?
11
+ @api_key
12
+ end
13
+
14
+ # api_key - The API key to use
15
+ def self.api_key=(api_key)
16
+ @api_key = api_key
17
+ end
18
+
19
+ end
20
+
21
+ directory = File.expand_path(File.dirname(__FILE__))
22
+
23
+ require File.join(directory, 'octopart', 'client')
@@ -0,0 +1,283 @@
1
+ # Public: A simple ruby wrapper for the Octopart.com API
2
+ # All methods are module methods and should be called on the Octopart module.
3
+ #
4
+ # Examples
5
+ #
6
+ # Octopart::Client.new('apikey')
7
+ #
8
+ module Octopart
9
+
10
+ # Public: An Octopart.com API Client
11
+ #
12
+ #
13
+ # Examples
14
+ #
15
+ # Octopart::Client.new('apikey')
16
+ #
17
+ class Client
18
+
19
+ include HTTParty
20
+ base_uri 'http://octopart.com/api/v2'
21
+ format :json
22
+
23
+
24
+ # Public: The API key for the client
25
+ attr_reader :api_key
26
+
27
+ # Public: Initialize an Octopart client
28
+ #
29
+ # api_key - The API key to use
30
+ # You can get an Octopart API key at http://octopart.com/api/register
31
+ def initialize(api_key=nil)
32
+ @api_key = api_key
33
+ @api_key ||= Octopart.api_key
34
+
35
+ end
36
+
37
+
38
+ # Public: Fetch a category object by its id
39
+ #
40
+ # id - The id of a category object
41
+ #
42
+ # Examples
43
+ #
44
+ # category(4174)
45
+ # # => category hash
46
+ #
47
+ # Returns a category hash
48
+ def category(id)
49
+ if id.is_a? Array
50
+ categories(id)
51
+ else
52
+ self.class.get('/categories/get', :query => {:id => id, :apikey => @api_key}).parsed_response
53
+ end
54
+ end
55
+
56
+
57
+ # Public: Fetch multiple category objects by their ids
58
+ #
59
+ # ids - Array of category object ids
60
+ #
61
+ # Examples
62
+ #
63
+ # categories([4215,4174,4780])
64
+ # # => category hash
65
+ #
66
+ # Returns a category hash
67
+ def categories(ids)
68
+ raise(ArgumentError, 'ids must be an array') unless ids.is_a?Array
69
+ self.class.get('/categories/get_multi', :query => {:ids => "[#{ids.join(",")}]", :apikey => @api_key}).parsed_response
70
+ end
71
+
72
+ # Public: Execute search over category objects
73
+ #
74
+ # q - Query string
75
+ # start - Ordinal position of first result. First position is 0. Default is 0
76
+ # limit - Maximum number of results to return. Default is 10
77
+ #
78
+ # Examples
79
+ #
80
+ # search_categories('resistor')
81
+ # # => category hash
82
+ #
83
+ # Returns a category hash
84
+ def search_categories(query, start=0, limit=10)
85
+ raise(ArgumentError, 'query must be a string > 2 characters and start/limit must be < 100') unless (query.is_a?(String) && query.length > 2 && start.between?(0, 100) &&limit.between?(0,100))
86
+ self.class.get('/categories/search', :query => {:q => query, :start => start, :limit => limit, :apikey => @api_key}).parsed_response
87
+ end
88
+
89
+ # Public: Fetch a part object by its id
90
+ #
91
+ # uid - the id of a part object
92
+ #
93
+ # Examples
94
+ #
95
+ # part(39619421)
96
+ # # => part hash
97
+ #
98
+ # Returns a part hash
99
+ def part(uid)
100
+ if uid.is_a? Array
101
+ parts(uid)
102
+ else
103
+ self.class.get('/parts/get', :query => {:uid => uid, :apikey => @api_key}).parsed_response
104
+ end
105
+ end
106
+
107
+ # Public: Fetch multiple part objects by their ids
108
+ #
109
+ # uids - JSON encoded list of part object ids. Max number of ids is 100.
110
+ #
111
+ # Examples
112
+ #
113
+ # parts([39619421,29035751,31119928])
114
+ # # => parts hash
115
+ #
116
+ # Returns a part hash
117
+ def parts(uids)
118
+ raise(ArgumentError, 'uids must be an array') unless uids.is_a?Array
119
+ self.class.get('/parts/get_multi', :query => {:uids => "[#{uids.join(",")}]", :apikey => @api_key}).parsed_response
120
+ end
121
+
122
+ # Public: Execute search over part objects
123
+ #
124
+ # query - Query string
125
+ # start - Ordinal position of first result. First position is 0. Default is 0. Maximum is 1000.
126
+ # limit - Number of results to return. Default is 10. Maximum is 100.
127
+ #
128
+ # Examples
129
+ #
130
+ # search_parts('capacitor')
131
+ # # => part hash
132
+ #
133
+ # search_parts('capacitor', 50)
134
+ # # => part hash
135
+ #
136
+ # search_parts('capacitor', 100, 25)
137
+ # # => part hash
138
+ #
139
+ # Returns a part hash
140
+ def search_parts(query, start=0, limit=10)
141
+ raise(ArgumentError, 'query must be a string > 2 characters, start < 1000, and limit must be < 100') unless (query.is_a?(String) && query.length > 2 && start.between?(0, 1000) &&limit.between?(0,100))
142
+ self.class.get('/parts/search', :query => {:q => query, :start => start, :limit => limit, :apikey => @api_key}).parsed_response
143
+ end
144
+
145
+ # Public: Suggest a part search query string
146
+ #
147
+ # q - Query string. Minimum of 2 characters.
148
+ # limit - Maximum number of results to return. Default is 5. Maximum is 10.
149
+ #
150
+ # Examples
151
+ #
152
+ # suggest_parts('sn74f')
153
+ # # => parts hash
154
+ #
155
+ # suggest_parts('sn74f', 10)
156
+ # # => parts hash
157
+ #
158
+ # Returns a part hash
159
+ def suggest_parts(query, limit=5)
160
+ raise(ArgumentError, 'query must be a string > 2 characters, and limit must be < 10') unless (query.is_a?(String) && query.length > 2 && limit.between?(0,10))
161
+ self.class.get('/parts/suggest', :query => {:q => query.split(' ').join('+'), :limit => limit, :apikey => @api_key}).parsed_response
162
+ end
163
+
164
+ # Public: Match (manufacturer,mpn) to part uids
165
+ #
166
+ # manufacturer_name - Manufacturer name
167
+ # mpn - Manufacturer part number
168
+ #
169
+ # Examples
170
+ #
171
+ # match_part('Texas Instruments', 'SN74LS240N')
172
+ # # => parts hash
173
+ #
174
+ # Returns a part hash
175
+ def match_part(manufacturer_name, mpn)
176
+ self.class.get('/parts/match', :query => {:manufacturer_name => manufacturer_name, :mpn => mpn, :apikey => @api_key}).parsed_response
177
+ end
178
+
179
+ # Public: Helper method for match_part(manufacturer,mpn)
180
+ #
181
+ # manufacturer_name - Manufacturer name
182
+ # mpn - Manufacturer part number
183
+ #
184
+ # Examples
185
+ #
186
+ # match_part('Texas Instruments', 'SN74LS240N')
187
+ # # => parts hash
188
+ #
189
+ # Returns a part hash
190
+ def match(manufacturer_name, mpn)
191
+ match_part(manufacturer_name, mpn)
192
+ end
193
+
194
+ # Public: Fetch a partattribute object by its id
195
+ #
196
+ # fieldname - The fieldname of a partattribute object
197
+ #
198
+ # Examples
199
+ #
200
+ # part_attribute('capacitance')
201
+ # # => partattribute hash
202
+ #
203
+ # Returns a partattribute hash
204
+ def part_attribute(fieldname)
205
+ if fieldname.is_a? Array
206
+ part_attributes(fieldname)
207
+ else
208
+ self.class.get('/partattributes/get', :query => {:fieldname => fieldname, :apikey => @api_key}).parsed_response
209
+ end
210
+ end
211
+
212
+ # Public: Fetch multiple partattribute objects by their ids
213
+ #
214
+ # fieldnames - The fieldnames of a partattribute objects
215
+ #
216
+ # Examples
217
+ #
218
+ # part_attributes(['capacitance', 'resistance'])
219
+ # # => partattribute hash
220
+ #
221
+ # Returns a partattribute hash
222
+ def part_attributes(fieldnames)
223
+ raise(ArgumentError, 'fieldnames must be an array') unless fieldnames.is_a?Array
224
+ self.class.get('/partattributes/get_multi', :query => {:fieldnames => "["+fieldnames.map{|v| "\"#{v}\""}.join(',')+"]", :apikey => @api_key}).parsed_response
225
+ end
226
+
227
+ # Public: Match lines of a BOM to parts
228
+ #
229
+ # lines - hash made up of the following optional parameters:
230
+ # q - Free form query
231
+ # mpn - MPN string
232
+ # manufacturer - Manufacturer name
233
+ # sku - Supplier SKU string
234
+ # supplier - Supplier name
235
+ # mpn_or_sku - Match on MPN or SKU
236
+ # start=0 - Ordinal position of first item
237
+ # limit=3 - Maximum number of items to return
238
+ # reference - Arbitrary reference string to differentiate results
239
+ #
240
+ # Examples
241
+ #
242
+ # bom_match({"mpn_or_sku"=> "60K6871", "manufacturer" => "Texas Instruments"})
243
+ # # => match hash
244
+ #
245
+ # Returns a match hash
246
+ def bom_match(lines)
247
+ raise(ArgumentError, 'lines must be a hash') unless lines.is_a?(::Hash)
248
+ self.class.get('/bom/match', :query => {:lines => "[{"+lines.map{|k,v| "\"#{k}\":\"#{v}\""}.join(',')+"}]", :apikey => @api_key}).parsed_response
249
+ end
250
+
251
+ # Public: Helper method for searches
252
+ #
253
+ # type - String name of the type
254
+ # query - Query string
255
+ # start - Ordinal position of first result. First position is 0. Default is 0. Maximum is 1000.
256
+ # limit - Number of results to return. Default is 10. Maximum is 100.
257
+ #
258
+ # Examples
259
+ #
260
+ # search_parts('parts', 'capacitor')
261
+ # # => part hash
262
+ #
263
+ # search_parts('categories', 'capacitor', 50)
264
+ # # => part hash
265
+ #
266
+ # search_parts('parts', 'capacitor', 100, 25)
267
+ # # => part hash
268
+ #
269
+ # Returns a part hash
270
+ def search(type, query, start=0, limit=10)
271
+ raise(ArgumentError, 'query must be a string > 2 characters and start/limit must be < 100') unless (query.is_a?(String) && query.length > 2 && start.between?(0, 100) &&limit.between?(0,100))
272
+ if type.downcase == 'part' || type.downcase == 'parts'
273
+ search_parts(query, start, limit)
274
+ elsif type.downcase == 'category' || type.downcase == 'categories'
275
+ search_categories(query, start, limit)
276
+ else
277
+ raise(ArgumentError, "type must be either 'parts' or 'categories'")
278
+ end
279
+ end
280
+
281
+ end
282
+
283
+ end