lotus-controller 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.