lotus-controller 0.4.0 → 0.4.1

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: 69d59a1b6b0f96e6af7bf468a3003a45992b17a3
4
- data.tar.gz: 93d926cb9fdf962ef3e55d6c5c1efb6de4b546ad
3
+ metadata.gz: 40bc827a76215d889abc5fd33c3b102cb626732e
4
+ data.tar.gz: 3ea7a9a16a40c1e00e2861684076f1a7c543efa8
5
5
  SHA512:
6
- metadata.gz: 129a9981a8f46af6d2cd149b9c811a81011cbc3e68b92af5e428e9d9cdc5afc1bb6070b605900acf231a4612d0eaf2c23088c7c17097c1c83aec9c030d5daa27
7
- data.tar.gz: 35da235765f394db0fbcbbe3770732ee3e308825981f9634c0f6e6a626e72acbd3188c00939dfcce097a689e706f1de8ea90814cc435bc30be4d74ac7511f765
6
+ metadata.gz: 2ff6ac5d43e155662c2318ba55184260d4ffdebbb6d0b6eec607d3563439bd809bf8dee089fdb342779eaa23c10d1d7bb5074ae11ead2c5c832bd64ee9506272
7
+ data.tar.gz: 8e6e4c60d239bd321aa0a1aec3aad3120fbef86dc86f33e8c50603f18013650b63ff184572379068fb2f734b7faf593586fcf0c97b9d3f5feb6d6e0167151df2
data/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # Lotus::Controller
2
2
  Complete, fast and testable actions for Rack
3
3
 
4
+ ## v0.4.1 - 2015-05-15
5
+ ### Fixed
6
+ - [Luca Guidi] Ensure proper automatic `Content-Type` working well with Internet Explorer.
7
+ - [Luca Guidi] Ensure `Lotus::Action#redirect_to` to return `::String` for Rack servers compatibility.
8
+
9
+ ### Changed
10
+ - [Alfonso Uceda Pompa] Prevent `Content-Type` and `Content-Lenght` to be sent when status code requires no body (eg. `204`).
11
+ This is for compatibility with `Rack::Lint`, not with RFC 2016.
12
+ - [Luca Guidi] Ensure `Lotus::Action::Params#to_h` to return `::Hash`
13
+
4
14
  ## v0.4.0 - 2015-03-23
5
15
  ### Added
6
16
  - [Erol Fornoles] `Action.use` now accepts a block
data/README.md CHANGED
@@ -75,7 +75,7 @@ __An action is an object__. That's important because __you have the full control
75
75
  In other words, you have the freedom to instantiate, inject dependencies and test it, both at the unit and integration level.
76
76
 
77
77
  In the example below, the default repository is `Article`. During a unit test we can inject a stubbed version, and invoke `#call` with the params.
78
- __We're avoiding HTTP calls__, we're eventually avoiding to hit the database (it depends on the stubbed repository), __we're just dealing with message passing__.
78
+ __We're avoiding HTTP calls__, we're also going to avoid hitting the database (it depends on the stubbed repository), __we're just dealing with message passing__.
79
79
  Imagine how **fast** the unit test could be.
80
80
 
81
81
  ```ruby
@@ -99,7 +99,7 @@ action.call({ id: 23 })
99
99
 
100
100
  The request params are passed as an argument to the `#call` method.
101
101
  If routed with *Lotus::Router*, it extracts the relevant bits from the Rack `env` (eg the requested `:id`).
102
- Otherwise everything passed as is: the full Rack `env` in production, and the given `Hash` for unit tests.
102
+ Otherwise everything is passed as is: the full Rack `env` in production, and the given `Hash` for unit tests.
103
103
 
104
104
  With Lotus::Router:
105
105
 
@@ -158,6 +158,12 @@ class Signup
158
158
  param :first_name
159
159
  param :last_name
160
160
  param :email
161
+
162
+ param :address do
163
+ param :line_one
164
+ param :state
165
+ param :country
166
+ end
161
167
  end
162
168
 
163
169
  def call(params)
@@ -168,6 +174,10 @@ class Signup
168
174
  # Whitelist :first_name, but not :admin
169
175
  puts params[:first_name] # => "Luca"
170
176
  puts params[:admin] # => nil
177
+
178
+ # Whitelist nested params [:address][:line_one], not [:address][:line_two]
179
+ puts params[:address][:line_one] # => '69 Tender St'
180
+ puts params[:address][:line_two] # => nil
171
181
  end
