trollied 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/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +294 -0
- data/README.rdoc +96 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/app/controllers/line_items_controller.rb +168 -0
- data/app/controllers/notes_controller.rb +121 -0
- data/app/controllers/orders_controller.rb +210 -0
- data/app/controllers/trolleys_controller.rb +26 -0
- data/app/helpers/gets_trollied_helper.rb +31 -0
- data/app/helpers/line_items_helper.rb +5 -0
- data/app/helpers/orders_helper.rb +184 -0
- data/app/models/line_item.rb +14 -0
- data/app/models/note.rb +15 -0
- data/app/models/order.rb +29 -0
- data/app/models/trolley.rb +51 -0
- data/app/views/line_items/_form.html.erb +8 -0
- data/app/views/line_items/_line_item.html.erb +12 -0
- data/app/views/line_items/new.html.erb +11 -0
- data/app/views/notes/_form.html.erb +7 -0
- data/app/views/notes/_new.html.erb +14 -0
- data/app/views/notes/_note.html.erb +4 -0
- data/app/views/notes/index.html.erb +13 -0
- data/app/views/notes/new.html.erb +5 -0
- data/app/views/orders/_date_pickers.html.erb +15 -0
- data/app/views/orders/_order.html.erb +53 -0
- data/app/views/orders/index.html.erb +22 -0
- data/app/views/orders/show.html.erb +14 -0
- data/app/views/trolleys/_orders.html.erb +13 -0
- data/app/views/trolleys/show.html.erb +16 -0
- data/config/locales/en.yml +115 -0
- data/config/routes.rb +8 -0
- data/generators/trollied_migrations/USAGE +2 -0
- data/generators/trollied_migrations/templates/line_items_migration.rb +16 -0
- data/generators/trollied_migrations/templates/notes_migration.rb +15 -0
- data/generators/trollied_migrations/templates/orders_migration.rb +15 -0
- data/generators/trollied_migrations/templates/trolleys_migration.rb +14 -0
- data/generators/trollied_migrations/trollied_migrations_generator.rb +13 -0
- data/lib/gets_trollied.rb +38 -0
- data/lib/gets_trollied_controller_helpers.rb +29 -0
- data/lib/has_trolley.rb +42 -0
- data/lib/has_trolley_controller_helpers.rb +43 -0
- data/lib/order_status.rb +121 -0
- data/lib/trollied.rb +5 -0
- data/rails/init.rb +10 -0
- data/test/full_2_3_5_app_with_tests/.gitignore +27 -0
- data/test/full_2_3_5_app_with_tests/README +1 -0
- data/test/full_2_3_5_app_with_tests/Rakefile +10 -0
- data/test/full_2_3_5_app_with_tests/app/controllers/application_controller.rb +14 -0
- data/test/full_2_3_5_app_with_tests/app/controllers/items_controller.rb +85 -0
- data/test/full_2_3_5_app_with_tests/app/controllers/user_controller.rb +2 -0
- data/test/full_2_3_5_app_with_tests/app/helpers/application_helper.rb +3 -0
- data/test/full_2_3_5_app_with_tests/app/helpers/items_helper.rb +2 -0
- data/test/full_2_3_5_app_with_tests/app/helpers/user_helper.rb +2 -0
- data/test/full_2_3_5_app_with_tests/app/models/item.rb +4 -0
- data/test/full_2_3_5_app_with_tests/app/models/user.rb +3 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/edit.html.erb +20 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/index.html.erb +22 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/new.html.erb +19 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/show.html.erb +13 -0
- data/test/full_2_3_5_app_with_tests/app/views/layouts/application.html.erb +19 -0
- data/test/full_2_3_5_app_with_tests/app/views/layouts/items.html.erb +19 -0
- data/test/full_2_3_5_app_with_tests/config/boot.rb +110 -0
- data/test/full_2_3_5_app_with_tests/config/database.yml +22 -0
- data/test/full_2_3_5_app_with_tests/config/environment.rb +57 -0
- data/test/full_2_3_5_app_with_tests/config/environments/development.rb +17 -0
- data/test/full_2_3_5_app_with_tests/config/environments/production.rb +28 -0
- data/test/full_2_3_5_app_with_tests/config/environments/test.rb +28 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/backtrace_silencers.rb +7 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/inflections.rb +10 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/mime_types.rb +5 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/new_rails_defaults.rb +21 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/session_store.rb +15 -0
- data/test/full_2_3_5_app_with_tests/config/locales/en.yml +4 -0
- data/test/full_2_3_5_app_with_tests/config/locales/fr.yml +4 -0
- data/test/full_2_3_5_app_with_tests/config/locales/zh.yml +4 -0
- data/test/full_2_3_5_app_with_tests/config/locales.yml +5 -0
- data/test/full_2_3_5_app_with_tests/config/routes.rb +8 -0
- data/test/full_2_3_5_app_with_tests/config.ru +6 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20100407010602_create_items.rb +13 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110426030509_create_users.rb +13 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110426033906_create_trolleys.rb +14 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110426033907_create_orders.rb +15 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110426033908_create_line_items.rb +16 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110615234040_create_notes.rb +15 -0
- data/test/full_2_3_5_app_with_tests/db/schema.rb +56 -0
- data/test/full_2_3_5_app_with_tests/db/seeds.rb +7 -0
- data/test/full_2_3_5_app_with_tests/doc/README_FOR_APP +2 -0
- data/test/full_2_3_5_app_with_tests/public/404.html +30 -0
- data/test/full_2_3_5_app_with_tests/public/422.html +30 -0
- data/test/full_2_3_5_app_with_tests/public/500.html +30 -0
- data/test/full_2_3_5_app_with_tests/public/favicon.ico +0 -0
- data/test/full_2_3_5_app_with_tests/public/images/rails.png +0 -0
- data/test/full_2_3_5_app_with_tests/public/index.html +275 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/application.js +2 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/controls.js +963 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/dragdrop.js +973 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/effects.js +1128 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/prototype.js +4320 -0
- data/test/full_2_3_5_app_with_tests/public/robots.txt +5 -0
- data/test/full_2_3_5_app_with_tests/public/stylesheets/scaffold.css +54 -0
- data/test/full_2_3_5_app_with_tests/script/about +4 -0
- data/test/full_2_3_5_app_with_tests/script/console +3 -0
- data/test/full_2_3_5_app_with_tests/script/dbconsole +3 -0
- data/test/full_2_3_5_app_with_tests/script/destroy +3 -0
- data/test/full_2_3_5_app_with_tests/script/generate +3 -0
- data/test/full_2_3_5_app_with_tests/script/performance/benchmarker +3 -0
- data/test/full_2_3_5_app_with_tests/script/performance/profiler +3 -0
- data/test/full_2_3_5_app_with_tests/script/plugin +3 -0
- data/test/full_2_3_5_app_with_tests/script/runner +3 -0
- data/test/full_2_3_5_app_with_tests/script/server +3 -0
- data/test/full_2_3_5_app_with_tests/test/factories.rb +22 -0
- data/test/full_2_3_5_app_with_tests/test/functional/line_items_controller_test.rb +69 -0
- data/test/full_2_3_5_app_with_tests/test/functional/orders_controller_test.rb +75 -0
- data/test/full_2_3_5_app_with_tests/test/integration/gets_trollied_test.rb +38 -0
- data/test/full_2_3_5_app_with_tests/test/integration/order_test.rb +79 -0
- data/test/full_2_3_5_app_with_tests/test/integration/trolley_test.rb +71 -0
- data/test/full_2_3_5_app_with_tests/test/performance/browsing_test.rb +9 -0
- data/test/full_2_3_5_app_with_tests/test/selenium.rb +83 -0
- data/test/full_2_3_5_app_with_tests/test/test_helper.rb +54 -0
- data/test/full_2_3_5_app_with_tests/test/unit/gets_trollied_test.rb +29 -0
- data/test/full_2_3_5_app_with_tests/test/unit/helpers/gets_trollied_helper_test.rb +75 -0
- data/test/full_2_3_5_app_with_tests/test/unit/helpers/orders_helper_test.rb +34 -0
- data/test/full_2_3_5_app_with_tests/test/unit/line_item_test.rb +28 -0
- data/test/full_2_3_5_app_with_tests/test/unit/note_test.rb +14 -0
- data/test/full_2_3_5_app_with_tests/test/unit/order_test.rb +65 -0
- data/test/full_2_3_5_app_with_tests/test/unit/trolley_test.rb +80 -0
- data/test/full_2_3_5_app_with_tests/tmp/restart.txt +0 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/init.rb +1 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/base.rb +31 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/force_extension.rb +57 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/locale.rb +70 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/pagination.rb +33 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/uuid_token.rb +78 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter.rb +94 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/force_extension_spec.rb +65 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/generation_spec.rb +367 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/pagination_extension_spec.rb +19 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/recognition_spec.rb +76 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/routing_filter_spec.rb +114 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/spec_helper.rb +108 -0
- data/test/helper.rb +10 -0
- metadata +345 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
|
|
4
|
+
class GetsTrolliedHelperTest < ActionView::TestCase
|
|
5
|
+
include HasTrolleyControllerHelpers::UrlFor
|
|
6
|
+
|
|
7
|
+
context "Helpers for stuff that gets trollied" do
|
|
8
|
+
setup do
|
|
9
|
+
@item = Factory.create(:item, :label => "a label")
|
|
10
|
+
|
|
11
|
+
@form_fragment = "form method=\"post\" action=\"/items/1/line_items\""
|
|
12
|
+
@input_fragment = "input type=\"submit\" value=\"+ Add to cart\""
|
|
13
|
+
|
|
14
|
+
def current_user
|
|
15
|
+
@current_user ||= User.first || Factory.create(:user)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
should "provide button_to_place_in_trolley that returns a form to add to cart for passed in purchasable_item" do
|
|
20
|
+
assert_has_button_in(button_to_place_in_trolley(@item))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
should "provide in_trolley_status_or_button_to_place_in_trolley that returns a form to add to cart for passed in purchasable_item when the item hasn't been added yet" do
|
|
24
|
+
assert_has_button_in(in_trolley_status_or_button_to_place_in_trolley(@item))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "should provide in_trolley_status_or_button_to_place_in_trolley that" do
|
|
28
|
+
setup do
|
|
29
|
+
@trolley = current_user.trolley
|
|
30
|
+
@trolley.add(@item)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
should "return a statement that item is in user's trolley for passed in purchasable_item when has previously been added" do
|
|
34
|
+
value = in_trolley_status_or_button_to_place_in_trolley(@item)
|
|
35
|
+
|
|
36
|
+
assert value.include?("<div class=\"in-trolley\">" +
|
|
37
|
+
t('gets_trollied_helper.in_trolley') +
|
|
38
|
+
"</div>")
|
|
39
|
+
|
|
40
|
+
assert_does_not_have_button_in(value)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context "when passed in purchasable_item has previously been added, but order has been checked out" do
|
|
44
|
+
setup do
|
|
45
|
+
@order = @trolley.selected_order
|
|
46
|
+
@order.checkout!
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
should "return a statement that item is in user's trolley " do
|
|
50
|
+
value = in_trolley_status_or_button_to_place_in_trolley(@item)
|
|
51
|
+
assert_does_not_have_button_in(value)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
should "return add to cart after the order has been moved to another state besides in_process" do
|
|
55
|
+
@order.cancel!
|
|
56
|
+
assert_has_button_in(in_trolley_status_or_button_to_place_in_trolley(@item))
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def assert_has_button_in(value)
|
|
66
|
+
assert value.include?(@form_fragment) &&
|
|
67
|
+
value.include?(@input_fragment)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def assert_does_not_have_button_in(value)
|
|
71
|
+
assert !value.include?(@form_fragment) &&
|
|
72
|
+
!value.include?(@input_fragment)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
|
|
4
|
+
class OrdersHelperTest < ActionView::TestCase
|
|
5
|
+
context "Helpers for orders" do
|
|
6
|
+
|
|
7
|
+
should "respond to button_to event method for an order for all possible events" do
|
|
8
|
+
Order.workflow_event_names.each do |event_name|
|
|
9
|
+
assert respond_to?("button_to_#{event_name}")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
should "have show_count_for method that takes a number and returns formatted string" do
|
|
14
|
+
assert_equal ' (2)', show_count_for(2)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
should "have state_links that returns a list of links to order states" do
|
|
18
|
+
@order1 = Factory.create(:order)
|
|
19
|
+
@order1.checkout!
|
|
20
|
+
|
|
21
|
+
@order2 = Factory.create(:order)
|
|
22
|
+
@order2.checkout!
|
|
23
|
+
@order2.cancel!
|
|
24
|
+
|
|
25
|
+
@order3 = Factory.create(:order)
|
|
26
|
+
|
|
27
|
+
@state = 'in_process' # default
|
|
28
|
+
|
|
29
|
+
html = "<ul id=\"state-links\" class=\"horizontal-list\"><li class=\"state-link first\">#{I18n.t('orders.index.in_process')} (1)</li><li class=\"state-link\"><a href=\"/orders?state=cancelled\">#{I18n.t('orders.index.cancelled')} (1)</a></li><li class=\"state-link\"><a href=\"/orders?state=current\">#{I18n.t('orders.index.current')} (1)</a></li></ul>"
|
|
30
|
+
|
|
31
|
+
assert_equal html, state_links
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
|
|
4
|
+
class LineItemTest < ActiveSupport::TestCase
|
|
5
|
+
context "A line_item" do
|
|
6
|
+
setup do
|
|
7
|
+
@item = Factory.create(:item)
|
|
8
|
+
|
|
9
|
+
@order = Factory.create(:order)
|
|
10
|
+
|
|
11
|
+
@order.add(@item)
|
|
12
|
+
|
|
13
|
+
@line_item = @order.line_items.first
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should "have a user through its order's user" do
|
|
17
|
+
assert_equal @order.user, @line_item.user
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "have a description_for_purchasing method" do
|
|
21
|
+
assert_respond_to @line_item, :description_for_purchasing
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
should "return the purchasable_item's purchase_description as delegated" do
|
|
25
|
+
assert_equal @item.description_for_purchasing, @line_item.description_for_purchasing
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
|
|
4
|
+
class NoteTest < ActiveSupport::TestCase
|
|
5
|
+
context "A note" do
|
|
6
|
+
setup do
|
|
7
|
+
@order = Factory.create(:order)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
should "be able to be created for an order" do
|
|
11
|
+
assert_nothing_raised { @order.notes.create!(:body => "a test note", :user => User.first) }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
|
|
4
|
+
class OrderTest < ActiveSupport::TestCase
|
|
5
|
+
context "An order" do
|
|
6
|
+
setup do
|
|
7
|
+
@item = Factory.create(:item)
|
|
8
|
+
@order = Factory.create(:order)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context "class" do
|
|
12
|
+
|
|
13
|
+
context "have a named scope 'in' that takes a state as an argument" do
|
|
14
|
+
should "return all orders if 'all' is the special case argument" do
|
|
15
|
+
assert_equal @order, Order.in('all').first
|
|
16
|
+
@order.checkout!
|
|
17
|
+
assert_equal @order, Order.in('all').first
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "return orders in that state" do
|
|
21
|
+
@order.checkout!
|
|
22
|
+
assert_equal @order, Order.in('in_process').first
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
should "have a user through its trolley's user" do
|
|
28
|
+
assert_equal @order.trolley.user, @order.user
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# test that we have integration with the workflow gem
|
|
32
|
+
should "have a workflow_state and the default is current" do
|
|
33
|
+
assert_equal 'current', @order.workflow_state
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
should "have a current_state" do
|
|
37
|
+
assert @order.respond_to?(:current_state)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
should "transition to in_process when checked out" do
|
|
41
|
+
@order.checkout!
|
|
42
|
+
# assert @order.ordered?
|
|
43
|
+
assert @order.in_process?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "after adding an item to it" do
|
|
47
|
+
setup do
|
|
48
|
+
@order.add(@item)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
should "create a line_item with the item" do
|
|
52
|
+
assert_purchasable_item_matches
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
should "return true when it contains an item" do
|
|
56
|
+
assert @order.contains?(@item)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
should "return false when it does not contain an item" do
|
|
61
|
+
assert @order.contains?(@item) == false
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
|
|
4
|
+
class TrolleyTest < ActiveSupport::TestCase
|
|
5
|
+
context "A trolley" do
|
|
6
|
+
setup do
|
|
7
|
+
@item = Factory.create(:item)
|
|
8
|
+
@trolley = Factory.create(:trolley)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context "when having an item placed in it" do
|
|
12
|
+
setup do
|
|
13
|
+
@trolley.add(@item)
|
|
14
|
+
@order = @trolley.selected_order
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
should "result in an order with a line_item for that item" do
|
|
18
|
+
assert_purchasable_item_matches
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
should "answer true for contains? method" do
|
|
22
|
+
assert @trolley.contains?(@item)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
should "return true for has_active_order_for? purchasable_item" do
|
|
26
|
+
assert @trolley.has_active_order_for?(@item)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context "and the item has already been placed in trolley, but first order has been checked out" do
|
|
30
|
+
setup do
|
|
31
|
+
@order.checkout!
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
should "answer false for contains? method when current state specified" do
|
|
35
|
+
assert @trolley.contains?(@item, :current) == false
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
should "answer true for contains? method when the item is in order with a given state" do
|
|
39
|
+
assert @trolley.contains?(@item, :in_process)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
should "have correct_order be an order that is current, not in_process order" do
|
|
43
|
+
correct_order = @trolley.correct_order(@item)
|
|
44
|
+
assert correct_order != @order
|
|
45
|
+
assert correct_order.current?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
should "return true for has_active_order_for? purchasable_item" do
|
|
49
|
+
assert @trolley.has_active_order_for?(@item)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context "and the order is then moved from in_process" do
|
|
53
|
+
should "return false for has_active_order_for? purchasable_item" do
|
|
54
|
+
@order.cancel!
|
|
55
|
+
assert !@trolley.has_active_order_for?(@item)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context "when an item is not in a trolley" do
|
|
64
|
+
should "answer false for contains? method" do
|
|
65
|
+
assert @trolley.contains?(@item) == false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
should "answer false for contains? method even if there is an order for the trolley" do
|
|
69
|
+
@trolley.selected_order
|
|
70
|
+
|
|
71
|
+
assert @trolley.contains?(@item) == false
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
should "return false for has_active_order_for? purchasable_item" do
|
|
75
|
+
assert !@trolley.has_active_order_for?(@item)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'routing_filter'
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module RoutingFilter
|
|
2
|
+
class Base
|
|
3
|
+
class_inheritable_accessor :active
|
|
4
|
+
self.active = true
|
|
5
|
+
|
|
6
|
+
attr_accessor :chain, :options
|
|
7
|
+
|
|
8
|
+
def initialize(options = {})
|
|
9
|
+
@options = options
|
|
10
|
+
options.each { |name, value| instance_variable_set :"@#{name}", value }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run(method, *args, &block)
|
|
14
|
+
_next = successor ? lambda { successor.run(method, *args, &block) } : block
|
|
15
|
+
active ? send(method, *args, &_next) : _next.call(*args)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def run_reverse(method, *args, &block)
|
|
19
|
+
_prev = predecessor ? lambda { predecessor.run(method, *args, &block) } : block
|
|
20
|
+
active ? send(method, *args, &_prev) : _prev.call(*args)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def predecessor
|
|
24
|
+
@chain.predecessor(self)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def successor
|
|
28
|
+
@chain.successor(self)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'routing_filter/base'
|
|
2
|
+
|
|
3
|
+
module RoutingFilter
|
|
4
|
+
class ForceExtension < Base
|
|
5
|
+
attr_reader :extension, :exclude
|
|
6
|
+
|
|
7
|
+
def initialize(*args)
|
|
8
|
+
super
|
|
9
|
+
@extension ||= 'html'
|
|
10
|
+
@exclude = %r(^(http.?://[^/]+)?\/?$) if @exclude.nil?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def around_recognize(path, env, &block)
|
|
14
|
+
extract_extension!(path) unless excluded?(path)
|
|
15
|
+
yield(path, env)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def around_generate(*args, &block)
|
|
19
|
+
returning yield do |result|
|
|
20
|
+
url = result.is_a?(Array) ? result.first : result
|
|
21
|
+
append_extension!(url) if append_extension?(url)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
protected
|
|
26
|
+
|
|
27
|
+
def extract_extension!(path)
|
|
28
|
+
path.sub! /\.#{extension}$/, ''
|
|
29
|
+
$1
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def append_extension?(url)
|
|
33
|
+
!(url.blank? || excluded?(url) || mime_extension?(url))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def excluded?(url)
|
|
37
|
+
case exclude
|
|
38
|
+
when Regexp
|
|
39
|
+
url =~ exclude
|
|
40
|
+
when Proc
|
|
41
|
+
exclude.call(url)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def mime_extension?(url)
|
|
46
|
+
url =~ /\.#{Mime::EXTENSION_LOOKUP.keys.join('|')}(\?|$)/
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def append_extension!(url)
|
|
50
|
+
url.replace url.sub(/(\?|$)/, ".#{extension}\\1")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def append_page!(url, page)
|
|
54
|
+
url.replace "#{url}/pages/#{page}"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/locale.rb
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require 'i18n'
|
|
2
|
+
require 'routing_filter/base'
|
|
3
|
+
|
|
4
|
+
module RoutingFilter
|
|
5
|
+
class Locale < Base
|
|
6
|
+
@@include_default_locale = true
|
|
7
|
+
cattr_writer :include_default_locale
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def include_default_locale?
|
|
11
|
+
@@include_default_locale
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def locales
|
|
15
|
+
@@locales ||= I18n.available_locales.map(&:to_sym)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def locales=(locales)
|
|
19
|
+
@@locales = locales.map(&:to_sym)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def locales_pattern
|
|
23
|
+
@@locales_pattern ||= %r(^/(#{self.locales.map { |l| Regexp.escape(l.to_s) }.join('|')})(?=/|$))
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def around_recognize(path, env, &block)
|
|
28
|
+
locale = extract_locale!(path) # remove the locale from the beginning of the path
|
|
29
|
+
returning yield do |params| # invoke the given block (calls more filters and finally routing)
|
|
30
|
+
params[:locale] = locale if locale # set recognized locale to the resulting params hash
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def around_generate(*args, &block)
|
|
35
|
+
locale = args.extract_options!.delete(:locale) # extract the passed :locale option
|
|
36
|
+
locale = I18n.locale if locale.nil? # default to I18n.locale when locale is nil (could also be false)
|
|
37
|
+
locale = nil unless valid_locale?(locale) # reset to no locale when locale is not valid
|
|
38
|
+
|
|
39
|
+
returning yield do |result|
|
|
40
|
+
if locale && prepend_locale?(locale)
|
|
41
|
+
url = result.is_a?(Array) ? result.first : result
|
|
42
|
+
prepend_locale!(url, locale)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
protected
|
|
48
|
+
|
|
49
|
+
def extract_locale!(path)
|
|
50
|
+
path.sub! self.class.locales_pattern, ''
|
|
51
|
+
$1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def prepend_locale?(locale)
|
|
55
|
+
self.class.include_default_locale? || !default_locale?(locale)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def valid_locale?(locale)
|
|
59
|
+
locale && self.class.locales.include?(locale.to_sym)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def default_locale?(locale)
|
|
63
|
+
locale && locale.to_sym == I18n.default_locale.to_sym
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def prepend_locale!(url, locale)
|
|
67
|
+
url.sub!(%r(^(http.?://[^/]*)?(.*))) { "#{$1}/#{locale}#{$2}" }
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/pagination.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'routing_filter/base'
|
|
2
|
+
|
|
3
|
+
module RoutingFilter
|
|
4
|
+
class Pagination < Base
|
|
5
|
+
def around_recognize(path, env, &block)
|
|
6
|
+
page = extract_page!(path)
|
|
7
|
+
returning yield(path, env) do |params|
|
|
8
|
+
params[:page] = page.to_i if page
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def around_generate(*args, &block)
|
|
13
|
+
page = args.extract_options!.delete(:page)
|
|
14
|
+
returning yield do |result|
|
|
15
|
+
if page && page != 1
|
|
16
|
+
url = result.is_a?(Array) ? result.first : result
|
|
17
|
+
append_page!(url, page)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
protected
|
|
23
|
+
|
|
24
|
+
def extract_page!(path)
|
|
25
|
+
path.sub! %r(/pages/([\d]+)/?$), ''
|
|
26
|
+
$1
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def append_page!(url, page)
|
|
30
|
+
url.sub!(/($|\?)/) { "/pages/#{page}#{$1}" }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/uuid_token.rb
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# This is a routing filter that extracts UUIDs from urls and exposes them via
|
|
2
|
+
# params[:uuid_token]
|
|
3
|
+
#
|
|
4
|
+
# URL scheme: http://example.com/d00fbbd1-82b6-4c1a-a57d-098d529d6854/your_route
|
|
5
|
+
#
|
|
6
|
+
# To enable this filter add map.filter :uuid_token to your routes.rb
|
|
7
|
+
#
|
|
8
|
+
# To make your restful path helpers use this :uuid_token use:
|
|
9
|
+
# new_post_path(:uuid_token => params[:uuid_token])
|
|
10
|
+
#
|
|
11
|
+
# If don't want to pass the :uuid_token manually you can add a custom module
|
|
12
|
+
# like this to your RAILS_ROOT/lib directory:
|
|
13
|
+
#
|
|
14
|
+
# module AccessToken
|
|
15
|
+
#
|
|
16
|
+
# class << self
|
|
17
|
+
# def current=(token)
|
|
18
|
+
# Thread.current[:uuid_token] = token
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# def current
|
|
22
|
+
# Thread.current[:uuid_token] ||= ""
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# end
|
|
27
|
+
#
|
|
28
|
+
# Now in your application_controller you can set a before_filter which sets that
|
|
29
|
+
# token for every request:
|
|
30
|
+
#
|
|
31
|
+
# before_filter :set_token
|
|
32
|
+
#
|
|
33
|
+
# protected
|
|
34
|
+
#
|
|
35
|
+
# def set_token
|
|
36
|
+
# AccessToken.current = params[:uuid_token] if params[:uuid_token]
|
|
37
|
+
# end
|
|
38
|
+
#
|
|
39
|
+
# As you can see below in the around_generate method, if you don't provide a
|
|
40
|
+
# :uuid_token argument for your restful path helpers it will try to get the
|
|
41
|
+
# current :uuid_token from the AccessToken module.
|
|
42
|
+
|
|
43
|
+
require 'routing_filter/base'
|
|
44
|
+
|
|
45
|
+
module RoutingFilter
|
|
46
|
+
class UuidToken < Base
|
|
47
|
+
|
|
48
|
+
def around_recognize(path, env, &block)
|
|
49
|
+
token = extract_token!(path) # remove the token from the beginning of the path
|
|
50
|
+
returning yield do |params| # invoke the given block (calls more filters and finally routing)
|
|
51
|
+
params[:uuid_token] = token if token # set recognized token to the resulting params hash
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def around_generate(*args, &block)
|
|
56
|
+
token = args.extract_options!.delete(:uuid_token) # extract the passed :token option
|
|
57
|
+
token = AccessToken.current if AccessToken && token.nil? # default to AccessToken.current when token is nil (could also be false)
|
|
58
|
+
|
|
59
|
+
returning yield do |result|
|
|
60
|
+
if token
|
|
61
|
+
url = result.is_a?(Array) ? result.first : result
|
|
62
|
+
prepend_token!(url, token)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
protected
|
|
68
|
+
|
|
69
|
+
def extract_token!(path)
|
|
70
|
+
path.sub! /([a-z\d]{8}\-[a-z\d]{4}\-[a-z\d]{4}\-[a-z\d]{4}\-[a-z\d]{12})\//, ''
|
|
71
|
+
$1
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def prepend_token!(url, token)
|
|
75
|
+
url.sub!(%r(^(http.?://[^/]*)?(.*))) { "#{$1}/#{token}#{$2}" }
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
module RoutingFilter
|
|
2
|
+
mattr_accessor :active
|
|
3
|
+
@@active = true
|
|
4
|
+
|
|
5
|
+
class Chain < Array
|
|
6
|
+
def << (filter)
|
|
7
|
+
filter.chain = self
|
|
8
|
+
super
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def run(method, *args, &final)
|
|
12
|
+
RoutingFilter.active && !first.nil? ? first.run(method, *args, &final) : final.call
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def run_reverse(method, *args, &final)
|
|
16
|
+
RoutingFilter.active && !last.nil? ? last.run_reverse(method, *args, &final) : final.call
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def predecessor(filter)
|
|
20
|
+
ix = index(filter)
|
|
21
|
+
ix > 0 ? self[ix - 1] : nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def successor(filter)
|
|
25
|
+
ix = index(filter)
|
|
26
|
+
ix < length - 1 ? self[ix + 1] : nil
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# allows to install a filter to the route set by calling: map.filter 'locale'
|
|
32
|
+
ActionController::Routing::RouteSet::Mapper.class_eval do
|
|
33
|
+
def filter(name, options = {})
|
|
34
|
+
require options.delete(:file) || "routing_filter/#{name}"
|
|
35
|
+
klass = RoutingFilter.const_get(name.to_s.camelize)
|
|
36
|
+
@set.filters << klass.new(options)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# same here for the optimized url generation in named routes
|
|
41
|
+
ActionController::Routing::RouteSet::NamedRouteCollection.class_eval do
|
|
42
|
+
# gosh. monkey engineering optimization code
|
|
43
|
+
def generate_optimisation_block_with_filtering(*args)
|
|
44
|
+
code = generate_optimisation_block_without_filtering(*args)
|
|
45
|
+
if match = code.match(%r(^return (.*) if (.*)))
|
|
46
|
+
# returned string must not contain newlines, or we'll spill out of inline code comments in
|
|
47
|
+
# ActionController::Routing::RouteSet::NamedRouteCollection#define_url_helper
|
|
48
|
+
"returning(#{match[1]}) { |result|" +
|
|
49
|
+
" ActionController::Routing::Routes.filters.run_reverse(:around_generate, *args, &lambda{ result }) " +
|
|
50
|
+
"} if #{match[2]}"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
alias_method_chain :generate_optimisation_block, :filtering
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
ActionController::Routing::RouteSet.class_eval do
|
|
57
|
+
def clear_with_filtering!
|
|
58
|
+
@filters.clear if @filters
|
|
59
|
+
clear_without_filtering!
|
|
60
|
+
end
|
|
61
|
+
alias_method_chain :clear!, :filtering
|
|
62
|
+
|
|
63
|
+
attr_writer :filters
|
|
64
|
+
|
|
65
|
+
def filters
|
|
66
|
+
@filters ||= RoutingFilter::Chain.new
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def recognize_path_with_filtering(path, env = {})
|
|
70
|
+
path = ::URI.unescape(path.dup) # string is frozen due to memoize
|
|
71
|
+
filters.run(:around_recognize, path, env, &lambda{ recognize_path_without_filtering(path, env) })
|
|
72
|
+
end
|
|
73
|
+
alias_method_chain :recognize_path, :filtering
|
|
74
|
+
|
|
75
|
+
def generate_with_filtering(*args)
|
|
76
|
+
filters.run_reverse(:around_generate, args.first, &lambda{ generate_without_filtering(*args) })
|
|
77
|
+
end
|
|
78
|
+
alias_method_chain :generate, :filtering
|
|
79
|
+
|
|
80
|
+
# add some useful information to the request environment
|
|
81
|
+
# right, this is from jamis buck's excellent article about routes internals
|
|
82
|
+
# http://weblog.jamisbuck.org/2006/10/26/monkey-patching-rails-extending-routes-2
|
|
83
|
+
# TODO move this ... where?
|
|
84
|
+
alias_method :extract_request_environment_without_host, :extract_request_environment unless method_defined? :extract_request_environment_without_host
|
|
85
|
+
def extract_request_environment(request)
|
|
86
|
+
returning extract_request_environment_without_host(request) do |env|
|
|
87
|
+
env.merge! :host => request.host,
|
|
88
|
+
:port => request.port,
|
|
89
|
+
:host_with_port => request.host_with_port,
|
|
90
|
+
:domain => request.domain,
|
|
91
|
+
:subdomain => request.subdomains.first
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|