context_exposer 0.0.1 → 0.1.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: 12da37ed9022c53dd944d8c73f53c0da2980a65f
4
- data.tar.gz: 7cd49fd373d8ea82633f36064c21eb95303e3ab4
3
+ metadata.gz: 2452c12a649755432297fcee4e4fefb40b864313
4
+ data.tar.gz: 8ace695b9b00d9f114874aa9b5719064c64a0c83
5
5
  SHA512:
6
- metadata.gz: 4cc5284dce7e9ac8c4d9afd9470cbd69e6f29f2bcc2c75749439ad195a86326e9848dd292db2cc1e8f2d31641eee89d28198e43620d295fe930a39bb631524a9
7
- data.tar.gz: 92d81c8be3d0dd2dd4e067f3c3c1a73837319d01ffeaaba0a2c4f29890e89caaa75960b7650994ade13f545c0446339bcc69f3aa57428679500d14e94d293b61
6
+ metadata.gz: 78721b922904ab3222e41024042691c3998103414314a5f4adf75bf8b34fd6c9a529c7acee68c23af948219b3577727276ffb1c617fd8d1ed21dc93a92484d47
7
+ data.tar.gz: c0bcbf8cb1781b7fc39f0b1d6246c7b11f931056925f64becd31ab19f3e76606b996b4faa5e67470ec8c407c4dc86bb9ba4c369fe7bfae23330a33f1914bec34
data/Gemfile CHANGED
@@ -3,20 +3,6 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in context_exposer.gemspec
4
4
  gemspec
5
5
 
6
- gem 'pry'
7
6
  gem 'rails', '>= 3.1'
8
-
9
- gem "rspec-rails", :group => [:test, :development]
10
-
11
- group :test do
12
- # gem 'factory_girl_rails', :require => false
13
- # gem "capybara"
14
- # gem "capybara-webkit"
15
- # gem 'growl'
16
- # gem "spork"
17
- # gem "guard"
18
- # gem "guard-bundler"
19
- # gem "guard-rspec"
20
- # gem "guard-spork"
21
- # gem "launchy"
22
- end
7
+ gem "rspec-rails", '>= 2.0', group: [:test, :development]
8
+ gem 'pry', group: [:development]
data/README.md CHANGED
@@ -36,6 +36,14 @@ class PostsController < ActionController::Base
36
36
  end
37
37
  ```
38
38
 
39
+ HAML view example
40
+
41
+ ```haml
42
+ %h1 Posts
43
+ = context.posts.each do |post|
44
+ %h2 = post.name
45
+ ```
46
+
39
47
  You can also define your own subclass of `ViewContext` and designate an instance of this custom class as your "exposed" target, via `view_context_class`method.
40
48
 
41
49
  Example:
@@ -47,7 +55,7 @@ class PostsController < ActionController::Base
47
55
  view_context_class :posts_view_context
48
56
 
49
57
  exposed(:post) { Post.find params[:id] }
50
- exposed(:posts) { Post.find params[:id] }
58
+ exposed(:posts) { Post.all }
51
59
  end
52
60
  ```
53
61
 
@@ -78,29 +86,78 @@ class PostsViewContext < ContextExposer::ViewContext
78
86
  end
