frecon 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a8a2e4e957492a0168c9e814b237ea59435aa800
4
- data.tar.gz: 3051b10b6a8e7740370ffd75eebce4230b3ef252
3
+ metadata.gz: fd60a8e39df9d65354023f15a71e7ff1941465cc
4
+ data.tar.gz: 322aad2f9008ee3bac2f566a1afcc7ccc60938f8
5
5
  SHA512:
6
- metadata.gz: b579c98940cd2759ed748dbaea6b51ffeef679c6f08f958a1e7501fda4e5043e20b4fb987422ebb002b013fb679eb1ac4586a6027bfb02186b196507a0faafc7
7
- data.tar.gz: a312a6a56950302d16e0075875e25ef9b830164eb9d7999820e364fa49c5b170a72b4f7bf96ff99a2a64e7cdaca836953b9811fab42a315102586fb03014a7fd
6
+ metadata.gz: d40ef54381e9b613289a0c1b82f486a965975866e1f7e3cbe16ec15285708e05156b2bfc4c6a27a567b3ecd72fa128f379fbcbfad6b008f5ccd19f81970b559b
7
+ data.tar.gz: e6c5a2c2bbddf8de4b04441c59cc45575f76019fb2f81e3d110860b736c8ce8a6ff57203f36d6e6f92066261b52c8b5ad18d9e8052543500d158b74f352c4df2
@@ -0,0 +1,16 @@
1
+ # lib/frecon/base/bson.rb
2
+ #
3
+ # Copyright (C) 2014 Christopher Cooper, Sam Craig, Tiger Huang, Vincent Mai, Sam Mercier, and Kristofer Rye
4
+ #
5
+ # This file is part of FReCon, an API for scouting at FRC Competitions, which is
6
+ # licensed under the MIT license. You should have received a copy of the MIT
7
+ # license with this program. If not, please see
8
+ # <http://opensource.org/licenses/MIT>.
9
+
10
+ module BSON
11
+ class ObjectId
12
+ def as_json(*args)
13
+ to_s
14
+ end
15
+ end
16
+ end
@@ -8,7 +8,7 @@
8
8
  # <http://opensource.org/licenses/MIT>.
9
9
 
10
10
  module FReCon
11
- VERSION = "0.2.2"
11
+ VERSION = "0.3.0"
12
12
 
13
13
  @environment_variable = :development
14
14
 
data/lib/frecon/base.rb CHANGED
@@ -7,5 +7,6 @@
7
7
  # license with this program. If not, please see
8
8
  # <http://opensource.org/licenses/MIT>.
9
9
 
10
+ require "frecon/base/bson"
10
11
  require "frecon/base/object"
11
12
  require "frecon/base/variables"
@@ -34,44 +34,61 @@ module FReCon
34
34
  "Could not find #{model} of #{attribute} #{value}!"
35
35
  end
36
36
 
37
- # Processes a POST/PUT request and returns the post data.
38
- def self.process_json_object_request(request)
37
+ def self.process_json_request(request)
39
38
  # Rewind the request body (an IO object)
40
39
  # in case someone else has already played
41
40
  # through it.
42
41
  request.body.rewind
43
42
 
44
43
  begin
45
- # Parse the POST data as a JSON hash
46
- # (because that's what it is)
47
44
  post_data = JSON.parse(request.body.read)
48
45
  rescue JSON::ParserError => e
49
- # If we have malformed JSON (JSON::ParserError is
50
- # raised), escape out of the function.
51
46
  raise RequestError.new(400, e.message)
52
47
  end
53
48
 
54
- raise RequestError.new(422, "Must pass a JSON object!", {post_data: post_data}) if post_data.is_an?(Array)
55
49
  post_data
56
50
  end
57
51
 
58
52
  def self.create(request, params, post_data = nil)
59
- post_data ||= process_json_object_request request
53
+ post_data ||= process_json_request request
60
54
 
61
- @model = model.new
62
- @model.attributes = post_data
55
+ if post_data.is_an? Array
56
+ results = post_data.map do |post_data_item|
57
+ begin
58
+ self.create(nil, nil, post_data_item)
59
+ rescue RequestError => e
60
+ e.return_value
61
+ end
62
+ end
63
+
64
+ status_code = 201
65
+
66
+ if(results.map do |result|
67
+ result.is_an?(Array) ? result[0] : 422
68
+ end.select do |status_code|
69
+ status_code != 201
70
+ end.count > 0)
71
+
72
+ status_code = 422
73
+ end
63
74
 
