lotus-controller 0.1.0 → 0.2.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: fac98fda3029902773f0dc45d886942f4e3fae87
4
- data.tar.gz: b2a40a8361d84bb0625aaf8d60925952999704ce
3
+ metadata.gz: 596855476b8c72b53e86d1101e54edb8137e4206
4
+ data.tar.gz: 40df1097012f2d091aad3eff3734cdd71077ecde
5
5
  SHA512:
6
- metadata.gz: 8f3c1d85c792b625120de32d1210dcd080501a6b041a5ccc3ee9d6788cb44bbe0354162c097f9488acdc25ddd841fa1378e9d24547832ba4b61b83edb4e44251
7
- data.tar.gz: 5080fe24a7c4260054730dddf65ebcf10803c45ddd4f95981984971cc81a9e635ef723fcffbc19150226125fc34ce3d9c9003b57ce59fbdd3f9f330b4b8c8104
6
+ metadata.gz: ebeec9005fb1c28cc195af167872a9d6aa206c65c951488b9671c11a472ff36c017c3c647c9e964db92a903cfa16b7a0f6b3b4dab777d1c18fa7de7438c590e5
7
+ data.tar.gz: 2626b3767d3a68ef4a2b7418c3d0711e68e27ea70f32fed7623391419ef2eacc447b65476eaabac224121ff68f1e51b9cf2bf07961a3280637d3231b39a0c159
data/CHANGELOG.md ADDED
@@ -0,0 +1,127 @@
1
+ ## v0.2.0
2
+ ### Jun 23, 2014
3
+
4
+ 48a5715 2014-06-22 **Luca Guidi** Made Lotus::Action#content_type public
5
+
6
+ 2d7b0cc 2014-06-22 **Luca Guidi** Let to specify a default format for all the requests that aren't strict about the requested Mime type (eg. `*/*`).
7
+
8
+ 401c1af 2014-06-19 **Luca Guidi** [breaking] Raise error if Lotus::Controller::Configuration#format doesn't receive the proper argument. Let Lotus::Action::Mime#accept to work with registered mime types
9
+
10
+ 028ec2e 2014-06-19 **Luca Guidi** Make Lotus::Action::Mime#format a public method
11
+
12
+ ce42cd4 2014-06-19 **Luca Guidi** Detect the asked mime type and return the corresponding format
13
+
14
+ 87323ad 2014-06-19 **Luca Guidi** Let actions to detect accepted mime type and to return the correct format symbol. Configuration can now register mime types
15
+
16
+ adf0357 2014-06-18 **Krzysztof Zalewski** [breaking] Implement Action#format
17
+
18
+ 328153b 2014-06-17 **Luca Guidi** Bump version to v0.2.0
19
+
20
+ b2e5c85 2014-06-17 **Luca Guidi** Depend on lotus-utils ~> 0.2
21
+
22
+ 166a3c8 2014-06-17 **Luca Guidi** Controller.duplicate can accept nil controllers namespace
23
+
24
+ c11bc96 2014-06-17 **Luca Guidi** Lotus::Controller: .duplicate => .dup, .generate => .duplicate
25
+
26
+ 9488c66 2014-06-16 **Luca Guidi** Gem: build only with lib/ and essential files
27
+
28
+ cd7038c 2014-06-16 **Luca Guidi** [breaking] Removed Lotus::Action::Throwable#throw in favor of #halt
29
+
30
+ c200e68 2014-06-16 **Luca Guidi** Pretty print exceptions in rack.errors
31
+
32
+ 3c122b0 2014-06-13 **Krzysztof Zalewski** Reference exception in rack.errors
33
+
34
+ 9e64c3f 2014-06-11 **Luca Guidi** Let Lotus::Controller.generate to set action_module
35
+
36
+ f28d7e3 2014-06-11 **Luca Guidi** Introducing Lotus::Controller.generate as shortcut for .duplicate and .configure
37
+
38
+ af217ea 2014-06-08 **Luca Guidi** [breaking] Use composition over inheritance for Lotus::Action::Params
39
+
40
+ 47e86db 2014-06-08 **Luca Guidi** [breaking] Use composition over inheritance for Lotus::Action::CookieJar
41
+
42
+ 5e2a4a7 2014-05-28 **Luca Guidi** Allow standalone actions to inherit configuration from the right framework. Added Configuration#modules in order to configure the additional modules to include by default
43
+
44
+ ceb7214 2014-05-28 **Luca Guidi** Better Ruby idioms
45
+
46
+ 075f9c3 2014-05-28 **Luca Guidi** Use the proper level of encapsulation for Configuration
47
+
48
+ 431970c 2014-05-27 **Luca Guidi** Ensure the right level of duplication for Lotus::Controller
49
+
50
+ ae49c57 2014-05-27 **Luca Guidi** [breaking] Keep independent copies of framework, controller and action configurations. Introduced in action_module for configuration.
51
+
52
+ c56683a 2014-05-27 **Luca Guidi** [breaking] Introduced configuration for Controller and Action
53
+
54
+ 8d39557 2014-05-10 **Luca Guidi** Added support for Ruby 2.1.2
55
+
56
+ c2854b6 2014-04-27 **Luca Guidi** Make HTTP status messages compliant with IANA and Rack
57
+
58
+ c137c3f 2014-04-27 **Luca Guidi** Implemented Action.use, that let to use a Rack middleware as a before callback
59
+
60
+ eb86286 2014-04-20 **Damir Zekic** Replace `#throw` override with `#halt` method
61
+
62
+ 6da21f9 2014-03-17 **Damir Zekic** Allow exception handling to be disabled
63
+
64
+ c0ccb72 2014-02-24 **Luca Guidi Added support for Ruby 2.1.1
65
+
66
+ ## v0.1.0
67
+ ### Feb 23, 2014
68
+
69
+ f750e4c 2014-02-22 **Luca Guidi** Moved .handled_exceptions from Action to Controller, so that the place where to configure the framework will be easier to find for developers.
70
+
71
+ 1de2a27 2014-02-17 **Luca Guidi** Added Lotus::Action.handle_exception
72
+
73
+ fd9e080 2014-02-13 **Luca Guidi** Implemented Lotus::Action.accept, in order to restrict the access when a non supported mime type is requested
74
+
75
+ 516983f 2014-02-13 **Luca Guidi** Implemented Lotus::Action#accept?
76
+
77
+ 634719a 2014-02-13 **Luca Guidi** Changed auto content type policy
78
+
79
+ 7cce354 2014-02-12 **Luca Guidi** Use @_env instead of the argument in Lotus::Action::Callable#call
80
+
81
+ a41b43d 2014-02-12 **Luca Guidi** Extracted constants for Lotus::Action::Params
82
+
83
+ 6bdf55b 2014-01-31 **Luca Guidi** Make session support optional
84
+
85
+ 29c5f8c 2014-01-31 **Luca Guidi** Make cookies support optional
86
+
87
+ 0b36afb 2014-01-31 **Luca Guidi** Removed Lotus::HTTP::Request and Response
88
+
89
+ 25b2bcf 2014-01-31 **Luca Guidi** Return serialized Rack response (Array) instead of the object. Lotus::Action::Redirect no longer depends on Response. Lotus::Action::CookieJar no longer depends on Response, but on headers.
90
+
91
+ b306f4f 2014-01-31 **Luca Guidi** Lotus::Action::Rack#session no longer depends on Request
92
+
93
+ 9a44477 2014-01-31 **Luca Guidi** Lotus::Action::Mime no longer depends on Request
94
+
95
+ 9b7f524 2014-01-31 **Luca Guidi** Lotus::Action::CookieJar logic for cookies extraction/set/get is no longer dependant on Request and Response.
96
+
97
+ fc6de40 2013-09-24 **Luca Guidi** Don't wrap body if respond to #each
98
+
99
+ ce46399 2013-09-24 **Luca Guidi** Introducing factory for Response
100
+
101
+ 83adc9c 2013-08-07 **Luca Guidi** Ensure to wrap body for HTTP::Response
102
+
103
+ 0a41bf8 2013-08-07 **Luca Guidi** Introducing Lotus::HTTP::Request/Response
104
+
105
+ c44d440 2013-07-12 **Luca Guidi** Integration tests for sessions
106
+
107
+ e62b355 2013-07-11 **Luca Guidi** Added automatic Mime Type capabilities
108
+
109
+ 351eb2f 2013-07-11 **Luca Guidi** Split features in proper `Lotus::Action` submodules.
110
+
111
+ 9d268df 2013-07-10 **Luca Guidi** Introducing throw facility, to stop the request flow immediately.
112
+
113
+ 73af6d1 2013-07-09 **Luca Guidi** Integration tests with Lotus::Router
114
+
115
+ 6938fae 2013-07-05 **Luca Guidi** Implemented cookies facilities.
116
+
117
+ 69f4c62 2013-07-02 **Luca Guidi** Rack compatibility
118
+
119
+ 13bd2d2 2013-06-28 **Luca Guidi** Implemented #redirect_to
120
+
121
+ 5adbee1 2013-06-28 **Luca Guidi** Implemented sessions support
122
+
123
+ 4bb794d 2013-06-28 **Luca Guidi** Implemented action callbacks
124
+
125
+ 3b792dc 2013-06-25 **Luca Guidi** Introducing Lotus::Controller
126
+
127
+ d279c48 2013-06-25 **Luca Guidi** Initial mess
File without changes
data/README.md CHANGED
@@ -9,6 +9,7 @@ A Rack compatible Controller layer for [Lotus](http://lotusrb.org).
9
9
  [![Coverage](https://coveralls.io/repos/lotus/controller/badge.png?branch=master)](https://coveralls.io/r/lotus/controller)
10
10
  [![Code Climate](https://codeclimate.com/github/lotus/controller.png)](https://codeclimate.com/github/lotus/controller)
11
11
  [![Dependencies](https://gemnasium.com/lotus/controller.png)](https://gemnasium.com/lotus/controller)
12
+ [![Inline docs](http://inch-ci.org/github/lotus/controller.png)](http://inch-ci.org/github/lotus/controller)
12
13
 
13
14
  ## Contact
14
15
 
@@ -16,7 +17,8 @@ A Rack compatible Controller layer for [Lotus](http://lotusrb.org).
16
17
  * Mailing List: http://lotusrb.org/mailing-list
17
18
  * API Doc: http://rdoc.info/gems/lotus-controller
18
19
  * Bugs/Issues: https://github.com/lotus/controller/issues
19
- * Support: http://stackoverflow.com/questions/tagged/lotusrb
20
+ * Support: http://stackoverflow.com/questions/tagged/lotus-ruby
21
+ * Chat: https://gitter.im/lotus/chat
20
22
 
21
23
  ## Rubies
22
24
 
@@ -44,7 +46,7 @@ $ gem install lotus-controller
44
46
 
45
47
  ## Usage
46
48
 
47
- Lotus::Controller is a thin layer (**275 LOCs**) for MVC web frameworks.
49
+ Lotus::Controller is a micro library for web frameworks.
48
50
  It works beautifully with [Lotus::Router](https://github.com/lotus/router), but it can be employed everywhere.
49
51
  It's designed to be fast and testable.
50
52
 
@@ -262,7 +264,7 @@ You can define how a specific raised exception should be transformed in an HTTP
262
264
  ```ruby
263
265
  class Show
264
266
  include Lotus::Action
265
- handle_exception RecordNotFound, 404
267
+ handle_exception RecordNotFound => 404
266
268
 
267
269
  def call(params)
268
270
  @article = Article.find params[:id]
@@ -277,7 +279,9 @@ Exception policies can be defined globally, **before** the controllers/actions
277
279
  are loaded.
278
280
 
279
281
  ```ruby
280
- Lotus::Controller.handled_exceptions = { RecordNotFound => 404 }
282
+ Lotus::Controller.configure do
283
+ handle_exception RecordNotFound => 404
284
+ end
281
285
 
282
286
  class Show
283
287
  include Lotus::Action
@@ -291,9 +295,36 @@ action = Show.new
291
295
  action.call({id: 'unknown'}) # => [404, {}, ["Not Found"]]
292
296
  ```
293
297
 
298
+ This feature can be turned off globally, in a controller or in a single action.
299
+
300
+ ```ruby
301
+ Lotus::Controller.configure do
302
+ handle_exceptions false
303
+ end
304
+
305
+ # or
306
+
307
+ class ArticlesController
308
+ include Lotus::Controller
309
+
310
+ configure do
311
+ handle_exceptions false
312
+ end
313
+
314
+ action 'Show' do
315
+ def call(params)
316
+ @article = Article.find params[:id]
317
+ end
318
+ end
319
+ end
320
+
321
+ action = ArticlesController::Show.new
322
+ action.call({id: 'unknown'}) # => [404, {}, ["Not Found"]]
323
+ ```
324
+
294
325
  ### Throwable HTTP statuses
295
326
 
296
- When [#throw](http://ruby-doc.org/core-2.1.0/Kernel.html#method-i-throw) is used with a valid HTTP code, it stops the execution and sets the proper status and body for the response:
327
+ When `#halt` is used with a valid HTTP code, it stops the execution and sets the proper status and body for the response:
297
328
 
298
329
  ```ruby
299
330
  class Show
@@ -307,7 +338,7 @@ class Show
307
338
 
308
339
  private
309
340
  def authenticate!
310
- throw 401 unless authenticated?
341
+ halt 401 unless authenticated?
311
342
  end
312
343
  end
313
344
 
@@ -469,8 +500,26 @@ action.call({ article: { title: 'Hello' }}) # => [302, {'Location' => '/articles
469
500
 
470
501
  ### Mime types
471
502
 
472
- Lotus::Action automatically sets the mime type, according to the request headers.
473
- However, you can override this value:
503
+ Lotus::Action automatically sets the `Content-Type` header, according to the request.
504
+
505
+ ```ruby
506
+ class Show
507
+ include Lotus::Action
508
+
509
+ def call(params)
510
+ end
511
+ end
512
+
513
+ action = Show.new
514
+
515
+ action.call({ 'HTTP_ACCEPT' => '*/*' }) # Content-Type "application/octet-stream"
516
+ action.format # :all
517
+
518
+ action.call({ 'HTTP_ACCEPT' => 'text/html' }) # Content-Type "text/html"
519
+ action.format # :html
520
+ ```
521
+
522
+ However, you can force this value:
474
523
 
475
524
  ```ruby
476
525
  class Show
@@ -478,12 +527,17 @@ class Show
478
527
 
479
528
  def call(params)
480
529
  # ...
481
- self.content_type = 'application/json'
530
+ self.format = :json
482
531
  end
483
532
  end
484
533
 
485
534
  action = Show.new
486
- action.call({ id: 23 }) # => [200, {'Content-Type' => 'application/json'}, '...']
535
+
536
+ action.call({ 'HTTP_ACCEPT' => '*/*' }) # Content-Type "application/json"
537
+ action.format # :json
538
+
539
+ action.call({ 'HTTP_ACCEPT' => 'text/html' }) # Content-Type "application/json"
540
+ action.format # :json
487
541
  ```
488
542
 
489
543
  You can restrict the accepted mime types:
@@ -517,6 +571,7 @@ class Show
517
571
  accept?('text/html') # => true
518
572
  accept?('application/xml') # => true
519
573
  accept?('application/json') # => false
574
+ self.format # :html
520
575
 
521
576
 
522
577
 
@@ -525,8 +580,44 @@ class Show
525
580
  accept?('text/html') # => true
526
581
  accept?('application/xml') # => true
527
582
  accept?('application/json') # => true
583
+ self.format # :html
584
+ end
585
+ end
586
+ ```
587
+
588
+ Lotus::Controller is shipped with an extensive list of the most common mime types.
589
+ Also, you can register your own:
590
+
591
+ ```ruby
592
+ Lotus::Controller.configure do
593
+ format custom: 'application/custom'
594
+ end
595
+
596
+ class Index
597
+ include Lotus::Action
598
+
599
+ def call(params)
600
+ end
601
+ end
602
+
603
+ action = Index.new
604
+
605
+ action.call({ 'HTTP_ACCEPT' => 'application/custom' }) # => Content-Type 'application/custom'
606
+ action.format # => :custom
607
+
608
+ class Show
609
+ include Lotus::Action
610
+
611
+ def call(params)
612
+ # ...
613
+ self.format = :custom
528
614
  end
529
615
  end
616
+
617
+ action = Show.new
618
+
619
+ action.call({ 'HTTP_ACCEPT' => '*/*' }) # => Content-Type 'application/custom'
620
+ action.format # => :custom
530
621
  ```
531
622
 
532
623
  ### No rendering, please
@@ -554,7 +645,7 @@ class ArticlesController
554
645
  end
555
646
  ```
556
647
 
557
- Which is a bit verboses. Instead, just do:
648
+ Which is a bit verbose. Instead, just do:
558
649
 
559
650
  ```ruby
560
651
  class ArticlesController
@@ -572,7 +663,7 @@ end
572
663
  ArticlesController::Index.new.call({})
573
664
  ```
574
665
 
575
- ## Lotus::Router integration
666
+ ### Lotus::Router integration
576
667
 
577
668
  While Lotus::Router works great with this framework, Lotus::Controller doesn't depend from it.
578
669
  You, as developer, are free to choose your own routing system.
@@ -604,12 +695,165 @@ convenient fallback, you should know that it's the slower option. **Be sure of
604
695
  loading your controllers before you initialize the router.**
605
696
 
606
697
 
607
- ## Rack integration
698
+ ### Rack integration
608
699
 
609
700
  Lotus::Controller is compatible with Rack. However, it doesn't mount any middleware.
610
- While a Lotus application's architecture is more web oriented, this framework is designed to build pure HTTP entpoints.
701
+ While a Lotus application's architecture is more web oriented, this framework is designed to build pure HTTP endpoints.
702
+
703
+ ### Rack middleware
704
+
705
+ Rack middleware can be configured globally in `config.ru`, but often they add an
706
+ unnecessary overhead for all those endpoints who aren't direct users of a
707
+ certain middleware. Think about a middleware to create sessions, where only
708
+ `SessionsController::Create` may be involved and the rest of the application
709
+ shouldn't pay the performance ticket of calling that middleware.
710
+
711
+ An action can employ one or more Rack middleware, with `.use`.
712
+
713
+ ```ruby
714
+ require 'lotus/controller'
715
+
716
+ class SessionsController
717
+ include Lotus::Controller
718
+
719
+ action 'Create' do
720
+ use OmniAuth
721
+
722
+ def call(params)
723
+ # ...
724
+ end
725
+ end
726
+ end
727
+ ```
728
+
729
+ ```ruby
730
+ require 'lotus/controller'
731
+
732
+ class SessionsController
733
+ include Lotus::Controller
734
+
735
+ action 'Create' do
736
+ use XMiddleware.new('x', 123)
737
+ use YMiddleware.new
738
+ use ZMiddleware
739
+
740
+ def call(params)
741
+ # ...
742
+ end
743
+ end
744
+ end
745
+ ```
746
+
747
+ ### Configuration
748
+
749
+ Lotus::Controller can be configured with a DSL that determines its behavior.
750
+ It supports a few options:
751
+
752
+ ```ruby
753
+ require 'lotus/controller'
754
+
755
+ Lotus::Controller.configure do
756
+ # Handle exceptions with HTTP statuses (true) or don't catch them (false)
757
+ # Argument: boolean, defaults to true
758
+ #
759
+ handle_exceptions true
760
+
761
+ # If the given exception is raised, return that HTTP status
762
+ # It can be used multiple times
763
+ # Argument: hash, empty by default
764
+ #
765
+ handle_exception ArgumentError => 404
766
+
767
+ # Configure which module to include when Lotus::Controller.action is used
768
+ # Argument: module, defaults to Lotus::Action
769
+ #
770
+ action_module MyApp::Action # module, defaults to Lotus::Action
771
+
772
+ # Register a format to mime type mapping
773
+ # Argument: hash, key: format symbol, value: mime type string, empty by default
774
+ #
775
+ format custom: 'application/custom'
776
+
777
+ # Configure the modules to be included/extended/prepended by default.
778
+ # Argument: proc, empty by default
779
+ #
780
+ modules do
781
+ include Lotus::Action::Sessions
782
+ prepend MyLibrary::Session::Store
783
+ end
784
+ end
785
+ ```
786
+
787
+ All those global configurations can be overwritten at a finer grained level:
788
+ controllers. Each controller and action has its own copy of the global
789
+ configuration, so that changes are inherited from the top to the bottom, but
790
+ not bubbled up in the opposite direction.
791
+
792
+ ```ruby
793
+ require 'lotus/controller'
794
+
795
+ Lotus::Controller.configure do
796
+ handle_exception ArgumentError => 404
797
+ end
798
+
799
+ class ArticlesController
800
+ include Lotus::Controller
801
+
802
+ configure do
803
+ handle_exceptions false
804
+ end
805
+
806
+ action 'Create' do
807
+ def call(params)
808
+ raise ArgumentError
809
+ end
810
+ end
811
+ end
812
+
813
+ class UsersController
814
+ include Lotus::Controller
815
+
816
+ action 'Create' do
817
+ def call(params)
818
+ raise ArgumentError
819
+ end
820
+ end
821
+ end
822
+
823
+ UsersController::Create.new.call({}) # => HTTP 400
824
+
825
+ ArticlesController::Create.new.call({})
826
+ # => raises ArgumentError because we set handle_exceptions to false
827
+ ```
828
+
829
+ ### Reusability
830
+
831
+ Lotus::Controller can be used as a singleton framework as seen in this README.
832
+ The application code includes `Lotus::Controller` or `Lotus::Action` directly
833
+ and the configuration is unique per Ruby process.
834
+
835
+ While this is convenient for tiny applications, it doesn't fit well for more
836
+ complex scenarios, where we want micro applications to coexist together.
837
+
838
+ ```ruby
839
+ require 'lotus/controller'
840
+
841
+ module WebApp
842
+ Controller = Lotus::Controller.duplicate
843
+ end
844
+
845
+ module ApiApp
846
+ Controller = Lotus::Controller.duplicate(self) do
847
+ handle_exception ArgumentError => 400
848
+ end
849
+ end
850
+ ```
851
+
852
+ The code above defines `WebApp::Controller` and `WebApp::Action`, to be used for
853
+ the `WebApp` endpoints, while `ApiApp::Controller` and `ApiApp::Action` have
854
+ a different configuration.
611
855
 
612
- ## Thread safety
856
+ ### Thread safety
613
857
 
614
858
  An Action is **mutable**. When used without Lotus::Router, be sure to instantiate an
615
859
  action for each request.