motion-bundler 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.rdoc +5 -0
- data/Gemfile +11 -0
- data/MIT-LICENSE +20 -0
- data/README.md +76 -0
- data/Rakefile +26 -0
- data/VERSION +1 -0
- data/lib/motion-bundler.rb +138 -0
- data/lib/motion-bundler/config.rb +13 -0
- data/lib/motion-bundler/device/boot.rb +1 -0
- data/lib/motion-bundler/device/core_ext.rb +22 -0
- data/lib/motion-bundler/gem_ext.rb +21 -0
- data/lib/motion-bundler/mocks/httparty.rb +125 -0
- data/lib/motion-bundler/mocks/mac_ruby-0.12/stringio.rb +855 -0
- data/lib/motion-bundler/mocks/mac_ruby-0.12/strscan.rb +657 -0
- data/lib/motion-bundler/mocks/zliby-0.0.5/zlib.rb +619 -0
- data/lib/motion-bundler/require.rb +36 -0
- data/lib/motion-bundler/require/mocker.rb +30 -0
- data/lib/motion-bundler/require/mocker/dirs.rb +20 -0
- data/lib/motion-bundler/require/mocker/hooks.rb +39 -0
- data/lib/motion-bundler/require/resolve.rb +52 -0
- data/lib/motion-bundler/require/ripper.rb +62 -0
- data/lib/motion-bundler/require/ripper/builder.rb +47 -0
- data/lib/motion-bundler/require/tracer.rb +39 -0
- data/lib/motion-bundler/require/tracer/hooks.rb +115 -0
- data/lib/motion-bundler/require/tracer/log.rb +68 -0
- data/lib/motion-bundler/simulator/boot.rb +3 -0
- data/lib/motion-bundler/simulator/console.rb +60 -0
- data/lib/motion-bundler/simulator/core_ext.rb +51 -0
- data/lib/motion-bundler/version.rb +7 -0
- data/motion-bundler.gemspec +23 -0
- data/rake +8 -0
- data/sample_app/.gitignore +16 -0
- data/sample_app/Gemfile +9 -0
- data/sample_app/Rakefile +17 -0
- data/sample_app/app/app_delegate.rb +8 -0
- data/sample_app/app/controllers/app_controller.rb +52 -0
- data/sample_app/lib/foo.rb +8 -0
- data/sample_app/lib/foo/bar.rb +9 -0
- data/sample_app/mocks/httparty.rb +5 -0
- data/sample_app/resources/Default-568h@2x.png +0 -0
- data/sample_app/spec/main_spec.rb +9 -0
- data/script/console +8 -0
- data/test/.gemfiles/simulator/test_setup +6 -0
- data/test/.gemfiles/simulator/test_setup.lock +22 -0
- data/test/gems/slot_machine/CHANGELOG.rdoc +5 -0
- data/test/gems/slot_machine/Gemfile +18 -0
- data/test/gems/slot_machine/MIT-LICENSE +20 -0
- data/test/gems/slot_machine/README.md +146 -0
- data/test/gems/slot_machine/Rakefile +9 -0
- data/test/gems/slot_machine/VERSION +1 -0
- data/test/gems/slot_machine/lib/slot.rb +3 -0
- data/test/gems/slot_machine/lib/slot_machine.rb +9 -0
- data/test/gems/slot_machine/lib/slot_machine/slot.rb +181 -0
- data/test/gems/slot_machine/lib/slot_machine/slots.rb +130 -0
- data/test/gems/slot_machine/lib/slot_machine/version.rb +7 -0
- data/test/gems/slot_machine/lib/slots.rb +3 -0
- data/test/gems/slot_machine/lib/time_slot.rb +30 -0
- data/test/gems/slot_machine/lib/time_slots.rb +3 -0
- data/test/gems/slot_machine/script/console +10 -0
- data/test/gems/slot_machine/slot_machine.gemspec +16 -0
- data/test/gems/slot_machine/test/test_helper.rb +7 -0
- data/test/gems/slot_machine/test/unit/test_slot.rb +259 -0
- data/test/gems/slot_machine/test/unit/test_slots.rb +117 -0
- data/test/gems/slot_machine/test/unit/test_time_slot.rb +75 -0
- data/test/gems/slot_machine/test/unit/test_time_slots.rb +54 -0
- data/test/lib/a.rb +2 -0
- data/test/lib/b.rb +5 -0
- data/test/lib/b/a.rb +6 -0
- data/test/lib/b/a/a.rb +6 -0
- data/test/lib/b/b.rb +4 -0
- data/test/lib/c.rb +2 -0
- data/test/lib/d/a.rb +4 -0
- data/test/lib/d/b.rb +7 -0
- data/test/lib/d/b/a.rb +8 -0
- data/test/lib/d/b/a/a.rb +8 -0
- data/test/lib/d/b/b.rb +6 -0
- data/test/lib/d/c.rb +4 -0
- data/test/mocks/net/http.rb +7 -0
- data/test/mocks/psych_foo-0.1.0/psych/handler.rb +7 -0
- data/test/mocks/yaml.rb +5 -0
- data/test/motion/device/test_core_ext.rb +39 -0
- data/test/motion/simulator/test_core_ext.rb +71 -0
- data/test/motion/simulator/test_setup.rb +76 -0
- data/test/test_helper.rb +109 -0
- data/test/test_helper/coverage.rb +7 -0
- data/test/test_helper/motion.rb +20 -0
- data/test/unit/require/mocker/test_dirs.rb +31 -0
- data/test/unit/require/mocker/test_hooks.rb +29 -0
- data/test/unit/require/ripper/test_builder.rb +32 -0
- data/test/unit/require/test_mocker.rb +59 -0
- data/test/unit/require/test_resolve.rb +32 -0
- data/test/unit/require/test_ripper.rb +75 -0
- data/test/unit/require/test_tracer.rb +101 -0
- data/test/unit/require/tracer/test_hooks.rb +52 -0
- data/test/unit/require/tracer/test_log.rb +87 -0
- data/test/unit/simulator/test_console.rb +59 -0
- data/test/unit/simulator/test_core_ext.rb +49 -0
- data/test/unit/test_config.rb +20 -0
- data/test/unit/test_gem_ext.rb +23 -0
- data/test/unit/test_motion-bundler.rb +146 -0
- data/test/unit/test_require.rb +46 -0
- metadata +275 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.rdoc
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Paul Engel
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# MotionBundler [![Build Status](https://secure.travis-ci.org/archan937/motion-bundler.png)](http://travis-ci.org/archan937/motion-bundler)
|
2
|
+
|
3
|
+
Use Ruby gems and mock require statements within RubyMotion applications
|
4
|
+
|
5
|
+
## Introduction
|
6
|
+
|
7
|
+
[RubyMotion](http://www.rubymotion.com) has united two great programming communities: the Ruby and iOS community. We are no longer forced to develop native iOS applications (for iPhone and iPad) using Objective-C and XCode anymore because we can choose using Ruby with any kind of text editor. Ruby gives us a lot of benefits like the beauty and flexibility of the language. Also, the Ruby community is driven by its enormous amount of open source libraries which are packed as so called "Ruby gems". Bundler is the Ruby standard for managing all the gem dependencies used within a Ruby project.
|
8
|
+
|
9
|
+
There are limitations though as you cannot use any random Ruby gem you want to. It either has to be RubyMotion aware (like [BubbleWrap](https://github.com/rubymotion/BubbleWrap)) or RubyMotion compatible (mostly when having as minimal gem dependencies as possible and not doing fancy Ruby stuff like code evaluation). Also, you cannot just require Ruby sources at runtime. You will have to specify them along with their mutual dependencies.
|
10
|
+
|
11
|
+
This can give us a lot of headaches and so I have created a Ruby gem called `MotionBundler`. It will unobtrusively track and specify the required Ruby sources and their mutual dependencies of Ruby gems you want to use in your RubyMotion application.
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
### Set up your Gemfile and Rakefile
|
16
|
+
|
17
|
+
You need to setup your `Gemfile` by separating RubyMotion aware Ruby gems from the ones that are not. Put the RubyMotion **unaware** gems in the `:motion` Bundler group like this:
|
18
|
+
|
19
|
+
source "http://rubygems.org"
|
20
|
+
|
21
|
+
# RubyMotion aware gems
|
22
|
+
gem "motion-bundler"
|
23
|
+
|
24
|
+
# RubyMotion unaware gems
|
25
|
+
group :motion do
|
26
|
+
gem "slot_machine"
|
27
|
+
end
|
28
|
+
|
29
|
+
Add `MotionBundler.setup` at the end of your `Rakefile`:
|
30
|
+
|
31
|
+
# -*- coding: utf-8 -*-
|
32
|
+
$:.unshift "/Library/RubyMotion/lib"
|
33
|
+
require "motion/project"
|
34
|
+
|
35
|
+
# Require and prepare Bundler
|
36
|
+
require "bundler"
|
37
|
+
Bundler.require
|
38
|
+
|
39
|
+
Motion::Project::App.setup do |app|
|
40
|
+
# Use `rake config' to see complete project settings.
|
41
|
+
app.name = "SampleApp"
|
42
|
+
end
|
43
|
+
|
44
|
+
# Track and specify files and their mutual dependencies within the :motion Bundler group
|
45
|
+
MotionBundler.setup
|
46
|
+
|
47
|
+
Run `bundle` and then `rake` to run the application in your iOS-simulator. Voila! You're done ^^
|
48
|
+
|
49
|
+
## Huh? Haven't you written LockOMotion already?
|
50
|
+
|
51
|
+
Yes, I did. But MotionBundler ...
|
52
|
+
|
53
|
+
* is an improved rewrite of [LockOMotion](https://github.com/archan937/lock-o-motion)
|
54
|
+
* has been stripped down
|
55
|
+
* has more code abstraction (and thus has much cleaner and readable code)
|
56
|
+
* has a [test coverage percentage of 100%](https://travis-ci.org/archan937/motion-bundler)
|
57
|
+
|
58
|
+
## More documentation
|
59
|
+
|
60
|
+
Please consult the [GitHub repository Wiki pages](https://github.com/archan937/motion-bundler/wiki/Overview) for further information about MotionBundler.
|
61
|
+
|
62
|
+
## Contact me
|
63
|
+
|
64
|
+
For support, remarks and requests, please mail me at [paul.engel@holder.nl](mailto:paul.engel@holder.nl).
|
65
|
+
|
66
|
+
## License
|
67
|
+
|
68
|
+
Copyright (c) 2013 Paul Engel, released under the MIT license
|
69
|
+
|
70
|
+
[http://holder.nl](http://holder.nl) - [http://codehero.es](http://codehero.es) - [http://gettopup.com](http://gettopup.com) - [http://github.com/archan937](http://github.com/archan937) - [http://twitter.com/archan937](http://twitter.com/archan937) - [paul.engel@holder.nl](mailto:paul.engel@holder.nl)
|
71
|
+
|
72
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
73
|
+
|
74
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
75
|
+
|
76
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require "rake/testtask"
|
4
|
+
require "colorize"
|
5
|
+
|
6
|
+
task :default => "test/unit"
|
7
|
+
|
8
|
+
Rake::TestTask.new("test/unit") do |t|
|
9
|
+
t.test_files = FileList["test/unit/**/test_*.rb"]
|
10
|
+
end
|
11
|
+
task("test/unit").clear_comments
|
12
|
+
task("test/unit").comment = "Run unit tests"
|
13
|
+
|
14
|
+
desc "Run motion tests (Usage: .rake)"
|
15
|
+
task "test/motion" do
|
16
|
+
if ENV["BUNDLE_GEMFILE"] == "foo"
|
17
|
+
FileList["test/motion/**/test_*.rb"].each_with_index do |test_file, index|
|
18
|
+
puts if index > 0 || ARGV.include?("test/unit")
|
19
|
+
puts "#{test_file}:\n".green
|
20
|
+
test_file = File.expand_path test_file
|
21
|
+
system "cd #{File.dirname test_file} && ruby #{File.basename test_file}"
|
22
|
+
end
|
23
|
+
else
|
24
|
+
puts "Please use `.rake` to run motion tests".red
|
25
|
+
end
|
26
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require "bundler"
|
2
|
+
require "motion-bundler/gem_ext"
|
3
|
+
require "motion-bundler/config"
|
4
|
+
require "motion-bundler/require"
|
5
|
+
require "motion-bundler/version"
|
6
|
+
|
7
|
+
module MotionBundler
|
8
|
+
extend self
|
9
|
+
|
10
|
+
MOTION_BUNDLER_FILE = File.expand_path "./.motion-bundler.rb"
|
11
|
+
|
12
|
+
def app_require(file)
|
13
|
+
app_requires << file
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup(&block)
|
17
|
+
Motion::Project::App.setup do |app|
|
18
|
+
touch_motion_bundler
|
19
|
+
|
20
|
+
files, files_dependencies, required = app.files, {}, []
|
21
|
+
ripper_require files, files_dependencies, required
|
22
|
+
tracer_require files, files_dependencies, required, &block
|
23
|
+
|
24
|
+
app.files = files
|
25
|
+
app.files_dependencies files_dependencies
|
26
|
+
|
27
|
+
write_motion_bundler files, files_dependencies, required
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def simulator?
|
32
|
+
!device?
|
33
|
+
end
|
34
|
+
|
35
|
+
def device?
|
36
|
+
argv.include? "device"
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_files
|
40
|
+
[File.expand_path("../motion-bundler/#{simulator? ? "simulator" : "device"}/boot.rb", __FILE__)]
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def argv
|
46
|
+
ARGV
|
47
|
+
end
|
48
|
+
|
49
|
+
def app_requires
|
50
|
+
@app_requires ||= []
|
51
|
+
end
|
52
|
+
|
53
|
+
def touch_motion_bundler
|
54
|
+
File.open(MOTION_BUNDLER_FILE, "w") {}
|
55
|
+
end
|
56
|
+
|
57
|
+
def ripper_require(files, files_dependencies, required)
|
58
|
+
ripper = Require::Ripper.new *Dir["app/**/*.rb"].collect{|x| "./#{x}"}
|
59
|
+
|
60
|
+
files.replace(ripper.files + files).uniq!
|
61
|
+
files_dependencies.merge!(ripper.files_dependencies)
|
62
|
+
|
63
|
+
files_dependencies.each{|k, v| v.uniq!}
|
64
|
+
required.concat(ripper.requires.values.flatten).uniq!; required.sort!
|
65
|
+
end
|
66
|
+
|
67
|
+
def tracer_require(files, files_dependencies, required)
|
68
|
+
Require.trace do
|
69
|
+
require MOTION_BUNDLER_FILE
|
70
|
+
default_files.each do |file|
|
71
|
+
require file
|
72
|
+
end
|
73
|
+
Bundler.require :motion
|
74
|
+
app_requires.delete_if do |file|
|
75
|
+
require file, "APP"
|
76
|
+
true
|
77
|
+
end
|
78
|
+
if block_given?
|
79
|
+
config = Config.new
|
80
|
+
yield config
|
81
|
+
config.requires.each{|file| require file, "APP"}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
files.replace(
|
86
|
+
Require.files + files - ["APP", "BUNDLER", __FILE__]
|
87
|
+
).uniq!
|
88
|
+
files_dependencies.merge!(
|
89
|
+
Require.files_dependencies.tap do |dependencies|
|
90
|
+
(dependencies.delete("BUNDLER") || []).each do |file|
|
91
|
+
dependencies[file] ||= []
|
92
|
+
dependencies[file] = default_files + dependencies[file]
|
93
|
+
end
|
94
|
+
dependencies.delete("APP")
|
95
|
+
dependencies.delete(__FILE__)
|
96
|
+
end
|
97
|
+
)
|
98
|
+
|
99
|
+
files_dependencies.each{|k, v| v.uniq!}
|
100
|
+
required.concat(Require.requires.values.flatten).uniq!; required.sort!
|
101
|
+
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
def write_motion_bundler(files, files_dependencies, required)
|
106
|
+
File.open(MOTION_BUNDLER_FILE, "w") do |file|
|
107
|
+
files_dependencies = files_dependencies.dup.tap do |dependencies|
|
108
|
+
if motion_bundler_dependencies = dependencies.delete(__FILE__)
|
109
|
+
dependencies["MOTION_BUNDLER"] = motion_bundler_dependencies
|
110
|
+
end
|
111
|
+
end
|
112
|
+
file << <<-RUBY_CODE.gsub(" ", "")
|
113
|
+
module MotionBundler
|
114
|
+
FILES = #{pretty_inspect files, 2}
|
115
|
+
FILES_DEPENDENCIES = #{pretty_inspect files_dependencies, 2}
|
116
|
+
REQUIRED = #{pretty_inspect required, 2}
|
117
|
+
end
|
118
|
+
RUBY_CODE
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def pretty_inspect(object, indent = 0)
|
123
|
+
if object.is_a?(Array)
|
124
|
+
entries = object.collect{|x| " #{pretty_inspect x, indent + 2}"}
|
125
|
+
return "[]" if entries.empty?
|
126
|
+
entries.each_with_index{|x, i| entries[i] = "#{x}," if i < entries.size - 1}
|
127
|
+
["[", entries, "]"].flatten.join "\n" + (" " * indent)
|
128
|
+
elsif object.is_a?(Hash)
|
129
|
+
entries = object.collect{|k, v| " #{k.inspect} => #{pretty_inspect v, indent + 2}"}
|
130
|
+
return "{}" if entries.empty?
|
131
|
+
entries.each_with_index{|x, i| entries[i] = "#{x}," if i < entries.size - 1}
|
132
|
+
["{", entries, "}"].flatten.join "\n" + (" " * indent)
|
133
|
+
else
|
134
|
+
object.inspect
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "core_ext"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Kernel
|
2
|
+
def require(name)
|
3
|
+
end
|
4
|
+
def require_relative(string)
|
5
|
+
end
|
6
|
+
def load(filename, wrap=false)
|
7
|
+
end
|
8
|
+
def autoload(mod, filename)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
class Object
|
12
|
+
def require(name)
|
13
|
+
end
|
14
|
+
def require_relative(string)
|
15
|
+
end
|
16
|
+
def load(filename, wrap=false)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
class Module
|
20
|
+
def autoload(mod, filename)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Motion
|
2
|
+
module Project
|
3
|
+
class Config
|
4
|
+
|
5
|
+
def files_dependencies(deps_hash)
|
6
|
+
res_path = lambda do |x|
|
7
|
+
path = /^\.?\//.match(x) ? x : File.join(".", x)
|
8
|
+
unless @files.flatten.include?(path)
|
9
|
+
App.fail "Can't resolve dependency `#{x}'"
|
10
|
+
end
|
11
|
+
path
|
12
|
+
end
|
13
|
+
deps_hash.each do |path, deps|
|
14
|
+
deps = [deps] unless deps.is_a?(Array)
|
15
|
+
@dependencies[res_path.call(path)] = deps.map(&res_path)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module HTTParty
|
2
|
+
extend self
|
3
|
+
|
4
|
+
def included(base)
|
5
|
+
base.extend self
|
6
|
+
end
|
7
|
+
|
8
|
+
def format(f)
|
9
|
+
@format = f
|
10
|
+
end
|
11
|
+
|
12
|
+
def base_uri(u)
|
13
|
+
@base_uri = u.sub(/\/$/, "")
|
14
|
+
end
|
15
|
+
|
16
|
+
def basic_auth(user, password)
|
17
|
+
@basic_auth = [user, password]
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(path, options = {}, &block)
|
21
|
+
send_request path, :get
|
22
|
+
end
|
23
|
+
|
24
|
+
def post(path, options = {}, &block)
|
25
|
+
send_request path, :post
|
26
|
+
end
|
27
|
+
|
28
|
+
def put(path, options = {}, &block)
|
29
|
+
send_request path, :put
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete(path, options = {}, &block)
|
33
|
+
send_request path, :delete
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def send_request(path, method, options = {})
|
39
|
+
path = "#{@base_uri}/#{path}" if @base_uri && !path.match(/^\w+:\/\//)
|
40
|
+
path = path.stringByAddingPercentEscapesUsingEncoding NSUTF8StringEncoding
|
41
|
+
method = method.to_s.upcase
|
42
|
+
|
43
|
+
if options[:body]
|
44
|
+
payload = payload_to_query_string(options[:body]).dataUsingEncoding(NSUTF8StringEncoding) if POST / PUT && payload
|
45
|
+
end
|
46
|
+
|
47
|
+
if payload && method == "GET"
|
48
|
+
path << "#{path.include?("?") ? "&" : "?"}#{payload}"
|
49
|
+
end
|
50
|
+
|
51
|
+
url = NSURL.URLWithString path.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
|
52
|
+
request = NSMutableURLRequest.requestWithURL url
|
53
|
+
|
54
|
+
if @basic_auth
|
55
|
+
auth_header = "Basic " + [@basic_auth.join(":")].pack("m0").dataUsingEncoding(NSUTF8StringEncoding)
|
56
|
+
request.addValue auth_header, forHTTPHeaderField: "Authorization"
|
57
|
+
request.HTTPMethod = method
|
58
|
+
end
|
59
|
+
|
60
|
+
if payload
|
61
|
+
request.HTTPBody = payload
|
62
|
+
end
|
63
|
+
|
64
|
+
response = Pointer.new :object
|
65
|
+
error = Pointer.new :object
|
66
|
+
data = NSURLConnection.sendSynchronousRequest request, returningResponse: response, error: error
|
67
|
+
|
68
|
+
HTTParty::Response.new response, data, {:format => @format, :error => error}
|
69
|
+
end
|
70
|
+
|
71
|
+
def payload_to_query_string(payload_hash)
|
72
|
+
payload_hash_to_array(payload_hash).collect{|key, value| "#{escape key}=#{escape value}"}.join "&"
|
73
|
+
end
|
74
|
+
|
75
|
+
def payload_hash_to_array(hash, prefix = nil)
|
76
|
+
array = []
|
77
|
+
hash.each do |key, value|
|
78
|
+
if value.is_a?(Hash)
|
79
|
+
array += payload_hash_to_array(value, prefix ? "#{prefix}[#{key.to_s}]" : key.to_s)
|
80
|
+
elsif value.is_a?(Array)
|
81
|
+
value.each do |val|
|
82
|
+
array << [prefix ? "#{prefix}[#{key.to_s}][]" : "#{key.to_s}[]", val]
|
83
|
+
end
|
84
|
+
else
|
85
|
+
array << [prefix ? "#{prefix}[#{key.to_s}]" : key.to_s, value]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
array
|
89
|
+
end
|
90
|
+
|
91
|
+
def escape(string)
|
92
|
+
CFURLCreateStringByAddingPercentEscapes(nil, string, "[]", ";=&,", KCFStringEncodingUTF8) if string
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
module HTTParty
|
98
|
+
class Response
|
99
|
+
|
100
|
+
def initialize(response, data, options = {})
|
101
|
+
@cached_response = NSCachedURLResponse.alloc.initWithResponse response.value, data: data
|
102
|
+
@options = options
|
103
|
+
end
|
104
|
+
|
105
|
+
def parsed_response
|
106
|
+
@parsed_response ||= begin
|
107
|
+
case @options[:format]
|
108
|
+
when :json
|
109
|
+
NSJSONSerialization.JSONObjectWithData @cached_response.data, options: NSJSONReadingMutableContainers, error: nil
|
110
|
+
else
|
111
|
+
NSString.alloc.initWithData @cached_response.data, encoding: NSUTF8StringEncoding
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def code
|
117
|
+
@cached_response.response.statusCode
|
118
|
+
end
|
119
|
+
|
120
|
+
def ok?
|
121
|
+
code.to_s.match /^20\d$/
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|