64
- if @model.save
65
- [201, @model.to_json]
75
+ [status_code, results.to_json]
66
76
  else
67
- raise RequestError.new(422, @model.errors.full_messages, {params: params, post_data: post_data})
77
+ @model = model.new
78
+ @model.attributes = post_data
79
+
80
+ if @model.save
81
+ [201, @model.to_json]
82
+ else
83
+ raise RequestError.new(422, @model.errors.full_messages, {params: params, post_data: post_data})
84
+ end
68
85
  end
69
86
  end
70
87
 
71
88
  def self.update(request, params, post_data = nil)
72
89
  raise RequestError.new(400, "Must supply a #{model_name.downcase} id!") unless params[:id]
73
90
 
74
- post_data ||= process_json_object_request request
91
+ post_data ||= process_json_request request
75
92
 
76
93
  @model = find_model params
77
94
 
@@ -127,6 +144,8 @@ module FReCon
127
144
  end
128
145
 
129
146
  def self.team_number_to_team_id(post_data)
147
+ return post_data unless post_data.is_a?(Hash)
148
+
130
149
  if post_data["team_number"] && !post_data["team_id"]
131
150
  unless (team = Team.number post_data["team_number"]).nil?
132
151
  post_data["team_id"] = team.id
@@ -143,6 +162,8 @@ module FReCon
143
162
  # This supports match_number and competition_name
144
163
  # or match_number and competition (which is a Hash).
145
164
  def self.match_number_and_competition_to_match_id(post_data)
165
+ return post_data unless post_data.is_a?(Hash)
166
+
146
167
  if post_data["match_number"] && !post_data["match_id"]
147
168
  if post_data["competition_name"] && (competition = Competition.find_by name: post_data["competition_name"])
148
169
  # Try to set the match to the already existing match.
@@ -165,7 +186,7 @@ module FReCon
165
186
  post_data.delete("competition_name")
166
187
 
167
188
  post_data
168
- elsif post_data["competition"] && post_data["competition"]["_id"] && post_data["competition"]["_id"]["$oid"] && (competition = Competition.find_by(id: post_data["competition"]["_id"]["$oid"]))
189
+ elsif post_data["competition"] && post_data["competition"]["_id"] && (competition = Competition.find_by(id: post_data["competition"]["_id"]))
169
190
  # Try to set the match to the already existing match.
170
191
  match = competition.matches.find_by number: post_data["match_number"]
171
192
 
@@ -15,11 +15,23 @@ module FReCon
15
15
  def self.full(params)
16
16
  dump = {}
17
17
 
18
- Model.descendants.each do |child|
19
- dump[child.name.gsub(/FReCon::/, "").downcase.pluralize] = child.all
18
+ ordered_descendants = Model.descendants.sort_by do |model|
19
+ id_fields = model.fields.keys.select do |attribute|
20
+ attribute.ends_with?("_id") && attribute != "_id"
21
+ end
22
+
23
+ [id_fields.count, dump_compliant_name(model)]
24
+ end
25
+
26
+ ordered_descendants.each do |child|
27
+ dump[dump_compliant_name(child)] = child.all
20
28
  end
21
29
 
22
30
  dump.to_json
23
31
  end
32
+
33
+ def self.dump_compliant_name(model)
34
+ model.name.gsub(/FReCon::/, "").downcase.pluralize
35
+ end
24
36
  end
25
37
  end
@@ -9,8 +9,8 @@
9
9
 
10
10
  module FReCon
11
11
  class ParticipationsController < Controller
12
- def self.create(request, params)
13
- super(request, params, team_number_to_team_id(process_json_object_request(request)))
12
+ def self.create(request, params, post_data = nil)
13
+ super(request, params, post_data || team_number_to_team_id(process_json_request(request)))
14
14
  end
15
15
 
16
16
  def self.competition(params)
@@ -13,8 +13,8 @@ require "frecon/models"
13
13
 
14
14
  module FReCon
