puffer 0.0.1 → 0.0.2

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.
Files changed (85) hide show
  1. data/.rspec +1 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +130 -0
  5. data/Rakefile +3 -2
  6. data/VERSION +1 -0
  7. data/app/views/layouts/puffer.html.erb +38 -0
  8. data/app/views/puffer/_form.html.erb +19 -0
  9. data/app/views/puffer/associated/_many.html.erb +56 -0
  10. data/app/views/puffer/associated/_one.html.erb +47 -0
  11. data/app/views/puffer/associated/many.rjs +1 -0
  12. data/app/views/puffer/associated/one.rjs +1 -0
  13. data/app/views/puffer/association/_many.html.erb +7 -0
  14. data/app/views/puffer/association/_one.html.erb +16 -0
  15. data/app/views/puffer/edit.html.erb +20 -0
  16. data/app/views/puffer/index.html.erb +83 -0
  17. data/app/views/puffer/new.html.erb +18 -0
  18. data/app/views/puffer/show.html.erb +29 -0
  19. data/app/views/puffer/toggle.rjs +1 -0
  20. data/autotest/discover.rb +2 -0
  21. data/puffer.gemspec +217 -0
  22. data/spec/dummy/Rakefile +7 -0
  23. data/spec/dummy/app/controllers/admin/categories_controller.rb +3 -0
  24. data/spec/dummy/app/controllers/admin/posts_controller.rb +3 -0
  25. data/spec/dummy/app/controllers/admin/profiles_controller.rb +3 -0
  26. data/spec/dummy/app/controllers/admin/tags_controller.rb +3 -0
  27. data/spec/dummy/app/controllers/admin/users_controller.rb +13 -0
  28. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  29. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  30. data/spec/dummy/app/models/category.rb +4 -0
  31. data/spec/dummy/app/models/post.rb +7 -0
  32. data/spec/dummy/app/models/post_category.rb +4 -0
  33. data/spec/dummy/app/models/profile.rb +5 -0
  34. data/spec/dummy/app/models/tag.rb +3 -0
  35. data/spec/dummy/app/models/tagging.rb +4 -0
  36. data/spec/dummy/app/models/user.rb +4 -0
  37. data/spec/dummy/app/views/admin/users/index.html.erb +0 -0
  38. data/spec/dummy/config.ru +4 -0
  39. data/spec/dummy/config/application.rb +45 -0
  40. data/spec/dummy/config/boot.rb +10 -0
  41. data/spec/dummy/config/database.yml +22 -0
  42. data/spec/dummy/config/environment.rb +5 -0
  43. data/spec/dummy/config/environments/development.rb +26 -0
  44. data/spec/dummy/config/environments/production.rb +49 -0
  45. data/spec/dummy/config/environments/test.rb +35 -0
  46. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  47. data/spec/dummy/config/initializers/inflections.rb +10 -0
  48. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  49. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  50. data/spec/dummy/config/initializers/session_store.rb +8 -0
  51. data/spec/dummy/config/locales/en.yml +5 -0
  52. data/spec/dummy/config/routes.rb +81 -0
  53. data/spec/dummy/db/migrate/20100930132559_create_admin_users.rb +14 -0
  54. data/spec/dummy/db/migrate/20100930132656_create_admin_posts.rb +15 -0
  55. data/spec/dummy/db/migrate/20100930132726_create_admin_categories.rb +13 -0
  56. data/spec/dummy/db/migrate/20100930132837_create_post_categories.rb +14 -0
  57. data/spec/dummy/db/migrate/20100930133425_create_admin_profiles.rb +16 -0
  58. data/spec/dummy/db/migrate/20101011155830_create_tags.rb +13 -0
  59. data/spec/dummy/db/migrate/20101011160326_create_taggings.rb +16 -0
  60. data/spec/dummy/db/schema.rb +68 -0
  61. data/spec/dummy/public/404.html +26 -0
  62. data/spec/dummy/public/422.html +26 -0
  63. data/spec/dummy/public/500.html +26 -0
  64. data/spec/dummy/public/favicon.ico +0 -0
  65. data/spec/dummy/public/javascripts/application.js +2 -0
  66. data/spec/dummy/public/javascripts/controls.js +965 -0
  67. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  68. data/spec/dummy/public/javascripts/effects.js +1123 -0
  69. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  70. data/spec/dummy/public/javascripts/rails.js +175 -0
  71. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  72. data/spec/dummy/script/rails +6 -0
  73. data/spec/fabricators/categories_fabricator.rb +3 -0
  74. data/spec/fabricators/posts_fabricator.rb +8 -0
  75. data/spec/fabricators/profiles_fabricator.rb +9 -0
  76. data/spec/fabricators/tags_fabricator.rb +3 -0
  77. data/spec/fabricators/users_fabricator.rb +12 -0
  78. data/spec/integration/navigation_spec.rb +9 -0
  79. data/spec/lib/params_spec.rb +119 -0
  80. data/spec/lib/render_fallback_spec.rb +17 -0
  81. data/spec/lib/resource/routing_spec.rb +67 -0
  82. data/spec/lib/resource_spec.rb +198 -0
  83. data/spec/puffer_spec.rb +7 -0
  84. data/spec/spec_helper.rb +34 -0
  85. metadata +283 -26