79
87
  ```
80
88
 
89
+ HAML view example
90
+
91
+ ```haml
92
+ %h1 Admin Posts
93
+ = context.admin_posts.each do |post|
94
+ %h2 = post.name
95
+ ```
96
+
97
+
81
98
  This opens up some amazing possibilities to really put the logic where it belongs.The custom ViewContext would benefit from having the "admin" and "user" logic extracted either to separate modules or a custom ViewContext base class ;)
82
99
 
83
100
  This approach opens up many new exciting ways to slice and dice your logic in a much better way, a new *MVC-C* architecture, the extra "C" for *Context*.
84
101
 
102
+ ### ResourceController
85
103
 
86
- ## TODO
104
+ The `ResourceController` automatically sets up the typical singular and plural-form resource helpers.
87
105
 
88
- Add some useful subclasses of `BaseController`, that add some extra magic!
89
- Also add some basic modules to integrate with typical authentication solutions etc. Get inspiration from other similar gems, fx `decent_exposure`. Allow for integration between these different solutions.
106
+ This simplifies the above `PostsController` example to this:
90
107
 
91
- ### ResourceController
108
+ ```ruby
109
+ class PostsController < ActionController::Base
110
+ include ContextExposer::ResourceController
111
+ end
112
+ ```
113
+
114
+ `ResourceController` uses the following internal logic for its default functionality. You can override these methods to customize your behavior as needed.
92
115
 
93
- It sould be nice to have a `ResourceController` to automatically set up the typical singular and plural-form resource helpers.
116
+ ```ruby
117
+ module ContextExposer::ResourceController
118
+ # ...
119
+
120
+ protected
121
+
122
+ def resource_id
123
+ params[:id]
124
+ end
125
+
126
+ def find_single_resource
127
+ self.class._the_resource.find resource_id
128
+ end
129
+
130
+ def find_all_resources
131
+ self.class._the_resource.all
132
+ end
133
+ ```
94
134
 
95
- This would simplify the above `PostsController` example to this:
135
+ ## Integration with decent_exposure gem
136
+
137
+ Initial integration support is included for `decent_exposure`, another popular gem with similar functionality. To add methods exposed by `decent_exposure` `#expose` to the context object, simply call `#context_expose_decently` or the alias method `#expose_decently`.
96
138
 
97
139
  ```ruby
140
+ # using gem 'decent_exposure'
141
+ # auto-included in ActionController::Base
142
+
98
143
  class PostsController < ActionController::Base
99
144
  include ContextExposer::ResourceController
145
+
146
+ expose(:posts)
147
+ expose(:post) { Post.first}
148
+ expose(:postal)
149
+
150
+ context_expose_decently except: 'postal'
100
151
  end
101
152
  ```
102
153
 
103
- Please help out :)
154
+ HAML view example
155
+
156
+ ```haml
157
+ %h1 Posts
158
+ = context.posts.each do |post|
159
+ %h2 = post.name
160
+ ```
104
161
 
105
162
  ## Contributing
106
163
 
@@ -5,4 +5,5 @@ end
5
5
 
6
6
  require "active_support"
7
7
  require "context_exposer/base_controller"
8
+ require "context_exposer/resource_controller"
8
9
  require "context_exposer/view_context"
@@ -5,6 +5,8 @@ module ContextExposer::BaseController
5
5
  before_filter :configure_exposed_context
6
6
 
7
7
  expose_context :context
8
+
9
+ # set_callback :process_action, :before, :configure_exposed_context
8
10
  end
9
11
 
10
12
  def view_context
@@ -18,6 +20,26 @@ module ContextExposer::BaseController
18
20
  exposure_storage[name.to_sym] = block
19
21
  end
20
22
 
23
+ # expose all exposures exposed by decent_exposure to context
24
+ def context_expose_decently options = {}
25
+ transfer_keys = _exposures.keys
26
+ except = (options[:except] || {}).map(&:to_sym)
27
+ only = (options[:only] || {}).map(&:to_sym)
28
+
29
+ transfer_keys = transfer_keys - except
30
+
31
+ unless only.empty?
32
+ transfer_keys.select {|k| only.include? k.to_sym }
33
+ end
34
+
35
+ transfer_keys.each do |exposure|
36
+ exposed exposure do
37
+ send(exposure)
38
+ end
39
+ end
40
+ end
41
+ alias_method :expose_decently, :context_expose_decently
42
+
21
43
  def view_context_class name
22
44
  define_method :view_context_class do
23
45
  @view_context_class ||= name.kind_of?(Class) ? name : name.to_s.camelize.constantize
@@ -28,6 +50,7 @@ module ContextExposer::BaseController
28
50
 
29
51
  def expose_context name
30
52
  return if exposed_view_context?
53
+
31
54
  if ActionController::Base.instance_methods.include?(name.to_sym)
32
55
  Kernel.warn "[WARNING] You are exposing the `#{name}` method, " \
33
56
  "which overrides an existing ActionController method of the same name. " \