172
182
  end
173
183
  ```
@@ -232,7 +242,7 @@ action = Show.new
232
242
  action.call({}) # => [200, {}, [""]]
233
243
  ```
234
244
 
235
- It has private accessors to explicitly set status, headers and body:
245
+ It has private accessors to explicitly set status, headers, and body:
236
246
 
237
247
  ```ruby
238
248
  class Show
@@ -251,17 +261,17 @@ action.call({}) # => [201, { "X-Custom" => "OK" }, ["Hi!"]]
251
261
 
252
262
  ### Exposures
253
263
 
254
- We know that actions are objects and Lotus::Action respects one of the pillars of OOP: __encapsulation__.
264
+ We know that actions are objects and `Lotus::Action` respects one of the pillars of OOP: __encapsulation__.
255
265
  Other frameworks extract instance variables (`@ivar`) and make them available to the view context.
256
266
 
257
- Lotus::Action's solution is the simple and powerful DSL: `expose`.
267
+ `Lotus::Action`'s solution is the simple and powerful DSL: `expose`.
258
268
  It's a thin layer on top of `attr_reader`.
259
269
 
260
270
  Using `expose` creates a getter for the given attribute, and adds it to the _exposures_.
261
271
  Exposures (`#exposures`) are a set of attributes exposed to the view.
262
272
  That is to say the variables necessary for rendering a view.
263
273
 
264
- By default, all Lotus::Actions expose `#params` and `#errors`.
274
+ By default, all `Lotus::Action` objects expose `#params` and `#errors`.
265
275
 
266
276
  ```ruby
267
277
  class Show
@@ -526,10 +536,34 @@ class RemoveCookies
526
536
  end
527
537
  end
528
538
 
529
- action = SetCookies.new
539
+ action = RemoveCookies.new
530
540
  action.call({}) # => [200, {'Set-Cookie' => "foo=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"}, '...']
531
541
  ```
532
542
 
543
+ Default values can be set in configuration, but overriden case by case.
544
+
545
+ ```ruby
546
+ require 'lotus/controller'
547
+ require 'lotus/action/cookies'
548
+
549
+ Lotus::Controller.configure do
550
+ cookies max_age: 300 # 5 minutes
551
+ end
552
+
553
+ class SetCookies
554
+ include Lotus::Action
555
+ include Lotus::Action::Cookies
556
+
557
+ def call(params)
558
+ # ...
559
+ cookies[:foo] = { value: 'bar', max_age: 100 }
560
+ end
561
+ end
562
+
563
+ action = SetCookies.new
564
+ action.call({}) # => [200, {'Set-Cookie' => "foo=bar; max-age=100;"}, '...']
565
+ ```
566
+
533
567
  ### Sessions
534
568
 
535
569
  It has builtin support for Rack sessions:
@@ -722,7 +756,7 @@ action.call({ article: { title: 'Hello' }}) # => [301, {'Location' => '/articles
722
756
 
723
757
  ### Mime Types
724
758
 
725
- Lotus::Action automatically sets the `Content-Type` header, according to the request.
759
+ `Lotus::Action` automatically sets the `Content-Type` header, according to the request.
726
760
 
727
761
  ```ruby
728
762
  class Show
@@ -872,7 +906,7 @@ Articles::Index.new.call({})
872
906
  ### Lotus::Router integration
873
907
 
874
908
  While Lotus::Router works great with this framework, Lotus::Controller doesn't depend on it.
875
- You, as developer, are free to choose your own routing system.
909
+ You, the developer, are free to choose your own routing system.
876
910
 
877
911
  But, if you use them together, the **only constraint is that an action must support _arity 0_ in its constructor**.
878
912
  The following examples are valid constructors:
@@ -908,9 +942,8 @@ While a Lotus application's architecture is more web oriented, this framework is
908
942
 
909
943
  ### Rack middleware
910
944
 
911
- Rack middleware can be configured globally in `config.ru`, but often they add an
912
- unnecessary overhead for all those endpoints that aren't direct users of a
913
- certain middleware.
945
+ Rack middleware can be configured globally in `config.ru`. However, consider that they often add
946
+ unnecessary overhead for *all* endpoints that aren't direct users of all the configured middleware.
914
947
 
915
948
  Think about a middleware to create sessions, where only `SessionsController::Create` needs that middleware, but every other action pays the performance price for that middleware.
916
949
 
@@ -1067,8 +1100,8 @@ end
1067
1100
  run Action
1068
1101
  ```
