Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
  • 18 commits
  • 20 files changed
  • 0 commit comments
  • 5 contributors
Commits on Jul 16, 2012
@siuying siuying add change history to all versions in CHANGELOG 027b7f8
@siuying siuying Add a demo project to show how complex gesture helpers works a67a20a
@siuying siuying add screenshot to the demo 6dd6d56
@dmarkow dmarkow Properly strip paths with trailing /lib 61e83bc
Commits on Jul 17, 2012
@smgt smgt Add App to notification center. 4a19e38
@mattetti mattetti Merge pull request #105 from simon/patch-1
Add App to notification center.
3d38816
@dmarkow dmarkow Restore nested hash support for POST/PUT requests 32091ca
@jamesotron jamesotron Merge dmarkow:lib_path_fix into master. 4f71bd7
@jamesotron jamesotron Mocha has a problem with not loading minitest, locking the version as…
… suggested on freerange/mocha#88.
8cdf792
@dmarkow dmarkow Extract payload hash processing to new method
Since this is now used for both GET/POST requests, it shouldn't be in a
GET-specific method.
bb96e7a
@dmarkow dmarkow Remove unnecessary generate_get_params method
Now that all the logic is pulled out to process_payload_hash, the
GET-specific part can just be done in the convert_payload_to_url method.
746a44e
Commits on Jul 18, 2012
@mattetti mattetti Merge pull request #107 from dmarkow/nested_params
Bring back nested params support for POST requests
d0f6205
@dmarkow dmarkow Add a format option for setting the Content-Type 9b4b07c
@dmarkow dmarkow Set the Content-Type based on the format parameter or payload bb48727
@mattetti mattetti Merge pull request #109 from dmarkow/payload_format
Format option for setting Content-Type
a791b2c
Commits on Jul 19, 2012
@mattetti mattetti fixed a bug with `:format` where the content type doesn't get set for…
… GET, HEAD or requests without a payload.
dba9383
@mattetti mattetti bumped the version e040c9f
@mattetti mattetti forgot the Gemfile.lock file e76c0f3
View
37 CHANGELOG.md
@@ -1,15 +1,32 @@
+## 1.1.2
+
+[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.1.0...v1.1.1)
+
+* Fixed a problem with the load path.
+* Added `format:` to the HTTP wrapper with [5 supported formats supported](https://github.com/rubymotion/BubbleWrap/pull/109) that sets the content type accordingly.
+* Default HTTP Content-Type for `POST` like requests is back to being
+ form url encoded.
+
## 1.1.1
+[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.1.0...v1.1.1)
+
+### Enhancements
+
+* Added support for symbols as selectors to the KVO module.
+* Improved the RSSParser by providing a delegate to handle errors.
+
+### Bug Fixes
+
* Fixed a bug with the way JSON payloads were handled in the HTTP
wrapper.
-* Improved the RSSParser by providing a delegate to handle errors.
-* Added support for symbols as selectors to the KVO module.
* Fixed a bug with the way the headers and content types were handled in
the HTTP wrapper.
## 1.1.0
-[Commit history](https://github.com/rubymotion/BubbleWrap/compare/1.0...1.1])
+[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.0.0...v1.1.0)
+
* Added `BubbleWrap::Reactor`, a simplified implementation of the Event Machine API on top of GCD.
* Added upload support to the HTTP wrapper.
* Added `BubbleWrap.create_uuid` to generate a uuid string.
@@ -24,6 +41,8 @@
## 1.0.0
+[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v0.4.0...v1.0.0)
+
* Improved the integration with RubyMotion build system.
* Improved test suite.
* Added better documentation, including on how to work on the internals.
@@ -33,25 +52,35 @@
## 0.4.0
+[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v0.3.1...v0.4.0)
+
* Refactored the code and test suite to be more modular and to handle
dependencies. One can now require only a subset of BW such as `require 'bubble-wrap/core'` or 'bubble-wrap/http'
## 0.3.1
+[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v0.3.0...v0.3.1)
+
* Added App.run_after(delay){ }
* HTTP responses return true to ok? when the status code is 20x.
## 0.3.0
-* Major refactoring preparing for 1.0: [List of commits](https://github.com/mattetti/BubbleWrap/compare/v0.2.1...v0.3.0)
+[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v0.2.1...v0.3.0)
+
+* Major refactoring preparing for 1.0
## 0.2.1
+[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v0.2.0...v0.2.1)
+
* Minor fix in the way the dependencies are set (had to monkey patch
RubyMotion)
## 0.2.0
+[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v0.1.2...v0.2.0)
+
* Added network activity notification to the HTTP wrapper.
* fixed a bug in the `NSNotificationCenter` wrapper.
View
5 Gemfile.lock
@@ -1,14 +1,14 @@
PATH
remote: .
specs:
- bubble-wrap (1.1.1)
+ bubble-wrap (1.1.2)
GEM
remote: https://rubygems.org/
specs:
bacon (1.1.0)
metaclass (0.0.1)
- mocha (0.12.0)
+ mocha (0.11.4)
metaclass (~> 0.0.1)
mocha-on-bacon (0.2.0)
mocha (>= 0.9.8)
@@ -20,5 +20,6 @@ PLATFORMS
DEPENDENCIES
bacon
bubble-wrap!
+ mocha (= 0.11.4)
mocha-on-bacon
rake
View
10 README.md
@@ -240,22 +240,22 @@ Helper methods to give NSNotificationCenter a Ruby-like interface:
```ruby
def viewWillAppear(animated)
- @foreground_observer = notification_center.observe UIApplicationWillEnterForegroundNotification do |notification|
+ @foreground_observer = App.notification_center.observe UIApplicationWillEnterForegroundNotification do |notification|
loadAndRefresh
end
- @reload_observer = notification_center.observe ReloadNotification do |notification|
+ @reload_observer = App.notification_center.observe ReloadNotification do |notification|
loadAndRefresh
end
end
def viewWillDisappear(animated)
- notification_center.unobserve @foreground_observer
- notification_center.unobserve @reload_observer
+ App.notification_center.unobserve @foreground_observer
+ App.notification_center.unobserve @reload_observer
end
def reload
- notification_center.post ReloadNotification
+ App.notification_center.post ReloadNotification
end
```
View
3 bubble-wrap.gemspec
@@ -16,7 +16,8 @@ Gem::Specification.new do |gem|
gem.extra_rdoc_files = gem.files.grep(%r{motion})
- gem.add_development_dependency 'bacon'
+ gem.add_development_dependency 'mocha', '0.11.4'
gem.add_development_dependency 'mocha-on-bacon'
+ gem.add_development_dependency 'bacon'
gem.add_development_dependency 'rake'
end
View
18 lib/bubble-wrap/requirement/path_manipulation.rb
@@ -22,13 +22,17 @@ def convert_to_absolute_path(path)
end
def strip_up_to_last_lib(path)
- path = path.split('lib')
- path = if path.size > 1
- path[0..-2].join('lib')
- else
- path[0]
- end
- path = path[0..-2] if path[-1] == '/'
+ if path =~ /\/lib$/
+ path = path.gsub(/\/lib$/, "")
+ else
+ path = path.split('lib')
+ path = if path.size > 1
+ path[0..-2].join('lib')
+ else
+ path[0]
+ end
+ path = path[0..-2] if path[-1] == '/'
+ end
path
end
View
2 lib/bubble-wrap/version.rb
@@ -1,3 +1,3 @@
module BubbleWrap
- VERSION = '1.1.1' unless defined?(BubbleWrap::VERSION)
+ VERSION = '1.1.2' unless defined?(BubbleWrap::VERSION)
end
View
55 motion/http.rb
@@ -119,6 +119,7 @@ def initialize(url_string, http_method = :get, options={})
@credentials = {:username => '', :password => ''}.merge(@credentials)
@timeout = options.delete(:timeout) || 30.0
@headers = escape_line_feeds(options.delete :headers)
+ @format = options.delete(:format)
@cache_policy = options.delete(:cache_policy) || NSURLRequestUseProtocolCachePolicy
@options = options
@response = HTTP::Response.new
@@ -126,6 +127,7 @@ def initialize(url_string, http_method = :get, options={})
@url = create_url(url_string)
@body = create_request_body
@request = create_request
+ set_content_type
@connection = create_connection(request, self)
@connection.start
@@ -221,16 +223,6 @@ def create_request_body
return nil if (@method == "GET" || @method == "HEAD")
return nil unless (@payload || @files)
- # if no headers provided, set content-type automatically
- if @headers.nil?
- @headers = {"Content-Type" => "multipart/form-data; boundary=#{@boundary}"}
- # else set content type unless it is specified
- # if content-type is specified, you should probably also specify
- # the :boundary key
- else
- @headers['Content-Type'] = "multipart/form-data; boundary=#{@boundary}" unless @headers.keys.find {|k| k.downcase == 'content-type'}
- end
-
body = NSMutableData.data
append_payload(body) if @payload
@@ -241,6 +233,27 @@ def create_request_body
body
end
+ def set_content_type
+ # if no headers provided, set content-type automatically
+ if @headers.nil? || !@headers.keys.find {|k| k.downcase == 'content-type'}
+ @headers ||= {}
+ @headers["Content-Type"] = case @format
+ when :json
+ "application/json"
+ when :xml
+ "application/xml"
+ when :text
+ "text/plain"
+ else
+ if @format == :form_data || @set_body_to_close_boundary
+ "multipart/form-data; boundary=#{@boundary}"
+ else
+ "application/x-www-form-urlencoded"
+ end
+ end
+ end
+ end
+
def append_payload(body)
if @payload.is_a?(NSData)
body.appendData(@payload)
@@ -255,7 +268,8 @@ def append_form_params(body)
if @payload.is_a?(String)
body.appendData(@payload.dataUsingEncoding NSUTF8StringEncoding)
else
- @payload.each do |key, value|
+ list = process_payload_hash(@payload)
+ list.each do |key, value|
form_data = NSMutableData.new
s = "\r\n--#{@boundary}\r\n"
s += "Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n"
@@ -295,28 +309,29 @@ def create_url(url_string)
end
def convert_payload_to_url
- params_array = generate_get_params(@payload)
+ params_array = process_payload_hash(@payload)
+ params_array.map! { |key, value| "#{key}=#{value}" }
@payload = params_array.join("&")
end
- def generate_get_params(payload, prefix=nil)
+ def process_payload_hash(payload, prefix=nil)
list = []
payload.each do |k,v|
if v.is_a?(Hash)
new_prefix = prefix ? "#{prefix}[#{k.to_s}]" : k.to_s
- param = generate_get_params(v, new_prefix)
- list << param
+ param = process_payload_hash(v, new_prefix)
+ list += param
elsif v.is_a?(Array)
v.each do |val|
- param = prefix ? "#{prefix}[#{k}][]=#{val}" : "#{k}[]=#{val}"
- list << param
+ param = prefix ? "#{prefix}[#{k.to_s}][]" : "#{k.to_s}[]"
+ list << [param, val]
end
else
- param = prefix ? "#{prefix}[#{k}]=#{v}" : "#{k}=#{v}"
- list << param
+ param = prefix ? "#{prefix}[#{k.to_s}]" : k.to_s
+ list << [param, v]
end
end
- return list.flatten
+ list
end
def log(message)
View
5 samples/gesture/.gitignore
@@ -0,0 +1,5 @@
+.repl_history
+build
+resources/*.nib
+resources/*.momd
+resources/*.storyboardc
View
4 samples/gesture/Gemfile
@@ -0,0 +1,4 @@
+source :rubygems
+
+gem 'bubble-wrap', '~> 1.1.0'
+gem 'motion-dryer'
View
12 samples/gesture/Gemfile.lock
@@ -0,0 +1,12 @@
+GEM
+ remote: http://rubygems.org/
+ specs:
+ bubble-wrap (1.1.1)
+ motion-dryer (0.0.1)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ bubble-wrap (~> 1.1.0)
+ motion-dryer
View
5 samples/gesture/README.md
@@ -0,0 +1,5 @@
+## Gesture Demo
+
+A bubble-wrap demo to show how to use gesture API.
+
+![](http://f.cl.ly/items/0e1J3W0Y0p3n3S2a0k2K/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%202012-07-16%20%E4%B8%8B%E5%8D%8802.15.30.png)
View
9 samples/gesture/Rakefile
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+$:.unshift("/Library/RubyMotion/lib")
+require 'motion/project'
+require 'bundler'
+Bundler.require :default
+
+Motion::Project::App.setup do |app|
+ app.name = 'gesture'
+end
View
16 samples/gesture/app/app_delegate.rb
@@ -0,0 +1,16 @@
+class AppDelegate
+ attr_reader :window
+
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
+ setup_window
+ true
+ end
+
+ # setup UI
+ def setup_window
+ @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
+ @window.rootViewController = DrawingViewController.alloc.init
+ @window.rootViewController.wantsFullScreenLayout = true
+ @window.makeKeyAndVisible
+ end
+end
View
12 samples/gesture/app/controllers/drawing_view_controller.rb
@@ -0,0 +1,12 @@
+class DrawingViewController < UIViewController
+ attr_reader :drawing_view
+
+ def loadView
+ screen = UIScreen.mainScreen.bounds
+ self.view = UIView.alloc.initWithFrame screen
+ self.view.backgroundColor = UIColor.whiteColor
+
+ @drawing_view = RectView.alloc.initWithFrame [[screen.size.width/2-50,screen.size.height/2-50], [100,100]]
+ self.view.addSubview @drawing_view
+ end
+end
View
2 samples/gesture/app/helpers/drawing_helper.rb
@@ -0,0 +1,2 @@
+module DrawingHelper
+end
View
92 samples/gesture/app/views/drawing/gesture_view.rb
@@ -0,0 +1,92 @@
+class GestureView < UIView
+ attr_accessor :rotation, :scale, :translation
+
+ def initWithCoder(coder)
+ super
+ setup
+ self
+ end
+
+ def initWithFrame(coder)
+ super
+ setup
+ self
+ end
+
+ ## UIGestureRecognizerDelegate
+
+ # Note: this method allow rotate and pinch gesture happen at the same time
+ def gestureRecognizer(recognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer:other_recognizer)
+ case recognizer
+ when @rotated_recognizer
+ if other_recognizer == @pinch_recognizer
+ return true
+ end
+ when @pinch_recognizer
+ if other_recognizer == @rotated_recognizer
+ return true
+ end
+ end
+ return false
+ end
+
+ private
+
+ def setup
+ self.layer.shouldRasterize = true
+ self.rotation = 0
+ self.scale = 1
+ setup_gesture
+ end
+
+ def setup_gesture
+ @panned_recognizer = self.whenPanned do |recognizer|
+ case(recognizer.state)
+ when UIGestureRecognizerStateBegan
+ @last_position = self.position
+ when UIGestureRecognizerStateChanged
+ self.translation = recognizer.translationInView(self.superview)
+ self.position = [@last_position.x + self.translation.x, @last_position.y + self.translation.y]
+ when UIGestureRecognizerStateEnded
+ @last_position = nil
+ end
+ end
+ @panned_recognizer.maximumNumberOfTouches = 1
+ @panned_recognizer.minimumNumberOfTouches = 1
+ @panned_recognizer.delegate = self
+
+ @rotated_recognizer = self.whenRotated do |recognizer|
+ case(recognizer.state)
+ when UIGestureRecognizerStateBegan
+ @last_rotation = self.rotation
+ when UIGestureRecognizerStateChanged
+ self.rotation = @last_rotation + recognizer.rotation
+ reset_transformation
+ when UIGestureRecognizerStateEnded
+ @last_rotation = nil
+ end
+ end
+ @rotated_recognizer.delegate = self
+
+ @pinch_recognizer = self.whenPinched do |recognizer|
+ case(recognizer.state)
+ when UIGestureRecognizerStateBegan
+ @last_scale = self.scale
+ when UIGestureRecognizerStateChanged
+ self.scale = @last_scale * recognizer.scale
+ reset_transformation
+ when UIGestureRecognizerStateEnded
+ @last_scale = nil
+ end
+ end
+ @pinch_recognizer.delegate = self
+ end
+
+ def reset_transformation
+ transform = CATransform3DIdentity
+ transform = CATransform3DRotate(transform, -1 * self.rotation, 0.0, 0.0, -1.0)
+ transform = CATransform3DScale(transform, self.scale, self.scale, 1.0)
+ self.layer.transform = transform
+ end
+
+end
View
13 samples/gesture/app/views/drawing/rect_view.rb
@@ -0,0 +1,13 @@
+class RectView < GestureView
+ def drawRect(rect)
+ super(rect)
+
+ context = UIGraphicsGetCurrentContext()
+ CGContextSetAllowsAntialiasing(context, true);
+ CGContextSetShouldAntialias(context, true);
+ CGContextSetFillColorWithColor(context, UIColor.redColor.CGColor)
+ CGContextSetLineWidth(context, 10.0)
+ CGContextAddRect(context, [[0,0], [self.frame.size.width,self.frame.size.height]])
+ CGContextFillPath(context)
+ end
+end
View
9 samples/gesture/spec/main_spec.rb
@@ -0,0 +1,9 @@
+describe "Application 'gesture'" do
+ before do
+ @app = UIApplication.sharedApplication
+ end
+
+ it "has one window" do
+ @app.windows.size.should == 1
+ end
+end
View
7 spec/lib/bubble-wrap/requirement/path_manipulation_spec.rb
@@ -1,7 +1,7 @@
require File.expand_path('../../../../../lib/bubble-wrap/requirement/path_manipulation', __FILE__)
describe BubbleWrap::Requirement::PathManipulation do
-
+
before do
@subject = Object.new
@subject.extend BubbleWrap::Requirement::PathManipulation
@@ -35,6 +35,11 @@
should == '/fake/lib/dir'
end
+ it "strips off only a trailing lib" do
+ @subject.strip_up_to_last_lib('/fake/lib/dir/lib').
+ should == '/fake/lib/dir'
+ end
+
it "doesn't modify the path otherwise" do
@subject.strip_up_to_last_lib('/fake/path').
should == '/fake/path'
View
58 spec/motion/http_spec.rb
@@ -108,6 +108,7 @@ def test_http_method(method)
credentials: @credentials
}
@action = lambda{|fa, ke|}
+ @format = "application/x-www-form-urlencoded"
@cache_policy = 24234
@leftover_option = 'trololo'
@headers = { 'User-Agent' => "Mozilla/5.0 (X11; Linux x86_64; rv:12.0) \n Gecko/20100101 Firefox/12.0" }
@@ -122,7 +123,8 @@ def test_http_method(method)
credentials: @credentials,
headers: @headers,
cache_policy: @cache_policy,
- leftover_option: @leftover_option
+ leftover_option: @leftover_option,
+ format: @format
}
@query = BubbleWrap::HTTP::Query.new( @localhost_url , :get, @options )
end
@@ -158,6 +160,11 @@ def test_http_method(method)
@options.should.not.has_key? :files
end
+ it "sets the format from options" do
+ @query.instance_variable_get(:@format).should.equal @format
+ @options.should.not.has_key? :format
+ end
+
it "should set self as the delegator if action was not passed in" do
new_query = BubbleWrap::HTTP::Query.new( 'http://localhost', :get, {})
new_query.instance_variable_get(:@delegator).should.equal new_query
@@ -241,7 +248,7 @@ def sample_data
lambda { query = create_query(data, nil) }.should.not.raise NoMethodError
end
- it "sets the payload as a string if JSON" do
+ it "sets the payload as a string if JSON" do
json = BW::JSON.generate({foo:42, bar:'BubbleWrap'})
puts "\n"
[:put, :post, :delete, :patch].each do |method|
@@ -252,6 +259,14 @@ def sample_data
end
end
+ it "sets the payload for a nested hash to multiple form-data parts" do
+ payload = { computer: { name: 'apple', model: 'macbook'} }
+ query = BubbleWrap::HTTP::Query.new( 'nil', :post, { payload: payload } )
+ uuid = query.instance_variable_get(:@boundary)
+ real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
+ real_payload.should.equal "\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"computer[name]\"\r\n\r\napple\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"computer[model]\"\r\n\r\nmacbook\r\n--#{uuid}--\r\n"
+ end
+
end
it "should set default timeout to 30s or the one from hash" do
@@ -351,6 +366,21 @@ def sample_data
@post_query.request.allHTTPHeaderFields.should.include?('Content-Type')
end
+ it "should use the format parameter to decide the Content-Type" do
+ json_query = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers, format: :json, payload: "{\"key\":\"abc1234\"}"})
+ json_query.request.allHTTPHeaderFields['Content-Type'].should.equal "application/json"
+ end
+
+ it "should default to multipart/form-data for payloads with a hash" do
+ uuid = @post_query.instance_variable_get(:@boundary)
+ @post_query.request.allHTTPHeaderFields['Content-Type'].should.equal "multipart/form-data; boundary=#{uuid}"
+ end
+
+ it "should default to application/x-www-form-urlencoded for non-hash payloads" do
+ string_query = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers, payload: "{\"key\":\"abc1234\"}"})
+ string_query.request.allHTTPHeaderFields['Content-Type'].should.equal "application/x-www-form-urlencoded"
+ end
+
it "should not add Content-Type if you provide one yourself" do
# also ensures check is case insenstive
@headers = { fake: 'headers', 'CONTENT-TYPE' => 'x-banana' }
@@ -365,21 +395,21 @@ def sample_data
end
- describe "Generating GET params" do
+ describe "Generating payloads" do
- it "should create params with nested hashes with prefix[key]=value" do
+ it "should create payload key/value pairs from nested hashes with prefix[key]=value" do
expected_params = [
- 'user[name]=marin',
- 'user[surname]=usalj',
- 'twitter=@mneorr',
- 'website=mneorr.com',
- 'values[]=apple',
- 'values[]=orange',
- 'values[]=peach',
- "credentials[username]=mneorr",
- "credentials[password]=123456xx!@crazy"
+ ['user[name]', 'marin'],
+ ['user[surname]', 'usalj'],
+ ['twitter', '@mneorr'],
+ ['website', 'mneorr.com'],
+ ['values[]', 'apple'],
+ ['values[]', 'orange'],
+ ['values[]', 'peach'],
+ ['credentials[username]', 'mneorr'],
+ ['credentials[password]', '123456xx!@crazy']
]
- @query.send(:generate_get_params, @payload).should.equal expected_params
+ @query.send(:process_payload_hash, @payload).should.equal expected_params
end
end

No commit comments for this range

Something went wrong with that request. Please try again.