@@ -40,7 +63,7 @@ module ContextExposer::BaseController
40
63
  end
41
64
 
42
65
  def exposed_view_context?
43
- @exposed_view_context ||= false
66
+ @exposed_view_context == true
44
67
  end
45
68
 
46
69
  def exposure_storage
@@ -57,10 +80,10 @@ module ContextExposer::BaseController
57
80
  return if configured_exposed_context?
58
81
  clazz = self.class
59
82
  exposed_methods = clazz.send(:exposure_hash)[clazz.to_s] || []
60
- # puts "exposed_methods for: #{clazz} - #{exposed_methods}"
61
83
  exposed_methods.each do |name, procedure|
84
+ this = self
62
85
  view_context.send :define_singleton_method, name do
63
- procedure.call
86
+ this.instance_eval(&procedure)
64
87
  end
65
88
  end
66
89
  @configured_exposed_context = true
@@ -0,0 +1,47 @@
1
+ module ContextExposer::ResourceController
2
+ extend ActiveSupport::Concern
3
+ include ContextExposer::BaseController
4
+
5
+ included do
6
+ puts "included: #{_normalized_resource_name}"
7
+
8
+ exposed(_normalized_resource_name.singularize) do
9
+ find_single_resource
10
+ end
11
+
12
+ exposed(_normalized_resource_name.pluralize) { find_all_resources }
13
+ exposed(_normalized_resource_list) { find_all_resources.to_a }
14
+ end
15
+
16
+ protected
17
+
18
+ def resource_id
19
+ params[:id]
20
+ end
21
+
22
+ def find_single_resource
23
+ self.class._the_resource.find resource_id
24
+ end
25
+
26
+ def find_all_resources
27
+ self.class._the_resource.all
28
+ end
29
+
30
+ module ClassMethods
31
+ def _the_resource
32
+ clazz_name = self.to_s.sub(/Controller$/, '').singularize
33
+ clazz_name.constantize
34
+ rescue NameError => e
35
+ raise "Resource #{clazz_name} is not defined. #{e}"
36
+ end
37
+
38
+ def _normalized_resource_list
39
+ _normalized_resource_name.pluralize + '_list'
40
+ end
41
+
42
+ def _normalized_resource_name
43
+ self.to_s.demodulize.sub(/Controller$/, '').underscore
44
+ end
45
+ end
46
+ end
47
+
@@ -1,3 +1,3 @@
1
1
  module ContextExposer
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,103 @@
1
+ require 'context_exposer'
2
+ # require 'rails'
3
+ require 'action_controller'
4
+
5
+ class Post
6
+ attr_accessor :name
7
+
8
+ def initialize name
9
+ @name = name
10
+ Post.add self
11
+ end
12
+
13
+ def self.find id
14
+ list.first
15
+ end
16
+
17
+ def self.all
18
+ Post.list
19
+ end
20
+
21
+ protected
22
+
23
+ def self.add post
24
+ list << post
25
+ end
26
+
27
+ def self.list
28
+ @list ||= []
29
+ end
30
+ end
31
+
32
+ class PostsController < ActionController::Base
33
+ include ContextExposer::ResourceController
34
+
35
+ def show
36
+ configure_exposed_context
37
+ end
38
+
39
+ def index
40
+ end
41
+
42
+ protected
43
+
44
+ def params
45
+ {id: 1}
46
+ end
47
+ end
48
+
49
+ describe ContextExposer::ResourceController do
50
+ describe "controller" do
51
+ subject { controller }
52
+
53
+ let(:controller) { PostsController.new }
54
+
55
+ before :all do
56
+ @post1 = Post.new 'My 1st post'
57
+ @post2 = Post.new 'My 2nd post'
58
+ end
59
+
60
+ context 'show post' do
61
+ # run action post
62
+ before :each do
63
+ controller.show
64
+ end
65
+
66
+ it 'defines :show as an action_method' do
67
+ expect(subject.action_methods).to include('show')
68
+ end
69
+
70
+ it "defines a method context" do
71
+ expect(subject).to respond_to(:context)
72
+ end
73
+
74
+ it "exposes the context to the view layer as a helper" do
75
+ expect(subject._helper_methods).to include(:context)
76
+ end
77
+
78
+ context 'context' do
79
+ subject { controller.context }
80
+
81
+ it "is an instance of ContextExposer::ViewContext" do
82
+ expect(subject).to be_a ContextExposer::ViewContext
83
+ end
84
+
85
+ it "defines a method :post" do
86
+ expect(subject).to respond_to(:post)
87
+ end
88
+
89
+ it "defines a method :posts" do
90
+ expect(subject).to respond_to(:posts)
91
+ end
92
+
93
+ it "calling method :post returns 'My 1st post' " do
94
+ expect(subject.post.name).to eq @post1.name
95
+ end
96
+
97
+ it "calling method :posts returns all posts " do
98
+ expect(subject.posts).to eq [@post1, @post2]
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -4,10 +4,20 @@ require 'action_controller'
4
4
  class MyController < ActionController::Base