1069
1102
 
1070
- Lotus::Controller heavely depends on class configuration, to ensure immutability
1071
- in deployment environments, please consider of invoke `Lotus::Controller.load!`.
1103
+ Lotus::Controller heavely depends on class configuration. To ensure immutability
1104
+ in deployment environments, use `Lotus::Controller.load!`.
1072
1105
 
1073
1106
  ## Versioning
1074
1107
 
@@ -68,11 +68,22 @@ module Lotus
68
68
  # Associate the given value with the given key and store them
69
69
  #
70
70
  # @param key [Symbol] the key
71
- # @param value [Object] the value
71
+ # @param value [#to_s,Hash] value that can be serialized as a string or
72
+ # expressed as a Hash
73
+ # @option value [String] :domain - The domain
74
+ # @option value [String] :path - The path
75
+ # @option value [Integer] :max_age - Duration expressed in seconds
76
+ # @option value [Time] :expires - Expiration time
77
+ # @option value [TrueClass,FalseClass] :secure - Restrict cookie to secure
78
+ # connections
79
+ # @option value [TrueClass,FalseClass] :httponly - Restrict JavaScript
80
+ # access
72
81
  #
73
82
  # @return [void]
74
83
  #
75
84
  # @since 0.2.0
85
+ #
86
+ # @see http://en.wikipedia.org/wiki/HTTP_cookie
76
87
  def []=(key, value)
77
88
  @cookies[key] = value
78
89
  end
@@ -93,6 +104,7 @@ module Lotus
93
104
  end
94
105
  @default_options.merge cookies_options
95
106
  end
107
+
96
108
  # Extract the cookies from the raw Rack env.
97
109
  #
98
110
  # This implementation is borrowed from Rack::Request#cookies.
@@ -14,12 +14,21 @@ module Lotus
14
14
 
15
15
  # Gets the cookies from the request and expose them as an Hash
16
16
  #
17
- # @return [Lotus::Action::CookieJar] the cookies
17
+ # It automatically sets options from global configuration, but it allows to
18
+ # override values case by case.
19
+ #
20
+ # For a list of options please have a look at <tt>Lotus::Controller::Configuration</tt>,
21
+ # and <tt>Lotus::Action::CookieJar</tt>.
22
+ #
23
+ # @return [Lotus::Action::CookieJar] cookies
18
24
  #
19
25
  # @since 0.1.0
20
26
  # @api public
21
27
  #
22
- # @example
28
+ # @see Lotus::Controller::Configuration#cookies
29
+ # @see Lotus::Action::CookieJar#[]=
30
+ #
31
+ # @example Basic Usage
23
32
  # require 'lotus/controller'
24
33
  # require 'lotus/action/cookies'
25
34
  #
@@ -40,6 +49,21 @@ module Lotus
40
49
  # cookies[:bax] = nil
41
50
  # end
42
51
  # end
52
+ #
53
+ # @example Cookies Options
54
+ # require 'lotus/controller'
55
+ # require 'lotus/action/cookies'
56
+ #
57
+ # class Show
58
+ # include Lotus::Action
59
+ # include Lotus::Action::Cookies
60
+ #
61
+ # def call(params)
62
+ # # ...
63
+ # # set a value
64
+ # cookies[:foo] = { value: 'bar', max_age: 300, path: '/dashboard' }
65
+ # end
66
+ # end
43
67
  def cookies
44
68
  @cookies ||= CookieJar.new(@_env.dup, headers, configuration.cookies)
45
69
  end
@@ -30,11 +30,9 @@ module Lotus
30
30
  'Allow' => true,
31
31
  'Content-Encoding' => true,
32
32
  'Content-Language' => true,
33
- 'Content-Length' => true,
34
33
  'Content-Location' => true,
35
34
  'Content-MD5' => true,
36
35
  'Content-Range' => true,
37
- 'Content-Type' => true,
38
36
  'Expires' => true,
39
37
  'Last-Modified' => true,
40
38
  'extension-header' => true
@@ -1,3 +1,5 @@
1
+ require 'rack/utils'
2
+ require 'lotus/utils'
1
3
  require 'lotus/utils/kernel'
