exposure 0.0.7 → 0.1.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.
- data/VERSION +1 -1
- data/lib/exposure/behaviors/building.rb +44 -6
- data/lib/exposure/behaviors/callbacks.rb +7 -7
- data/lib/exposure/behaviors/finding.rb +4 -3
- data/lib/exposure/behaviors/flashing.rb +3 -3
- data/lib/exposure/behaviors/responding.rb +3 -3
- data/lib/exposure/configuration.rb +1 -0
- data/lib/exposure/options.rb +16 -14
- data/lib/exposure/patterns/resources.rb +4 -3
- data/lib/exposure.rb +1 -1
- data/spec/builders/builder_spec.rb +59 -0
- data/spec/builders/nested_builder_spec.rb +39 -0
- metadata +6 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
@@ -12,24 +12,62 @@ module Exposure
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def build_default_builder(member, nesting)
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
if nesting.any?
|
16
|
+
builders = self::const_set(:DefaultBuilders, {
|
17
|
+
self.resource_name.intern => Proc.new { [:build, params[resource_name] ] },
|
18
|
+
})
|
19
|
+
else
|
20
|
+
self::const_set(:DefaultBuilders, {
|
21
|
+
self.resource_name.intern => Proc.new { [:new, params[resource_name] ] },
|
22
|
+
})
|
23
|
+
end
|
18
24
|
end
|
19
25
|
end
|
20
26
|
|
21
27
|
module InstaneMethods
|
22
28
|
private
|
23
29
|
def custom_builder_for(resource_name)
|
24
|
-
|
30
|
+
if builder = self.class::Builders[resource_name]
|
31
|
+
return builder
|
32
|
+
end
|
25
33
|
end
|
26
34
|
|
27
35
|
def default_builder_for(resource_name)
|
28
|
-
|
36
|
+
if builder = self.class::DefaultBuilders[resource_name]
|
37
|
+
return builder
|
38
|
+
end
|
29
39
|
end
|
30
40
|
|
31
41
|
def builder_for(resource_name)
|
32
|
-
custom_builder_for(resource_name) || default_builder_for(resource_name)
|
42
|
+
custom_builder_for(resource_name) || default_builder_for(resource_name) || finder_for(resource_name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def call_builder_chain(object, chain, use_associaiton = true)
|
46
|
+
chain = chain.clone
|
47
|
+
links = chain.shift
|
48
|
+
return object unless links
|
49
|
+
|
50
|
+
message = builder_for(links[0])
|
51
|
+
association = links[1] if use_associaiton
|
52
|
+
|
53
|
+
case message
|
54
|
+
when Symbol
|
55
|
+
value = self.send(message)
|
56
|
+
when Proc
|
57
|
+
value = self.instance_eval(&message)
|
58
|
+
else
|
59
|
+
raise "invalid builder of #{message.inspect}"
|
60
|
+
end
|
61
|
+
|
62
|
+
if value.kind_of?(Array) && !value.respond_to?(:proxy_target)
|
63
|
+
if use_associaiton
|
64
|
+
call_builder_chain(object.send(association).send(*value), chain)
|
65
|
+
else
|
66
|
+
call_builder_chain(object.send(*value), chain)
|
67
|
+
end
|
68
|
+
else
|
69
|
+
call_builder_chain(value, chain)
|
70
|
+
end
|
33
71
|
end
|
34
72
|
end
|
35
73
|
end
|
@@ -13,7 +13,7 @@ module Exposure
|
|
13
13
|
build_callback('before', trigger, action, options)
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
# access point for creating and configuring after_ callbacks.
|
18
18
|
def after(trigger, *actions)
|
19
19
|
options = actions.extract_options!
|
@@ -25,24 +25,24 @@ module Exposure
|
|
25
25
|
# builds callbacks that adhere to the ActiveSupport::Callbacks interface
|
26
26
|
def build_callback(prefix, trigger, action, options) #:nodoc:
|
27
27
|
callback_name = "#{prefix}_#{trigger}"
|
28
|
-
|
28
|
+
|
29
29
|
if options[:on]
|
30
30
|
callback_name += "_on_#{options.delete(:on)}"
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
options[:if] ||= []
|
34
|
-
|
34
|
+
|
35
35
|
only_methods = options.delete(:only)
|
36
36
|
except_methods = options.delete(:except)
|
37
|
-
|
37
|
+
|
38
38
|
if only_methods
|
39
39
|
options[:if] << Proc.new {|c| only_methods.include?(c.action_name.intern) }
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
if except_methods
|
43
43
|
options[:if] << Proc.new {|c| !except_methods.include?(c.action_name.intern) }
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
self.send(callback_name, action, options)
|
47
47
|
end
|
48
48
|
end
|
@@ -54,12 +54,13 @@ module Exposure
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def call_finder_chain(object, chain, use_associaiton = true)
|
57
|
+
chain = chain.clone
|
57
58
|
links = chain.shift
|
58
59
|
return object unless links
|
59
|
-
|
60
|
+
|
60
61
|
message = finder_for(links[0])
|
61
62
|
association = links[1] if use_associaiton
|
62
|
-
|
63
|
+
|
63
64
|
case message
|
64
65
|
when Symbol
|
65
66
|
value = self.send(message)
|
@@ -68,7 +69,7 @@ module Exposure
|
|
68
69
|
else
|
69
70
|
raise "invalid finder of #{message.inspect}"
|
70
71
|
end
|
71
|
-
|
72
|
+
|
72
73
|
if value.kind_of?(Array) && !value.respond_to?(:proxy_target)
|
73
74
|
if use_associaiton
|
74
75
|
call_finder_chain(object.send(association).send(*value), chain)
|
@@ -17,7 +17,7 @@ module Exposure
|
|
17
17
|
# can be a Proc or method name as symbol.
|
18
18
|
def flash_for(action_name, options = {}, &block)
|
19
19
|
options[:is] ||= block
|
20
|
-
|
20
|
+
|
21
21
|
case options[:on]
|
22
22
|
when NilClass, :any
|
23
23
|
self.const_get(:FlashMessages)["#{action_name}.success.html"] = options[:is]
|
@@ -46,13 +46,13 @@ module Exposure
|
|
46
46
|
false
|
47
47
|
end
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
def default_flash_for(action_name, action_status)
|
51
51
|
if message_proc = self.class::DefaultFlashMessages["#{action_name}.#{action_status}.html"]
|
52
52
|
flash[:message] = self.instance_eval(&message_proc)
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
def flash_for(action_name, action_successful)
|
57
57
|
custom_flash_for(action_name, action_successful) || default_flash_for(action_name, action_successful)
|
58
58
|
end
|
@@ -27,7 +27,7 @@ module Exposure
|
|
27
27
|
options = actions.extract_options!
|
28
28
|
options[:is] ||= block
|
29
29
|
formats = options[:formats] || [:html]
|
30
|
-
|
30
|
+
|
31
31
|
case options[:on]
|
32
32
|
when NilClass, :any
|
33
33
|
build_custom_response(actions, :success, formats, options[:is])
|
@@ -62,7 +62,7 @@ module Exposure
|
|
62
62
|
false
|
63
63
|
end
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
def default_response_for(action_name, action_status, format)
|
67
67
|
if responder = self.class::DefaultResponses["#{action_name}.#{action_status}.#{format}"]
|
68
68
|
self.instance_eval &responder
|
@@ -70,7 +70,7 @@ module Exposure
|
|
70
70
|
return false
|
71
71
|
end
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
74
|
def response_for(action_name, action_status, format = :html)
|
75
75
|
format = :html if format == :all
|
76
76
|
custom_response_for(action_name, action_status, format) || default_response_for(action_name, action_status, format) || head(:not_acceptable)
|
data/lib/exposure/options.rb
CHANGED
@@ -1,52 +1,54 @@
|
|
1
1
|
module Exposure
|
2
2
|
module Configuration
|
3
3
|
module Options
|
4
|
-
|
5
4
|
def allow_actions!
|
6
5
|
if @_exposed_resource_options[:only]
|
7
6
|
@_exposed_resource_options[:except] = Patterns::Resources::DefaultActions - @_exposed_resource_options[:only]
|
8
7
|
end
|
9
|
-
|
8
|
+
|
10
9
|
if @_exposed_resource_options[:except]
|
11
10
|
@_exposed_resource_options[:except].each do |action|
|
12
11
|
undef_method(action)
|
13
12
|
end
|
14
13
|
end
|
15
14
|
end
|
16
|
-
|
15
|
+
|
17
16
|
def allow_formats!
|
18
17
|
formats = @_exposed_resource_options[:formats] || [:html, :xml]
|
19
18
|
end
|
20
|
-
|
19
|
+
|
21
20
|
def name!
|
22
21
|
self.resource_name = @_exposed_resource_name.to_s.singularize
|
23
22
|
self.resources_name = @_exposed_resource_name.to_s
|
24
23
|
end
|
25
|
-
|
24
|
+
|
26
25
|
def build_default_finders!
|
27
26
|
if nesting = @_exposed_resource_options[:nested]
|
28
27
|
self.build_nested_default_finders!(nesting)
|
29
28
|
return
|
30
29
|
end
|
31
|
-
|
30
|
+
|
32
31
|
self.parent_model = self.resource_name.camelize.constantize
|
33
32
|
build_default_finders(self.resource_name, [])
|
34
33
|
self.member_nesting = [ [self.resource_name.to_sym] ]
|
35
34
|
self.collection_nesting = [ [self.resources_name.to_sym] ]
|
36
35
|
end
|
37
|
-
|
36
|
+
|
38
37
|
def build_default_builders!
|
39
|
-
|
38
|
+
nesting = @_exposed_resource_options[:nested] || []
|
39
|
+
nesting = nesting.clone
|
40
|
+
nesting.shift
|
41
|
+
build_default_builder(self.resources_name, nesting)
|
40
42
|
end
|
41
|
-
|
43
|
+
|
42
44
|
def build_nested_default_finders!(nesting)
|
43
|
-
|
45
|
+
nesting = nesting.clone
|
44
46
|
self.parent_model = nesting.shift.to_s.singularize.camelize.constantize
|
45
|
-
|
47
|
+
|
46
48
|
build_default_finders(self.resources_name, nesting)
|
47
|
-
|
48
|
-
nesting.collect! {|sym| [sym.to_s.singularize.to_sym, sym]}
|
49
|
-
|
49
|
+
|
50
|
+
nesting = nesting.collect! {|sym| [sym.to_s.singularize.to_sym, sym]}
|
51
|
+
|
50
52
|
self.member_nesting = nesting + [ [self.resource_name.to_sym] ]
|
51
53
|
self.collection_nesting = nesting + [ [self.resources_name.to_sym] ]
|
52
54
|
end
|
@@ -5,6 +5,7 @@ module Exposure
|
|
5
5
|
base::const_set(:DefaultResponses, DefaultResponses)
|
6
6
|
base::const_set(:DefaultFlashMessages, DefaultFlashMessages)
|
7
7
|
base::const_set(:Finders, { true => {}, false => {} })
|
8
|
+
base::const_set(:Builders, {})
|
8
9
|
base::const_set(:FlashMessages, {})
|
9
10
|
base::const_set(:Responses, {} )
|
10
11
|
end
|
@@ -208,15 +209,15 @@ module Exposure
|
|
208
209
|
end
|
209
210
|
|
210
211
|
def build_record
|
211
|
-
@resource = instance_variable_set("@#{resource_name}", parent_model.
|
212
|
+
@resource = instance_variable_set("@#{resource_name}", call_builder_chain(parent_model, self.class.member_nesting, false))
|
212
213
|
end
|
213
214
|
|
214
215
|
def find_record
|
215
|
-
@resource = instance_variable_set("@#{resource_name}", call_finder_chain(parent_model, self.class.member_nesting
|
216
|
+
@resource = instance_variable_set("@#{resource_name}", call_finder_chain(parent_model, self.class.member_nesting, false))
|
216
217
|
end
|
217
218
|
|
218
219
|
def find_records
|
219
|
-
@resources = instance_variable_set("@#{resources_name}", call_finder_chain(parent_model, self.class.collection_nesting
|
220
|
+
@resources = instance_variable_set("@#{resources_name}", call_finder_chain(parent_model, self.class.collection_nesting, false))
|
220
221
|
end
|
221
222
|
|
222
223
|
def delete_record
|
data/lib/exposure.rb
CHANGED
@@ -12,7 +12,7 @@ require 'exposure/behaviors/responding'
|
|
12
12
|
require 'exposure/patterns/resources'
|
13
13
|
|
14
14
|
module Exposure
|
15
|
-
VERSION =
|
15
|
+
VERSION = File.read(File.join(File.dirname(__FILE__), '../VERSION')).strip!.freeze
|
16
16
|
def self.included(base)
|
17
17
|
base.extend Configuration
|
18
18
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe "builders", :type => :controller do
|
4
|
+
setup = lambda {
|
5
|
+
class PiratesController < ActionController::Base
|
6
|
+
expose_many(:pirates)
|
7
|
+
private
|
8
|
+
def build_pirate
|
9
|
+
Pirate.new(params[:pirate])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
ActionController::Routing::Routes.draw do |map|
|
14
|
+
map.resources :pirates
|
15
|
+
end
|
16
|
+
}
|
17
|
+
|
18
|
+
setup.call
|
19
|
+
controller_name :pirates
|
20
|
+
Object.remove_class(PiratesController)
|
21
|
+
|
22
|
+
before(:each) do
|
23
|
+
setup.call
|
24
|
+
@controller = PiratesController.new
|
25
|
+
@request = ActionController::TestRequest.new
|
26
|
+
@response = ActionController::TestResponse.new
|
27
|
+
|
28
|
+
@pirate = Factory.stub(:pirate)
|
29
|
+
Pirate.stub(:new => @pirate)
|
30
|
+
end
|
31
|
+
|
32
|
+
after(:each) do
|
33
|
+
Object.remove_class(PiratesController)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "builds with a proc" do
|
37
|
+
PiratesController.build :pirate, :with => Proc.new { Pirate.new(params[:pirate]) }
|
38
|
+
post(:create, {:pirate => {}}).inspect
|
39
|
+
|
40
|
+
should assign_to(:pirate).with(@pirate)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "finds with a method name as symbol" do
|
44
|
+
PiratesController.build :pirate, :with => :build_pirate
|
45
|
+
post(:create, {:pirate => {}})
|
46
|
+
|
47
|
+
should assign_to(:pirate).with(@pirate)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "finds with a block" do
|
51
|
+
PiratesController.build :pirate do
|
52
|
+
Pirate.new(params[:pirate])
|
53
|
+
end
|
54
|
+
|
55
|
+
post(:create, {:pirate => {}})
|
56
|
+
|
57
|
+
should assign_to(:pirate).with(@pirate)
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe "nested builders", :type => :controller do
|
4
|
+
setup = lambda {
|
5
|
+
class ShipsController < ActionController::Base
|
6
|
+
expose_many(:ships, :nested => [:pirates])
|
7
|
+
end
|
8
|
+
|
9
|
+
ActionController::Routing::Routes.draw do |map|
|
10
|
+
map.resources :pirates do |pirate|
|
11
|
+
pirate.resources :ships
|
12
|
+
end
|
13
|
+
end
|
14
|
+
}
|
15
|
+
|
16
|
+
setup.call
|
17
|
+
controller_name :ships
|
18
|
+
Object.remove_class(ShipsController)
|
19
|
+
|
20
|
+
before(:each) do
|
21
|
+
setup.call
|
22
|
+
@controller = ShipsController.new
|
23
|
+
@request = ActionController::TestRequest.new
|
24
|
+
@response = ActionController::TestResponse.new
|
25
|
+
|
26
|
+
@pirate = Factory.create(:pirate_with_ships)
|
27
|
+
Pirate.stub(:find => @pirate)
|
28
|
+
|
29
|
+
get(:new, {:pirate_id => 1, :ship => nil})
|
30
|
+
end
|
31
|
+
|
32
|
+
after(:each) do
|
33
|
+
Object.remove_class(ShipsController)
|
34
|
+
end
|
35
|
+
|
36
|
+
it { should assign_to(:ship) }
|
37
|
+
it { should assign_to(:resource) }
|
38
|
+
|
39
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exposure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Trek Glowacki
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-10
|
12
|
+
date: 2009-11-10 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -39,6 +39,8 @@ files:
|
|
39
39
|
- script/console
|
40
40
|
- script/destroy
|
41
41
|
- script/generate
|
42
|
+
- spec/builders/builder_spec.rb
|
43
|
+
- spec/builders/nested_builder_spec.rb
|
42
44
|
- spec/callbacks_spec.rb
|
43
45
|
- spec/configuration_spec.rb
|
44
46
|
- spec/custom_matchers.rb
|
@@ -99,6 +101,8 @@ signing_key:
|
|
99
101
|
specification_version: 3
|
100
102
|
summary: exposed resources
|
101
103
|
test_files:
|
104
|
+
- spec/builders/builder_spec.rb
|
105
|
+
- spec/builders/nested_builder_spec.rb
|
102
106
|
- spec/callbacks_spec.rb
|
103
107
|
- spec/configuration_spec.rb
|
104
108
|
- spec/custom_matchers.rb
|