5
5
  include ContextExposer::BaseController
6
6
 
7
- exposed(:post) { Post.find params[:id] }
7
+ exposed(:bird) { "Bird" }
8
8
 
9
- def post
9
+ # since: extend DecentExposure::Exposure
10
+ def self._exposures
11
+ {decent: 'hi', hello: 'yo!'}
12
+ end
13
+
14
+ expose_decently except: %w{hello}
15
+
16
+ def show
17
+ configure_exposed_context
10
18
  end
19
+
20
+ protected
11
21
  end
12
22
 
13
23
  class MyCoolController < ActionController::Base
@@ -21,7 +31,9 @@ class MyCoolController < ActionController::Base
21
31
  configure_exposed_context
22
32
  end
23
33
 
24
- def params; end
34
+ protected
35
+
36
+ def params; end
25
37
  end
26
38
 
27
39
  class MegaCoolViewContext < ContextExposer::ViewContext
@@ -43,11 +55,11 @@ describe ContextExposer::BaseController do
43
55
 
44
56
  # run action post
45
57
  before :each do
46
- controller.post
58
+ controller.show
47
59
  end
48
60
 
49
- it 'defines :post as an action_method' do
50
- expect(subject.action_methods).to include('post')
61
+ it 'defines :show as an action_method' do
62
+ expect(subject.action_methods).to include('show')
51
63
  end
52
64
 
53
65
  it "defines a method context" do
@@ -77,6 +89,14 @@ describe ContextExposer::BaseController do
77
89
  expect(subject).to respond_to(:bird)
78
90
  end
79
91
 
92
+ it "defines a method :decent" do
93
+ expect(subject).to respond_to(:decent)
94
+ end
95
+
96
+ it "does not defines a decent method :hello" do
97
+ expect(subject).to_not respond_to(:hello)
98
+ end
99
+
80
100
  it "calling method :bird returns 'Bird' " do
81
101
  expect(subject.bird).to eq "Bird"
82
102
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: context_exposer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kristian Mandrup
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-03-14 00:00:00.000000000 Z
11
+ date: 2013-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -55,9 +55,11 @@ files:
55
55
  - context_exposer.gemspec
56
56
  - lib/context_exposer.rb
57
57
  - lib/context_exposer/base_controller.rb
58
+ - lib/context_exposer/resource_controller.rb
58
59
  - lib/context_exposer/version.rb
59
60
  - lib/context_exposer/view_context.rb
60
61
  - spec/app/posts_spec.rb
62
+ - spec/context_exposer/expose_resource_spec.rb
61
63
  - spec/context_exposer/expose_spec.rb
62
64
  - spec/dummy/README.rdoc
63
65
  - spec/dummy/Rakefile
@@ -122,6 +124,7 @@ summary: The Context object becomes the single communication point between View
122
124
  Controller
123
125
  test_files:
124
126
  - spec/app/posts_spec.rb
127
+ - spec/context_exposer/expose_resource_spec.rb
125
128
  - spec/context_exposer/expose_spec.rb
126
129
  - spec/dummy/README.rdoc
127
130
  - spec/dummy/Rakefile