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 CHANGED
@@ -1 +1 @@
1
- 0.0.7
1
+ 0.1.0
@@ -12,24 +12,62 @@ module Exposure
12
12
  end
13
13
 
14
14
  def build_default_builder(member, nesting)
15
- self::const_set(:DefaultBuilder, {
16
- self.resource_name.intern => Proc.new { [:new, params[resource_name] ] }
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)
@@ -25,6 +25,7 @@ module Exposure
25
25
 
26
26
  include ActiveSupport::Callbacks
27
27
  include Exposure::Finding
28
+ include Exposure::Building
28
29
  include Exposure::Flashing
29
30
  include Exposure::Responding
30
31
  include Exposure::Callbacks
@@ -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
- true
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.new(params[resource_name]))
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.clone, false))
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.clone, false))
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 = '0.0.6'
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.7
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-26 00:00:00 -04:00
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