@@ -0,0 +1,175 @@
1
+ (function() {
2
+ // Technique from Juriy Zaytsev
3
+ // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
4
+ function isEventSupported(eventName) {
5
+ var el = document.createElement('div');
6
+ eventName = 'on' + eventName;
7
+ var isSupported = (eventName in el);
8
+ if (!isSupported) {
9
+ el.setAttribute(eventName, 'return;');
10
+ isSupported = typeof el[eventName] == 'function';
11
+ }
12
+ el = null;
13
+ return isSupported;
14
+ }
15
+
16
+ function isForm(element) {
17
+ return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM'
18
+ }
19
+
20
+ function isInput(element) {
21
+ if (Object.isElement(element)) {
22
+ var name = element.nodeName.toUpperCase()
23
+ return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA'
24
+ }
25
+ else return false
26
+ }
27
+
28
+ var submitBubbles = isEventSupported('submit'),
29
+ changeBubbles = isEventSupported('change')
30
+
31
+ if (!submitBubbles || !changeBubbles) {
32
+ // augment the Event.Handler class to observe custom events when needed
33
+ Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap(
34
+ function(init, element, eventName, selector, callback) {
35
+ init(element, eventName, selector, callback)
36
+ // is the handler being attached to an element that doesn't support this event?
37
+ if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) ||
38
+ (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) {
39
+ // "submit" => "emulated:submit"
40
+ this.eventName = 'emulated:' + this.eventName
41
+ }
42
+ }
43
+ )
44
+ }
45
+
46
+ if (!submitBubbles) {
47
+ // discover forms on the page by observing focus events which always bubble
48
+ document.on('focusin', 'form', function(focusEvent, form) {
49
+ // special handler for the real "submit" event (one-time operation)
50
+ if (!form.retrieve('emulated:submit')) {
51
+ form.on('submit', function(submitEvent) {
52
+ var emulated = form.fire('emulated:submit', submitEvent, true)
53
+ // if custom event received preventDefault, cancel the real one too
54
+ if (emulated.returnValue === false) submitEvent.preventDefault()
55
+ })
56
+ form.store('emulated:submit', true)
57
+ }
58
+ })
59
+ }
60
+
61
+ if (!changeBubbles) {
62
+ // discover form inputs on the page
63
+ document.on('focusin', 'input, select, texarea', function(focusEvent, input) {
64
+ // special handler for real "change" events
65
+ if (!input.retrieve('emulated:change')) {
66
+ input.on('change', function(changeEvent) {
67
+ input.fire('emulated:change', changeEvent, true)
68
+ })
69
+ input.store('emulated:change', true)
70
+ }
71
+ })
72
+ }
73
+
74
+ function handleRemote(element) {
75
+ var method, url, params;
76
+
77
+ var event = element.fire("ajax:before");
78
+ if (event.stopped) return false;
79
+
80
+ if (element.tagName.toLowerCase() === 'form') {
81
+ method = element.readAttribute('method') || 'post';
82
+ url = element.readAttribute('action');
83
+ params = element.serialize();
84
+ } else {
85
+ method = element.readAttribute('data-method') || 'get';
86
+ url = element.readAttribute('href');
87
+ params = {};
88
+ }
89
+
90
+ new Ajax.Request(url, {
91
+ method: method,
92
+ parameters: params,
93
+ evalScripts: true,
94
+
95
+ onComplete: function(request) { element.fire("ajax:complete", request); },
96
+ onSuccess: function(request) { element.fire("ajax:success", request); },
97
+ onFailure: function(request) { element.fire("ajax:failure", request); }
98
+ });
99
+
100
+ element.fire("ajax:after");
101
+ }
102
+
103
+ function handleMethod(element) {
104
+ var method = element.readAttribute('data-method'),
105
+ url = element.readAttribute('href'),
106
+ csrf_param = $$('meta[name=csrf-param]')[0],
107
+ csrf_token = $$('meta[name=csrf-token]')[0];
108
+
109
+ var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
110
+ element.parentNode.insert(form);
111
+
112
+ if (method !== 'post') {
113
+ var field = new Element('input', { type: 'hidden', name: '_method', value: method });
114
+ form.insert(field);
115
+ }
116
+
117
+ if (csrf_param) {
118
+ var param = csrf_param.readAttribute('content'),
119
+ token = csrf_token.readAttribute('content'),
120
+ field = new Element('input', { type: 'hidden', name: param, value: token });
121
+ form.insert(field);
122
+ }
123
+
124
+ form.submit();
125
+ }
126
+
127
+
128
+ document.on("click", "*[data-confirm]", function(event, element) {
129
+ var message = element.readAttribute('data-confirm');
130
+ if (!confirm(message)) event.stop();
131
+ });
132
+
133
+ document.on("click", "a[data-remote]", function(event, element) {
134
+ if (event.stopped) return;
135
+ handleRemote(element);
136
+ event.stop();
137
+ });
138
+
139
+ document.on("click", "a[data-method]", function(event, element) {
140
+ if (event.stopped) return;
141
+ handleMethod(element);
142
+ event.stop();
143
+ });
144
+
145
+ document.on("submit", function(event) {
146
+ var element = event.findElement(),
147
+ message = element.readAttribute('data-confirm');
148
+ if (message && !confirm(message)) {
149
+ event.stop();
150
+ return false;
151
+ }
152
+
153
+ var inputs = element.select("input[type=submit][data-disable-with]");
154
+ inputs.each(function(input) {
155
+ input.disabled = true;
156
+ input.writeAttribute('data-original-value', input.value);
157
+ input.value = input.readAttribute('data-disable-with');
158
+ });
159
+
160
+ var element = event.findElement("form[data-remote]");
161
+ if (element) {
162
+ handleRemote(element);
163
+ event.stop();
164
+ }
165
+ });
166
+
167
+ document.on("ajax:after", "form", function(event, element) {
168
+ var inputs = element.select("input[type=submit][disabled=true][data-disable-with]");
169
+ inputs.each(function(input) {
170
+ input.value = input.readAttribute('data-original-value');
171
+ input.removeAttribute('data-original-value');
172
+ input.disabled = false;
173
+ });
174
+ });
175
+ })();
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,3 @@
1
+ Fabricator :category do
2
+ title { Forgery::LoremIpsum.word }
3
+ end
@@ -0,0 +1,8 @@
1
+ Fabricator :post do
2
+ title { Forgery::LoremIpsum.sentence }
3
+ body { Forgery::LoremIpsum.paragraphs 3 }
4
+ end
5
+
6
+ Fabricator :post_with_categories, :from => :post do
7
+ categories!(:count => 2) { |post, i| Fabricate(:category, :posts => [post]) }
8
+ end
@@ -0,0 +1,9 @@
1
+ Fabricator :profile do
2
+ name { Forgery::Name.first_name }
3
+ surname { Forgery::Name.last_name }
4
+ birth_date { Date.current }
5
+ end
6
+
7
+ Fabricator :profile_with_tags, :from => :profile do
8
+ tags!(:count => 3) { |profile, i| Fabricate :tag }
9
+ end
@@ -0,0 +1,3 @@
1
+ Fabricator :tag do
2
+ name { Forgery::LoremIpsum.word }
3
+ end
@@ -0,0 +1,12 @@
1
+ Fabricator :user do
2
+ email {Forgery::Internet.email_address}
3
+ password '123456'
4
+ end
5
+
6
+ Fabricator :user_with_profile, :from => :user do
7
+ profile! { Fabricate :profile }
8
+ end
9
+
10
+ Fabricator :user_with_profile_and_tags, :from => :user do
11
+ profile! { Fabricate :profile_with_tags }
12
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Navigation" do
4
+ include Capybara
5
+
6
+ it "should be a valid app" do
7
+ ::Rails.application.should be_a(Dummy::Application)
8
+ end
9
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Params" do
4
+
5
+ include RSpec::Rails::RequestExampleGroup
6
+
7
+ =begin
8
+ params_examples = [
9
+ [:admin_users_url, true, [], [:profile, :posts]]
10
+ ]
11
+
12
+ params_examples.each do |(url, plural, ancestors, children)|
13
+ describe "GET #{url}" do
14
+ it "should set proper params" do
15
+ get send(url)
16
+
17
+ request.params[:plural].should == plural
18
+ request.params[:ancestors].should == ancestors
19
+ request.params[:children].should == children
20
+ end
21
+ end
22
+ end
23
+ =end
24
+
25
+ before :each do
26
+ @resource = mock(Puffer::Resource, :collection => [], :member => nil, :template => {:nothing => true})
27
+ Puffer::Resource.stub(:new) {@resource}
28
+ end
29
+
30
+ describe "GET /admin/users" do
31
+ it "should set proper params" do
32
+ get admin_users_url
33
+
34
+ request.params[:plural].should be_true
35
+ request.params[:ancestors].should == []
36
+ request.params[:children].should == [:profile, :posts]
37
+ end
38
+ end
39
+
40
+ describe "GET /admin/users/1/profile" do
41
+ it "should set proper params" do
42
+ get admin_user_profile_url(1)
43
+
44
+ request.params[:plural].should be_false
45
+ request.params[:ancestors].should == [:users]
46
+ request.params[:children].should == [:tags]
47
+ end
48
+ end
49
+
50
+ describe "get /admin/users/1/posts" do
51
+ it "should set proper params" do
52
+ get admin_user_posts_url(1)
53
+
54
+ request.params[:plural].should be_true
55
+ request.params[:ancestors].should == [:users]
56
+ request.params[:children].should == [:categories, :tags]
57
+ end
58
+ end
59
+
60
+ describe "GET /admin/users/1/posts/1/categories" do
61
+ it "should set proper params" do
62
+ get admin_user_post_categories_url(1, 1)
63
+
64
+ request.params[:plural].should be_true
65
+ request.params[:ancestors].should == [:users, :posts]
66
+ request.params[:children].should == []
67
+ end
68
+ end
69
+
70
+ describe "GET /profiles" do
71
+ it "should set proper params" do
72
+ get admin_profiles_url
73
+
74
+ request.params[:plural].should be_true
75
+ request.params[:ancestors].should == []
76
+ request.params[:children].should == [:tags]
77
+ end
78
+ end
79
+
80
+ describe "GET /posts" do
81
+ it "should set proper params" do
82
+ get admin_posts_url
83
+
84
+ request.params[:plural].should be_true
85
+ request.params[:ancestors].should == []
86
+ request.params[:children].should == [:user, :categories]
87
+ end
88
+ end
89
+
90
+ describe "GET /admin/posts/1/categories" do
91
+ it "should set proper params" do
92
+ get admin_post_categories_url(1)
93
+
94
+ request.params[:plural].should be_true
95
+ request.params[:ancestors].should == [:posts]
96
+ request.params[:children].should == []
97
+ end
98
+ end
99
+
100
+ describe "GET /categories" do
101
+ it "should set proper params" do
102
+ get admin_categories_url
103
+
104
+ request.params[:plural].should be_true
105
+ request.params[:ancestors].should == []
106
+ request.params[:children].should == [:posts]
107
+ end
108
+ end
109
+
110
+ describe "GET /admin/categories/1/posts" do
111
+ it "should set proper params" do
112
+ get admin_category_posts_url(1)
113
+
114
+ request.params[:plural].should be_true
115
+ request.params[:ancestors].should == [:categories]
116
+ request.params[:children].should == []
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Rendering" do
4
+
5
+ include RSpec::Rails::RequestExampleGroup
6
+
7
+ it "should render native temptate if exists" do
8
+ get admin_users_url
9
+ response.should render_template('admin/users/index')
10
+ end
11
+
12
+ it "should fallback to puffer template if native not exists" do
13
+ get admin_posts_url
14
+ response.should render_template('puffer/index')
15
+ end
16
+
17
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Puffer::Resource do
4
+
5
+ include RSpec::Rails::RequestExampleGroup
6
+
7
+ it "regular path" do
8
+ @category = Fabricate :category
9
+ @mock_category = mock_model Category, :id => 42
10
+
11
+ get admin_category_path(@category)
12
+ resource = Puffer::Resource.new request.params.merge(:controller => 'admin/categories', :action => 'show'), request
13
+
14
+ resource.index_path.should == admin_categories_path
15
+ resource.path.should == admin_category_path(@category)
16
+ resource.path(@mock_category).should == admin_category_path(@mock_category)
17
+ resource.new_path.should == new_admin_category_path
18
+ resource.edit_path.should == edit_admin_category_path(@category)
19
+ resource.edit_path(@mock_category).should == edit_admin_category_path(@mock_category)
20
+ end
21
+
22
+ it "plural path" do
23
+ @post = Fabricate :post_with_categories
24
+ @category = @post.categories.first
25
+ @mock_category = mock_model Category, :id => 42
26
+
27
+ get admin_post_category_path(@post, @category)
28
+ resource = Puffer::Resource.new request.params.merge(:controller => 'admin/categories', :action => 'show'), request
29
+
30
+ resource.index_path.should == admin_post_categories_path(@post)
31
+ resource.path.should == admin_post_category_path(@post, @category)
32
+ resource.path(@mock_category).should == admin_post_category_path(@post, @mock_category)
33
+ resource.new_path.should == new_admin_post_category_path(@post)
34
+ resource.edit_path.should == edit_admin_post_category_path(@post, @category)
35
+ resource.edit_path(@mock_category).should == edit_admin_post_category_path(@post, @mock_category)
36
+ end
37
+
38
+ it "singular path" do
39
+ @user = Fabricate :user_with_profile
40
+ @profile = @user.profile
41
+
42
+ get admin_user_profile_path(@user)
43
+ resource = Puffer::Resource.new request.params.merge(:controller => 'admin/profiles', :action => 'show'), request
44
+
45
+ resource.index_path.should == admin_user_profile_path(@user)
46
+ resource.path.should == admin_user_profile_path(@user)
47
+ resource.new_path.should == new_admin_user_profile_path(@user)
48
+ resource.edit_path.should == edit_admin_user_profile_path(@user)
49
+ end
50
+
51
+ it "singular parent path" do
52
+ @user = Fabricate :user_with_profile_and_tags
53
+ @tag = @user.profile.tags.first
54
+ @mock_tag = mock_model Tag, :id => 42
55
+
56
+ get admin_user_profile_tag_path(@user, @tag)
57
+ resource = Puffer::Resource.new request.params.merge(:controller => 'admin/tags', :action => 'show'), request
58
+
59
+ resource.index_path.should == admin_user_profile_tags_path(@user)
60
+ resource.path.should == admin_user_profile_tag_path(@user, @tag)
61
+ resource.path(@mock_tag).should == admin_user_profile_tag_path(@user, @mock_tag)
62
+ resource.new_path.should == new_admin_user_profile_tag_path(@user)
63
+ resource.edit_path.should == edit_admin_user_profile_tag_path(@user, @tag)
64
+ resource.edit_path(@mock_tag).should == edit_admin_user_profile_tag_path(@user, @mock_tag)
65
+ end
66
+
67
+ end
@@ -0,0 +1,198 @@
1
+ require 'spec_helper'
2
+
3
+ describe Puffer::Resource do
4
+
5
+ def default_params
6
+ ActiveSupport::HashWithIndifferentAccess.new(:controller => 'admin/categories', :action => 'index', :plural => true, :ancestors => [], :children => [])
7
+ end
8
+
9
+ def plain_params
10
+ ActiveSupport::HashWithIndifferentAccess.new(:plural => true, :ancestors => [], :children => [])
11
+ end
12
+
13
+ it "no tree" do
14
+ resource = Puffer::Resource.new default_params
15
+ resource.parent.should be_nil
16
+ resource.children.should be_empty
17
+ end
18
+
19
+ it "full tree" do
20
+ resource = Puffer::Resource.new default_params.merge(:ancestors => [:posts], :children => [:users, :posts])
21
+ resource.parent.should_not be_nil
22
+ resource.ancestors.count.should == 1
23
+ resource.children.count.should == 2
24
+ end
25
+
26
+ describe "#parent" do
27
+
28
+ it "common params" do
29
+ resource = Puffer::Resource.new default_params.merge(:ancestors => [:users, :posts], :user_id => 37, :post_id => 42)
30
+ parent = resource.parent
31
+
32
+ parent.params.should == plain_params.merge(:ancestors => [:users], :user_id => 37, :id => 42)
33
+ parent.controller_name.should == 'posts'
34
+ end
35
+
36
+ end
37
+
38
+ describe "#children" do
39
+
40
+ it "common params" do
41
+ resource = Puffer::Resource.new default_params.merge(:controller => 'admin/posts', :ancestors => [:users], :children => [:categories], :user_id => 37)
42
+ child = resource.children.first
43
+
44
+ child.params.should == plain_params.merge(:ancestors => [:users, :posts], :user_id => 37)
45
+ child.controller_name.should == 'categories'
46
+ end
47
+
48
+ it "plural params" do
49
+ resource = Puffer::Resource.new default_params.merge(:controller => 'admin/users', :children => [:profile])
50
+ child = resource.children.first
51
+
52
+ child.params.should == plain_params.merge(:ancestors => [:users], :plural => false)
53
+ child.controller_name.should == 'profiles'
54
+ end
55
+
56
+ it "params with :id" do
57
+ resource = Puffer::Resource.new default_params.merge(:controller => 'admin/posts', :ancestors => [:users], :children => [:categories], :user_id => 37, :id => 42)
58
+ child = resource.children.first
59
+
60
+ child.params.should == plain_params.merge(:ancestors => [:users, :posts], :user_id => 37, :post_id => 42)
61
+ child.controller_name.should == 'categories'
62
+ end
63
+
64
+ end
65
+
66
+ describe "#collection" do
67
+
68
+ before :all do
69
+ @post = Fabricate :post_with_categories
70
+ @category = Fabricate :category
71
+ @user = Fabricate :user_with_profile_and_tags
72
+ end
73
+
74
+ it "no parent" do
75
+ resource = Puffer::Resource.new default_params
76
+
77
+ resource.collection.should == Category.limit(30).all
78
+ end
79
+
80
+ it "plural parent" do
81
+ resource = Puffer::Resource.new default_params.merge(:ancestors => [:posts], :post_id => 42)
82
+
83
+ Post.stub(:find).with(42) {@post}
84
+ resource.collection.should == @post.categories.limit(30).all
85
+ end
86
+
87
+ it "singular parent" do
88
+ resource = Puffer::Resource.new default_params.merge(:controller => 'admin/tags', :ancestors => [:users, :profile], :user_id => 42)
89
+
90
+ User.stub(:find).with(42) {@user}
91
+ resource.collection.should == @user.profile.tags.limit(30).all
92
+ end
93
+
94
+ end
95
+
96
+ describe "#member" do
97
+
98
+ before :all do
99
+ @post = Fabricate :post_with_categories
100
+ @category = Fabricate :category
101
+ @user = Fabricate :user_with_profile_and_tags
102
+ end
103
+
104
+ it "no parent" do
105
+ resource = Puffer::Resource.new default_params.merge(:id => 42)
106
+
107
+ Category.stub(:find).with(42) {@category}
108
+ resource.member.should == @category
109
+ end
110
+
111
+ it "plural parent" do
112
+ resource = Puffer::Resource.new default_params.merge(:ancestors => [:posts], :post_id => 42, :id => 37)
113
+
114
+ @categories = @post.categories
115
+
116
+ Post.stub(:find).with(42) {@post}
117
+ @categories.stub(:find).with(37) {@category}
118
+ resource.member.should == @category
119
+ end
120
+
121
+ it "singular" do
122
+ resource = Puffer::Resource.new default_params.merge(:controller => 'admin/profiles', :plural => false, :ancestors => [:users], :user_id => 42)
123
+
124
+ @profile = @user.profile
125
+
126
+ User.stub(:find).with(42) {@user}
127
+ @user.stub(:profile) {@profile}
128
+
129
+ resource.member.should == @profile
130
+ end
131
+
132
+ it "singular parent" do
133
+ resource = Puffer::Resource.new default_params.merge(:controller => 'admin/tags', :ancestors => [:users, :profile], :user_id => 42, :id => 37)
134
+
135
+ @profile = @user.profile
136
+ @tag = @profile.tags.first
137
+
138
+ User.stub(:find).with(42) {@user}
139
+ @user.stub(:profile) {@profile}
140
+ @profile.tags.stub(:find).with(37) {@tag}
141
+
142
+ resource.member.should == @tag
143
+ end
144
+
145
+ end
146
+
147
+ describe "#new_member" do
148
+
149
+ before :all do
150
+ @post = Fabricate :post_with_categories
151
+ @category = Fabricate :category
152
+ @user = Fabricate :user_with_profile_and_tags
153
+ end
154
+
155
+ it "no parent" do
156
+ resource = Puffer::Resource.new default_params
157
+
158
+ Category.stub(:new) {@category}
159
+ resource.new_member.should == @category
160
+ end
161
+
162
+ it "plural parent" do
163
+ resource = Puffer::Resource.new default_params.merge(:ancestors => [:posts], :post_id => 42)
164
+
165
+ @categories = @post.categories
166
+
167
+ Post.stub(:find).with(42) {@post}
168
+ @categories.stub(:new) {@category}
169
+ resource.new_member.should == @category
170
+ end
171
+
172
+ it "singular" do
173
+ resource = Puffer::Resource.new default_params.merge(:controller => 'admin/profiles', :plural => false, :ancestors => [:users], :user_id => 42)
174
+
175
+ @profile = @user.profile
176
+
177
+ User.stub(:find).with(42) {@user}
178
+ @user.stub(:build_profile) {@profile}
179
+
180
+ resource.new_member.should == @profile
181
+ end
182
+
183
+ it "singular parent" do
184
+ resource = Puffer::Resource.new default_params.merge(:controller => 'admin/tags', :ancestors => [:users, :profile], :user_id => 42)
185
+
186
+ @profile = @user.profile
187
+ @tag = @profile.tags.first
188
+
189
+ User.stub(:find).with(42) {@user}
190
+ @user.stub(:profile) {@profile}
191
+ @profile.tags.stub(:new) {@tag}
192
+
193
+ resource.new_member.should == @tag
194
+ end
195
+
196
+ end
197
+
198
+ end