2
4
 
3
5
  module Lotus
@@ -415,7 +417,7 @@ module Lotus
415
417
  # @api private
416
418
  def accepts
417
419
  unless accept == DEFAULT_ACCEPT
418
- ::Rack::Utils.best_q_match(accept, ::Rack::Mime::MIME_TYPES.values)
420
+ best_q_match(accept, ::Rack::Mime::MIME_TYPES.values)
419
421
  end
420
422
  end
421
423
 
@@ -446,6 +448,34 @@ module Lotus
446
448
  "#{content_type}; charset=#{charset}"
447
449
  end
448
450
 
451
+ # Patched version of <tt>Rack::Utils.best_q_match</tt>.
452
+ #
453
+ # @since x.x.x
454
+ # @api private
455
+ #
456
+ # @see http://www.rubydoc.info/gems/rack/Rack/Utils#best_q_match-class_method
457
+ # @see https://github.com/rack/rack/pull/659
458
+ # @see https://github.com/lotus/controller/issues/59
459
+ # @see https://github.com/lotus/controller/issues/104
460
+ def best_q_match(q_value_header, available_mimes)
461
+ values = ::Rack::Utils.q_values(q_value_header)
462
+
463
+ values = values.map do |req_mime, quality|
464
+ match = available_mimes.find { |am| ::Rack::Mime.match?(am, req_mime) }
465
+ next unless match
466
+ [match, quality]
467
+ end.compact
468
+
469
+ # See https://github.com/lotus/controller/issues/59
470
+ # See https://github.com/lotus/controller/issues/104
471
+ values = values.reverse unless Lotus::Utils.jruby?
472
+
473
+ value = values.sort_by do |match, quality|
474
+ (match.split('/', 2).count('*') * -10) + quality
475
+ end.last
476
+
477
+ value.first if value
478
+ end
449
479
  end
450
480
  end
451
481
  end
@@ -51,7 +51,7 @@ module Lotus
51
51
  # action = Create.new
52
52
  # action.call({}) # => [301, {'Location' => '/articles/23'}, '']
53
53
  def redirect_to(url, status: 302)
54
- headers[LOCATION] = url
54
+ headers[LOCATION] = ::String.new(url)
55
55
  halt(status)
56
56
  end
57
57
  end
@@ -2,7 +2,6 @@ require 'lotus/utils/class_attribute'
2
2
  require 'lotus/action'
3
3
  require 'lotus/controller/configuration'
4
4
  require 'lotus/controller/version'
5
- require 'rack-patch'
6
5
 
7
6
  module Lotus
8
7
  # A set of logically grouped actions
@@ -3,6 +3,6 @@ module Lotus
3
3
  # Defines the version
4
4
  #
5
5
  # @since 0.1.0
6
- VERSION = '0.4.0'.freeze
6
+ VERSION = '0.4.1'.freeze
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lotus-controller
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-03-23 00:00:00.000000000 Z
12
+ date: 2015-05-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -149,7 +149,6 @@ files:
149
149
  - lib/lotus/controller/configuration.rb
150
150
  - lib/lotus/controller/version.rb
151
151
  - lib/lotus/http/status.rb
152
- - lib/rack-patch.rb
153
152
  - lotus-controller.gemspec
154
153
  homepage: http://lotusrb.org
155
154
  licenses:
data/lib/rack-patch.rb DELETED
@@ -1,28 +0,0 @@
1
- # see https://github.com/rack/rack/pull/659
2
- require 'rack'
3
- require 'lotus/utils'
4
-
5
- if Rack.release <= '1.5'
6
- require 'rack/utils'
7
-
8
- Rack::Utils.class_eval do
9
- def self.best_q_match(q_value_header, available_mimes)
10
- values = q_values(q_value_header)
11
-
12
- values = values.map do |req_mime, quality|
13
- match = available_mimes.find { |am| Rack::Mime.match?(am, req_mime) }
14
- next unless match
15
- [match, quality]
16
- end.compact
17
-
18
- # See https://github.com/lotus/controller/issues/59
19
- values = values.reverse if RUBY_VERSION >= '2.2.0' || Lotus::Utils.rubinius?
20
-
21
- value = values.sort_by do |match, quality|
22
- (match.split('/', 2).count('*') * -10) + quality
23
- end.last
24
-
25
- value.first if value
26
- end
27
- end
28
- end