15
15
  class RecordsController < Controller
16
- def self.create(request, params)
17
- super(request, params, match_number_and_competition_to_match_id(team_number_to_team_id(process_json_object_request(request))))
16
+ def self.create(request, params, post_data = nil)
17
+ super(request, params, post_data || match_number_and_competition_to_match_id(team_number_to_team_id(process_json_request(request))))
18
18
  end
19
19
 
20
20
  def self.competition(params)
@@ -12,8 +12,8 @@ require "frecon/models/robot"
12
12
 
13
13
  module FReCon
14
14
  class RobotsController < Controller
15
- def self.create(request, params)
16
- super(request, params, team_number_to_team_id(process_json_object_request(request)))
15
+ def self.create(request, params, post_data = nil)
16
+ super(request, params, post_data || team_number_to_team_id(process_json_request(request)))
17
17
  end
18
18
 
19
19
  def self.competition(params)
@@ -125,6 +125,9 @@ module FReCon
125
125
  # round (Integer), optional
126
126
  # replay_number (Integer), optional
127
127
 
128
+ # Convert keys to symbols if needed.
129
+ args = Hash[args.map { |key, value| [key.to_sym, value] }]
130
+
128
131
  raise TypeError, "type must be a Symbol or String" unless args[:type].is_a?(Symbol) || args[:type].is_a?(String)
129
132
  raise ArgumentError, "type must be in #{POSSIBLE_TYPES.inspect}" unless POSSIBLE_TYPES.include?(args[:type].to_sym)
130
133
 
data/lib/frecon/model.rb CHANGED
@@ -26,6 +26,10 @@ module FReCon
26
26
  ObjectSpace.each_object(Class).select { |possibleChild| possibleChild < self }
27
27
  end
28
28
 
29
+ def self.controller
30
+ (self.name.pluralize + "Controller").constantize
31
+ end
32
+
29
33
  def no_invalid_relations
30
34
  # Get all of the belongs_to fields (ends with "_id" and not "_id" because that is the id).
31
35
  attributes.keys.select { |attribute| attribute.end_with?("_id") && attribute != "_id" }.each do |relation|
@@ -31,6 +31,8 @@ module FReCon
31
31
  when String
32
32
  Position.new(object).mongoize
33
33
  when Hash
34
+ # Convert keys to symbols if necessary.
35
+ object = Hash[object.map { |key, value| [key.to_sym, value] }]
34
36
  Position.new(object[:alliance], object[:number]).mongoize
35
37
  else
36
38
  object
@@ -45,6 +47,8 @@ module FReCon
45
47
  when String
46
48
  Position.new(object).mongoize
47
49
  when Hash
50
+ # Convert keys to symbols if necessary.
51
+ object = Hash[object.map { |key, value| [key.to_sym, value] }]
48
52
  Position.new(object[:alliance], object[:number]).mongoize
49
53
  else
50
54
  object
@@ -0,0 +1,70 @@
1
+ # lib/frecon/scraper.rb
2
+ #
3
+ # Copyright (C) 2014 Christopher Cooper, Sam Craig, Tiger Huang, Vincent Mai, Sam Mercier, and Kristofer Rye
4
+ #
5
+ # This file is part of FReCon, an API for scouting at FRC Competitions, which is
6
+ # licensed under the MIT license. You should have received a copy of the MIT
7
+ # license with this program. If not, please see
8
+ # <http://opensource.org/licenses/MIT>.
9
+
10
+ require "httparty"
11
+
12
+ module FReCon
13
+ # The default scraper scrapes other FReCon instances.
14
+ # To scrape a different source, a descendant scraper should be used.
15
+ class Scraper
16
+ def initialize(base_uri)
17
+ @base_uri = base_uri
18
+ end
19
+
20
+ # Reads and imports a data string.
21
+ # Determines what to do with information in the `context` hash.
22
+ def read(data, context = {})
23
+ # `data` will be a string, so we need to convert it from JSON.
24
+ data = JSON.parse(data)
25
+
26
+ # Here we want `context` to tell us what model we are making.
27
+ if context[:model]
28
+ result = context[:model].controller.create(nil, nil, data)
29
+ result.first == 201 ? result.first : JSON.parse(result.last)
30
+ else
31
+ # Therefore, we must be dealing with a dump.
32
+ statuses = data.map do |key, value|
33
+ begin
34
+ unless value.empty?
35
+ model = ("FReCon::" + key.singularize.capitalize).constantize
36
+ result = model.controller.create(nil, nil, value)
37
+ result.first == 201 ? result.first : JSON.parse(result.last)
38
+ end
39
+ rescue Moped::Errors::OperationFailure => e
40
+ RequestError.new(422, "A model already exists in your database with the key you are trying to import.\nPerhaps you should clear your database?").return_value
41
+ end
42
+ end
43
+ statuses.delete(nil)
44
+ statuses
45
+ end
46
+ end
47
+
48
+ # If no arguments are passed, will import the whole other database.
49
+ # If only one argument is passed, will import all of that model.
50
+ # If two arguments are passed, will import the models that match
51
+ # the query params.
52
+ def get(model = nil, query = {})
53
+ # Turns something like "team" into Team.
54
+ model = ("FReCon::" + model.capitalize).constantize if model.is_a?(String)
55
+
56
+ # The route name for the model branch.
57
+ route_name = model.name.gsub(/FReCon::/, "").downcase.pluralize if model
58
+
59
+ if !model && query.empty?
60
+ data = HTTParty.get("http://#{@base_uri}:4567/dump")
61
+ elsif model && query.empty?
62
+ data = HTTParty.get("http://#{@base_uri}:4567/#{route_name}")
63
+ else
64
+ data = HTTParty.get("http://#{@base_uri}:4567/#{route_name}", { query: query })
65
+ end
66
+
67
+ read data.body, model: model
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,10 @@
1
+ # lib/frecon/scrapers.rb
2
+ #
3
+ # Copyright (C) 2014 Christopher Cooper, Sam Craig, Tiger Huang, Vincent Mai, Sam Mercier, and Kristofer Rye
4
+ #
5
+ # This file is part of FReCon, an API for scouting at FRC Competitions, which is
6
+ # licensed under the MIT license. You should have received a copy of the MIT
7
+ # license with this program. If not, please see
8
+ # <http://opensource.org/licenses/MIT>.
9
+
10
+ require "frecon/scraper"
data/lib/frecon/server.rb CHANGED
@@ -22,6 +22,7 @@ module FReCon
22
22
  end
23
23
 
24
24
  def self.run!
25
+ set :environment, FReCon.environment
25
26
  Database.setup(FReCon.environment)
26
27
 
27
28
  super
data/lib/frecon.rb CHANGED
@@ -7,8 +7,12 @@
7
7
  # license with this program. If not, please see
8
8
  # <http://opensource.org/licenses/MIT>.
9
9
 
10
+ require "mongoid"
11
+
10
12
  require "frecon/base"
11
13
 
12
14
  require "frecon/database"
13
15
  require "frecon/server"
14
16
  require "frecon/console"
17
+
18
+ require "frecon/scrapers"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: frecon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Craig
@@ -57,6 +57,20 @@ dependencies:
57
57
  - - "~>"
58
58
  - !ruby/object:Gem::Version
59
59
  version: '4.0'
60
+ - !ruby/object:Gem::Dependency
61
+ name: httparty
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '0.13'
67
+ type: :runtime
68
+ prerelease: false
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '0.13'
60
74
  description: A JSON API for scouting FRC competitions that manages the database for
61
75
  the user.
62
76
  email: frc-frecon@googlegroups.com
@@ -68,6 +82,7 @@ files:
68
82
  - bin/frecon
69
83
  - lib/frecon.rb
70
84
  - lib/frecon/base.rb
85
+ - lib/frecon/base/bson.rb
71
86
  - lib/frecon/base/object.rb
72
87
  - lib/frecon/base/variables.rb
73
88
  - lib/frecon/console.rb
@@ -94,6 +109,8 @@ files:
94
109
  - lib/frecon/position.rb
95
110
  - lib/frecon/request_error.rb
96
111
  - lib/frecon/routes.rb
112
+ - lib/frecon/scraper.rb
113
+ - lib/frecon/scrapers.rb
97
114
  - lib/frecon/server.rb
98
115
  homepage: https://github.com/frc-frecon/frecon
99
116
  licenses: