active_cached_resource 0.0.1.pre
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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +22 -0
- data/.standard.yml +2 -0
- data/CHANGELOG.md +5 -0
- data/README.md +45 -0
- data/Rakefile +21 -0
- data/example/consumer/.dockerignore +41 -0
- data/example/consumer/.gitattributes +9 -0
- data/example/consumer/.gitignore +36 -0
- data/example/consumer/.kamal/hooks/docker-setup.sample +3 -0
- data/example/consumer/.kamal/hooks/post-deploy.sample +14 -0
- data/example/consumer/.kamal/hooks/post-proxy-reboot.sample +3 -0
- data/example/consumer/.kamal/hooks/pre-build.sample +51 -0
- data/example/consumer/.kamal/hooks/pre-connect.sample +47 -0
- data/example/consumer/.kamal/hooks/pre-deploy.sample +109 -0
- data/example/consumer/.kamal/hooks/pre-proxy-reboot.sample +3 -0
- data/example/consumer/.kamal/secrets +17 -0
- data/example/consumer/Dockerfile +65 -0
- data/example/consumer/Gemfile +17 -0
- data/example/consumer/Rakefile +6 -0
- data/example/consumer/app/controllers/application_controller.rb +2 -0
- data/example/consumer/app/controllers/concerns/.keep +0 -0
- data/example/consumer/app/jobs/application_job.rb +7 -0
- data/example/consumer/app/mailers/application_mailer.rb +4 -0
- data/example/consumer/app/models/application_record.rb +3 -0
- data/example/consumer/app/models/concerns/.keep +0 -0
- data/example/consumer/app/models/person.rb +9 -0
- data/example/consumer/app/views/layouts/mailer.html.erb +13 -0
- data/example/consumer/app/views/layouts/mailer.text.erb +1 -0
- data/example/consumer/bin/brakeman +7 -0
- data/example/consumer/bin/bundle +109 -0
- data/example/consumer/bin/dev +2 -0
- data/example/consumer/bin/docker-entrypoint +14 -0
- data/example/consumer/bin/jobs +6 -0
- data/example/consumer/bin/kamal +27 -0
- data/example/consumer/bin/rails +4 -0
- data/example/consumer/bin/rake +4 -0
- data/example/consumer/bin/rubocop +8 -0
- data/example/consumer/bin/setup +34 -0
- data/example/consumer/bin/thrust +5 -0
- data/example/consumer/config/application.rb +20 -0
- data/example/consumer/config/boot.rb +3 -0
- data/example/consumer/config/cache.yml +16 -0
- data/example/consumer/config/credentials.yml.enc +1 -0
- data/example/consumer/config/database.yml +14 -0
- data/example/consumer/config/deploy.yml +116 -0
- data/example/consumer/config/environment.rb +5 -0
- data/example/consumer/config/environments/development.rb +64 -0
- data/example/consumer/config/environments/production.rb +85 -0
- data/example/consumer/config/environments/test.rb +50 -0
- data/example/consumer/config/initializers/cors.rb +16 -0
- data/example/consumer/config/initializers/filter_parameter_logging.rb +8 -0
- data/example/consumer/config/initializers/inflections.rb +16 -0
- data/example/consumer/config/locales/en.yml +31 -0
- data/example/consumer/config/puma.rb +41 -0
- data/example/consumer/config/queue.yml +18 -0
- data/example/consumer/config/recurring.yml +10 -0
- data/example/consumer/config/routes.rb +10 -0
- data/example/consumer/config.ru +6 -0
- data/example/consumer/db/cache_schema.rb +14 -0
- data/example/consumer/db/queue_schema.rb +129 -0
- data/example/consumer/db/seeds.rb +0 -0
- data/example/consumer/lib/tasks/.keep +0 -0
- data/example/consumer/log/.keep +0 -0
- data/example/consumer/public/robots.txt +1 -0
- data/example/consumer/script/.keep +0 -0
- data/example/consumer/storage/.keep +0 -0
- data/example/consumer/tmp/.keep +0 -0
- data/example/consumer/tmp/cache/.keep +0 -0
- data/example/consumer/tmp/pids/.keep +0 -0
- data/example/consumer/tmp/storage/.keep +0 -0
- data/example/consumer/vendor/.keep +0 -0
- data/example/provider/.dockerignore +41 -0
- data/example/provider/.gitattributes +9 -0
- data/example/provider/.gitignore +32 -0
- data/example/provider/.kamal/hooks/docker-setup.sample +3 -0
- data/example/provider/.kamal/hooks/post-deploy.sample +14 -0
- data/example/provider/.kamal/hooks/post-proxy-reboot.sample +3 -0
- data/example/provider/.kamal/hooks/pre-build.sample +51 -0
- data/example/provider/.kamal/hooks/pre-connect.sample +47 -0
- data/example/provider/.kamal/hooks/pre-deploy.sample +109 -0
- data/example/provider/.kamal/hooks/pre-proxy-reboot.sample +3 -0
- data/example/provider/.kamal/secrets +17 -0
- data/example/provider/Dockerfile +65 -0
- data/example/provider/Gemfile +14 -0
- data/example/provider/Rakefile +6 -0
- data/example/provider/app/controllers/application_controller.rb +2 -0
- data/example/provider/app/controllers/concerns/.keep +0 -0
- data/example/provider/app/controllers/people_controller.rb +68 -0
- data/example/provider/app/jobs/application_job.rb +7 -0
- data/example/provider/app/mailers/application_mailer.rb +4 -0
- data/example/provider/app/models/address.rb +3 -0
- data/example/provider/app/models/application_record.rb +3 -0
- data/example/provider/app/models/company.rb +3 -0
- data/example/provider/app/models/concerns/.keep +0 -0
- data/example/provider/app/models/person.rb +6 -0
- data/example/provider/app/views/layouts/mailer.html.erb +13 -0
- data/example/provider/app/views/layouts/mailer.text.erb +1 -0
- data/example/provider/bin/brakeman +7 -0
- data/example/provider/bin/bundle +109 -0
- data/example/provider/bin/dev +2 -0
- data/example/provider/bin/docker-entrypoint +14 -0
- data/example/provider/bin/jobs +6 -0
- data/example/provider/bin/kamal +27 -0
- data/example/provider/bin/rails +4 -0
- data/example/provider/bin/rake +4 -0
- data/example/provider/bin/rubocop +8 -0
- data/example/provider/bin/setup +34 -0
- data/example/provider/bin/thrust +5 -0
- data/example/provider/config/application.rb +44 -0
- data/example/provider/config/boot.rb +3 -0
- data/example/provider/config/cache.yml +16 -0
- data/example/provider/config/credentials.yml.enc +1 -0
- data/example/provider/config/database.yml +20 -0
- data/example/provider/config/deploy.yml +116 -0
- data/example/provider/config/environment.rb +5 -0
- data/example/provider/config/environments/development.rb +64 -0
- data/example/provider/config/environments/production.rb +85 -0
- data/example/provider/config/environments/test.rb +50 -0
- data/example/provider/config/initializers/cors.rb +16 -0
- data/example/provider/config/initializers/filter_parameter_logging.rb +8 -0
- data/example/provider/config/initializers/inflections.rb +16 -0
- data/example/provider/config/locales/en.yml +31 -0
- data/example/provider/config/puma.rb +41 -0
- data/example/provider/config/queue.yml +18 -0
- data/example/provider/config/recurring.yml +10 -0
- data/example/provider/config/routes.rb +4 -0
- data/example/provider/config.ru +6 -0
- data/example/provider/db/cache_schema.rb +14 -0
- data/example/provider/db/migrate/20241202183937_create_people.rb +11 -0
- data/example/provider/db/migrate/20241202183955_create_addresses.rb +13 -0
- data/example/provider/db/migrate/20241202184017_create_companies.rb +14 -0
- data/example/provider/db/queue_schema.rb +129 -0
- data/example/provider/db/schema.rb +47 -0
- data/example/provider/db/seeds.rb +18 -0
- data/example/provider/lib/tasks/.keep +0 -0
- data/example/provider/log/.keep +0 -0
- data/example/provider/public/robots.txt +1 -0
- data/example/provider/script/.keep +0 -0
- data/example/provider/storage/.keep +0 -0
- data/example/provider/tmp/.keep +0 -0
- data/example/provider/tmp/pids/.keep +0 -0
- data/example/provider/tmp/storage/.keep +0 -0
- data/example/provider/vendor/.keep +0 -0
- data/lib/active_cached_resource/caching.rb +176 -0
- data/lib/active_cached_resource/caching_strategies/active_support_cache.rb +31 -0
- data/lib/active_cached_resource/caching_strategies/base.rb +114 -0
- data/lib/active_cached_resource/caching_strategies/sql_cache.rb +32 -0
- data/lib/active_cached_resource/configuration.rb +50 -0
- data/lib/active_cached_resource/logger.rb +22 -0
- data/lib/active_cached_resource/model.rb +33 -0
- data/lib/active_cached_resource/version.rb +12 -0
- data/lib/active_cached_resource.rb +64 -0
- data/lib/activeresource/.gitignore +15 -0
- data/lib/activeresource/README.md +283 -0
- data/lib/activeresource/examples/performance.rb +72 -0
- data/lib/activeresource/lib/active_resource/active_job_serializer.rb +26 -0
- data/lib/activeresource/lib/active_resource/associations/builder/association.rb +32 -0
- data/lib/activeresource/lib/active_resource/associations/builder/belongs_to.rb +16 -0
- data/lib/activeresource/lib/active_resource/associations/builder/has_many.rb +14 -0
- data/lib/activeresource/lib/active_resource/associations/builder/has_one.rb +14 -0
- data/lib/activeresource/lib/active_resource/associations.rb +175 -0
- data/lib/activeresource/lib/active_resource/base.rb +1741 -0
- data/lib/activeresource/lib/active_resource/callbacks.rb +22 -0
- data/lib/activeresource/lib/active_resource/collection.rb +214 -0
- data/lib/activeresource/lib/active_resource/connection.rb +298 -0
- data/lib/activeresource/lib/active_resource/custom_methods.rb +129 -0
- data/lib/activeresource/lib/active_resource/exceptions.rb +98 -0
- data/lib/activeresource/lib/active_resource/formats/json_format.rb +28 -0
- data/lib/activeresource/lib/active_resource/formats/xml_format.rb +27 -0
- data/lib/activeresource/lib/active_resource/formats.rb +24 -0
- data/lib/activeresource/lib/active_resource/http_mock.rb +386 -0
- data/lib/activeresource/lib/active_resource/inheriting_hash.rb +34 -0
- data/lib/activeresource/lib/active_resource/log_subscriber.rb +26 -0
- data/lib/activeresource/lib/active_resource/railtie.rb +31 -0
- data/lib/activeresource/lib/active_resource/reflection.rb +78 -0
- data/lib/activeresource/lib/active_resource/schema.rb +60 -0
- data/lib/activeresource/lib/active_resource/singleton.rb +111 -0
- data/lib/activeresource/lib/active_resource/threadsafe_attributes.rb +65 -0
- data/lib/activeresource/lib/active_resource/validations.rb +176 -0
- data/lib/activeresource/lib/active_resource.rb +49 -0
- data/lib/activeresource/lib/activeresource.rb +3 -0
- data/lib/activeresource/test/abstract_unit.rb +153 -0
- data/lib/activeresource/test/cases/active_job_serializer_test.rb +53 -0
- data/lib/activeresource/test/cases/association_test.rb +104 -0
- data/lib/activeresource/test/cases/associations/builder/belongs_to_test.rb +42 -0
- data/lib/activeresource/test/cases/associations/builder/has_many_test.rb +28 -0
- data/lib/activeresource/test/cases/associations/builder/has_one_test.rb +28 -0
- data/lib/activeresource/test/cases/authorization_test.rb +276 -0
- data/lib/activeresource/test/cases/base/custom_methods_test.rb +155 -0
- data/lib/activeresource/test/cases/base/equality_test.rb +53 -0
- data/lib/activeresource/test/cases/base/load_test.rb +249 -0
- data/lib/activeresource/test/cases/base/schema_test.rb +428 -0
- data/lib/activeresource/test/cases/base_errors_test.rb +129 -0
- data/lib/activeresource/test/cases/base_test.rb +1622 -0
- data/lib/activeresource/test/cases/callbacks_test.rb +155 -0
- data/lib/activeresource/test/cases/collection_test.rb +172 -0
- data/lib/activeresource/test/cases/connection_test.rb +357 -0
- data/lib/activeresource/test/cases/finder_test.rb +217 -0
- data/lib/activeresource/test/cases/format_test.rb +137 -0
- data/lib/activeresource/test/cases/http_mock_test.rb +213 -0
- data/lib/activeresource/test/cases/inheritence_test.rb +19 -0
- data/lib/activeresource/test/cases/inheriting_hash_test.rb +25 -0
- data/lib/activeresource/test/cases/log_subscriber_test.rb +63 -0
- data/lib/activeresource/test/cases/reflection_test.rb +65 -0
- data/lib/activeresource/test/cases/validations_test.rb +78 -0
- data/lib/activeresource/test/fixtures/address.rb +20 -0
- data/lib/activeresource/test/fixtures/beast.rb +16 -0
- data/lib/activeresource/test/fixtures/comment.rb +5 -0
- data/lib/activeresource/test/fixtures/customer.rb +5 -0
- data/lib/activeresource/test/fixtures/inventory.rb +14 -0
- data/lib/activeresource/test/fixtures/person.rb +15 -0
- data/lib/activeresource/test/fixtures/pet.rb +6 -0
- data/lib/activeresource/test/fixtures/post.rb +5 -0
- data/lib/activeresource/test/fixtures/product.rb +11 -0
- data/lib/activeresource/test/fixtures/project.rb +19 -0
- data/lib/activeresource/test/fixtures/proxy.rb +6 -0
- data/lib/activeresource/test/fixtures/sound.rb +11 -0
- data/lib/activeresource/test/fixtures/street_address.rb +6 -0
- data/lib/activeresource/test/fixtures/subscription_plan.rb +7 -0
- data/lib/activeresource/test/fixtures/weather.rb +21 -0
- data/lib/activeresource/test/setter_trap.rb +28 -0
- data/lib/activeresource/test/singleton_test.rb +138 -0
- data/lib/activeresource/test/threadsafe_attributes_test.rb +91 -0
- data/lib/generators/active_cached_resource/install_generator.rb +31 -0
- data/lib/generators/active_cached_resource/templates/migration.erb +16 -0
- data/sorbet/config +4 -0
- data/sorbet/rbi/annotations/.gitattributes +1 -0
- data/sorbet/rbi/annotations/activemodel.rbi +89 -0
- data/sorbet/rbi/annotations/activesupport.rbi +457 -0
- data/sorbet/rbi/annotations/minitest.rbi +119 -0
- data/sorbet/rbi/annotations/rainbow.rbi +269 -0
- data/sorbet/rbi/dsl/.gitattributes +1 -0
- data/sorbet/rbi/dsl/active_support/callbacks.rbi +21 -0
- data/sorbet/rbi/gems/.gitattributes +1 -0
- data/sorbet/rbi/gems/actioncable@8.0.0.rbi +252 -0
- data/sorbet/rbi/gems/actionmailbox@8.0.0.rbi +9 -0
- data/sorbet/rbi/gems/actionmailer@8.0.0.rbi +9 -0
- data/sorbet/rbi/gems/actionpack@8.0.0.rbi +20909 -0
- data/sorbet/rbi/gems/actiontext@8.0.0.rbi +9 -0
- data/sorbet/rbi/gems/actionview@8.0.0.rbi +16207 -0
- data/sorbet/rbi/gems/activejob@8.0.0.rbi +9 -0
- data/sorbet/rbi/gems/activemodel-serializers-xml@1.0.3.rbi +166 -0
- data/sorbet/rbi/gems/activemodel@8.0.0.rbi +6857 -0
- data/sorbet/rbi/gems/activerecord@8.0.0.rbi +42896 -0
- data/sorbet/rbi/gems/activeresource@6.1.4.rbi +3944 -0
- data/sorbet/rbi/gems/activestorage@8.0.0.rbi +9 -0
- data/sorbet/rbi/gems/activesupport@8.0.0.rbi +21251 -0
- data/sorbet/rbi/gems/ast@2.4.2.rbi +585 -0
- data/sorbet/rbi/gems/base64@0.2.0.rbi +509 -0
- data/sorbet/rbi/gems/benchmark@0.4.0.rbi +618 -0
- data/sorbet/rbi/gems/bigdecimal@3.1.8.rbi +78 -0
- data/sorbet/rbi/gems/builder@3.3.0.rbi +9 -0
- data/sorbet/rbi/gems/bump@0.10.0.rbi +169 -0
- data/sorbet/rbi/gems/byebug@11.1.3.rbi +3607 -0
- data/sorbet/rbi/gems/coderay@1.1.3.rbi +3427 -0
- data/sorbet/rbi/gems/concurrent-ruby@1.3.4.rbi +11645 -0
- data/sorbet/rbi/gems/connection_pool@2.4.1.rbi +9 -0
- data/sorbet/rbi/gems/crass@1.0.6.rbi +623 -0
- data/sorbet/rbi/gems/date@3.4.0.rbi +75 -0
- data/sorbet/rbi/gems/diff-lcs@1.5.1.rbi +1131 -0
- data/sorbet/rbi/gems/docile@1.4.1.rbi +377 -0
- data/sorbet/rbi/gems/drb@2.2.1.rbi +1347 -0
- data/sorbet/rbi/gems/erubi@1.13.0.rbi +150 -0
- data/sorbet/rbi/gems/globalid@1.2.1.rbi +9 -0
- data/sorbet/rbi/gems/i18n@1.14.6.rbi +2359 -0
- data/sorbet/rbi/gems/io-console@0.7.2.rbi +9 -0
- data/sorbet/rbi/gems/json@2.8.2.rbi +1901 -0
- data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +14238 -0
- data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +240 -0
- data/sorbet/rbi/gems/logger@1.6.1.rbi +920 -0
- data/sorbet/rbi/gems/loofah@2.23.1.rbi +1081 -0
- data/sorbet/rbi/gems/mail@2.8.1.rbi +9 -0
- data/sorbet/rbi/gems/marcel@1.0.4.rbi +9 -0
- data/sorbet/rbi/gems/method_source@1.1.0.rbi +304 -0
- data/sorbet/rbi/gems/mini_mime@1.1.5.rbi +9 -0
- data/sorbet/rbi/gems/minitest@5.25.2.rbi +1547 -0
- data/sorbet/rbi/gems/net-imap@0.5.1.rbi +9 -0
- data/sorbet/rbi/gems/net-pop@0.1.2.rbi +9 -0
- data/sorbet/rbi/gems/net-protocol@0.2.2.rbi +292 -0
- data/sorbet/rbi/gems/net-smtp@0.5.0.rbi +9 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
- data/sorbet/rbi/gems/nio4r@2.7.4.rbi +9 -0
- data/sorbet/rbi/gems/nokogiri@1.16.7.rbi +7311 -0
- data/sorbet/rbi/gems/parallel@1.26.3.rbi +291 -0
- data/sorbet/rbi/gems/parser@3.3.6.0.rbi +5519 -0
- data/sorbet/rbi/gems/prism@1.2.0.rbi +39085 -0
- data/sorbet/rbi/gems/pry-byebug@3.10.1.rbi +1151 -0
- data/sorbet/rbi/gems/pry@0.14.2.rbi +10076 -0
- data/sorbet/rbi/gems/psych@5.2.0.rbi +1785 -0
- data/sorbet/rbi/gems/racc@1.8.1.rbi +162 -0
- data/sorbet/rbi/gems/rack-session@2.0.0.rbi +727 -0
- data/sorbet/rbi/gems/rack-test@2.1.0.rbi +747 -0
- data/sorbet/rbi/gems/rack@3.1.8.rbi +4905 -0
- data/sorbet/rbi/gems/rackup@2.2.1.rbi +230 -0
- data/sorbet/rbi/gems/rails-dom-testing@2.2.0.rbi +758 -0
- data/sorbet/rbi/gems/rails-html-sanitizer@1.6.0.rbi +785 -0
- data/sorbet/rbi/gems/rails@8.0.0.rbi +9 -0
- data/sorbet/rbi/gems/railties@8.0.0.rbi +6287 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +403 -0
- data/sorbet/rbi/gems/rake@13.2.1.rbi +3091 -0
- data/sorbet/rbi/gems/rbi@0.2.1.rbi +4535 -0
- data/sorbet/rbi/gems/rdoc@6.8.1.rbi +12572 -0
- data/sorbet/rbi/gems/regexp_parser@2.9.2.rbi +3772 -0
- data/sorbet/rbi/gems/reline@0.5.12.rbi +2416 -0
- data/sorbet/rbi/gems/rexml@3.3.9.rbi +4858 -0
- data/sorbet/rbi/gems/rspec-core@3.13.2.rbi +11287 -0
- data/sorbet/rbi/gems/rspec-expectations@3.13.3.rbi +8183 -0
- data/sorbet/rbi/gems/rspec-mocks@3.13.2.rbi +5341 -0
- data/sorbet/rbi/gems/rspec-support@3.13.1.rbi +1630 -0
- data/sorbet/rbi/gems/rspec@3.13.0.rbi +83 -0
- data/sorbet/rbi/gems/rubocop-ast@1.36.1.rbi +7303 -0
- data/sorbet/rbi/gems/rubocop-performance@1.21.1.rbi +9 -0
- data/sorbet/rbi/gems/rubocop@1.65.1.rbi +58170 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1318 -0
- data/sorbet/rbi/gems/securerandom@0.3.2.rbi +395 -0
- data/sorbet/rbi/gems/simplecov-html@0.13.1.rbi +225 -0
- data/sorbet/rbi/gems/simplecov@0.22.0.rbi +2149 -0
- data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +9 -0
- data/sorbet/rbi/gems/spoom@1.5.0.rbi +4932 -0
- data/sorbet/rbi/gems/standard-custom@1.0.2.rbi +9 -0
- data/sorbet/rbi/gems/standard-performance@1.4.0.rbi +9 -0
- data/sorbet/rbi/gems/standard@1.40.0.rbi +929 -0
- data/sorbet/rbi/gems/stringio@3.1.2.rbi +9 -0
- data/sorbet/rbi/gems/tapioca@0.16.4.rbi +3597 -0
- data/sorbet/rbi/gems/thor@1.3.2.rbi +4378 -0
- data/sorbet/rbi/gems/timeout@0.4.2.rbi +151 -0
- data/sorbet/rbi/gems/tzinfo@2.0.6.rbi +5918 -0
- data/sorbet/rbi/gems/unicode-display_width@2.6.0.rbi +66 -0
- data/sorbet/rbi/gems/uri@1.0.2.rbi +2377 -0
- data/sorbet/rbi/gems/useragent@0.16.10.rbi +9 -0
- data/sorbet/rbi/gems/websocket-driver@0.7.6.rbi +9 -0
- data/sorbet/rbi/gems/websocket-extensions@0.1.5.rbi +9 -0
- data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
- data/sorbet/rbi/gems/yard@0.9.37.rbi +18504 -0
- data/sorbet/rbi/gems/zeitwerk@2.7.1.rbi +9 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +12 -0
- metadata +543 -0
|
@@ -0,0 +1,1622 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "abstract_unit"
|
|
4
|
+
require "fixtures/person"
|
|
5
|
+
require "fixtures/customer"
|
|
6
|
+
require "fixtures/street_address"
|
|
7
|
+
require "fixtures/sound"
|
|
8
|
+
require "fixtures/beast"
|
|
9
|
+
require "fixtures/proxy"
|
|
10
|
+
require "fixtures/address"
|
|
11
|
+
require "fixtures/subscription_plan"
|
|
12
|
+
require "fixtures/post"
|
|
13
|
+
require "fixtures/comment"
|
|
14
|
+
require "fixtures/product"
|
|
15
|
+
require "fixtures/inventory"
|
|
16
|
+
require "active_support/json"
|
|
17
|
+
require "active_support/core_ext/hash/conversions"
|
|
18
|
+
require "mocha/minitest"
|
|
19
|
+
|
|
20
|
+
class BaseTest < ActiveSupport::TestCase
|
|
21
|
+
def setup
|
|
22
|
+
setup_response # find me in abstract_unit
|
|
23
|
+
@original_person_site = Person.site
|
|
24
|
+
@original_person_proxy = Person.proxy
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def teardown
|
|
28
|
+
Person.site = @original_person_site
|
|
29
|
+
Person.proxy = @original_person_proxy
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
########################################################################
|
|
33
|
+
# Tests relating to setting up the API-connection configuration
|
|
34
|
+
########################################################################
|
|
35
|
+
|
|
36
|
+
def test_site_accessor_accepts_uri_or_string_argument
|
|
37
|
+
site = URI.parse("http://localhost")
|
|
38
|
+
|
|
39
|
+
assert_nothing_raised { Person.site = "http://localhost" }
|
|
40
|
+
assert_equal site, Person.site
|
|
41
|
+
|
|
42
|
+
assert_nothing_raised { Person.site = site }
|
|
43
|
+
assert_equal site, Person.site
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_should_use_site_prefix_and_credentials
|
|
47
|
+
assert_equal "http://foo:bar@beast.caboo.se", Forum.site.to_s
|
|
48
|
+
assert_equal "http://foo:bar@beast.caboo.se/forums/:forum_id", Topic.site.to_s
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_site_variable_can_be_reset
|
|
52
|
+
actor = Class.new(ActiveResource::Base)
|
|
53
|
+
assert_nil actor.site
|
|
54
|
+
actor.site = "http://localhost:31337"
|
|
55
|
+
actor.site = nil
|
|
56
|
+
assert_nil actor.site
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_proxy_accessor_accepts_uri_or_string_argument
|
|
60
|
+
proxy = URI.parse("http://localhost")
|
|
61
|
+
|
|
62
|
+
assert_nothing_raised { Person.proxy = "http://localhost" }
|
|
63
|
+
assert_equal proxy, Person.proxy
|
|
64
|
+
|
|
65
|
+
assert_nothing_raised { Person.proxy = proxy }
|
|
66
|
+
assert_equal proxy, Person.proxy
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_should_use_proxy_prefix_and_credentials
|
|
70
|
+
assert_equal "http://user:password@proxy.local:3000", ProxyResource.proxy.to_s
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_proxy_variable_can_be_reset
|
|
74
|
+
actor = Class.new(ActiveResource::Base)
|
|
75
|
+
assert_nil actor.site
|
|
76
|
+
actor.proxy = "http://localhost:31337"
|
|
77
|
+
actor.proxy = nil
|
|
78
|
+
assert_nil actor.site
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_should_accept_setting_user
|
|
82
|
+
Forum.user = "david"
|
|
83
|
+
assert_equal("david", Forum.user)
|
|
84
|
+
assert_equal("david", Forum.connection.user)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def test_should_accept_setting_password
|
|
88
|
+
Forum.password = "test123"
|
|
89
|
+
assert_equal("test123", Forum.password)
|
|
90
|
+
assert_equal("test123", Forum.connection.password)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_should_accept_setting_bearer_token
|
|
94
|
+
Forum.bearer_token = "token123"
|
|
95
|
+
assert_equal("token123", Forum.bearer_token)
|
|
96
|
+
assert_equal("token123", Forum.connection.bearer_token)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_should_accept_setting_auth_type
|
|
100
|
+
Forum.auth_type = :digest
|
|
101
|
+
assert_equal(:digest, Forum.auth_type)
|
|
102
|
+
assert_equal(:digest, Forum.connection.auth_type)
|
|
103
|
+
|
|
104
|
+
Forum.auth_type = :bearer
|
|
105
|
+
assert_equal(:bearer, Forum.auth_type)
|
|
106
|
+
assert_equal(:bearer, Forum.connection.auth_type)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_should_accept_setting_timeout
|
|
110
|
+
Forum.timeout = 5
|
|
111
|
+
assert_equal(5, Forum.timeout)
|
|
112
|
+
assert_equal(5, Forum.connection.timeout)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_should_accept_setting_open_timeout
|
|
116
|
+
Forum.open_timeout = 5
|
|
117
|
+
assert_equal(5, Forum.open_timeout)
|
|
118
|
+
assert_equal(5, Forum.connection.open_timeout)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def test_should_accept_setting_read_timeout
|
|
122
|
+
Forum.read_timeout = 5
|
|
123
|
+
assert_equal(5, Forum.read_timeout)
|
|
124
|
+
assert_equal(5, Forum.connection.read_timeout)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def test_should_accept_setting_ssl_options
|
|
128
|
+
expected = { verify: 1 }
|
|
129
|
+
Forum.ssl_options = expected
|
|
130
|
+
assert_equal(expected, Forum.ssl_options)
|
|
131
|
+
assert_equal(expected, Forum.connection.ssl_options)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def test_user_variable_can_be_reset
|
|
135
|
+
actor = Class.new(ActiveResource::Base)
|
|
136
|
+
actor.site = "http://cinema"
|
|
137
|
+
assert_nil actor.user
|
|
138
|
+
actor.user = "username"
|
|
139
|
+
actor.user = nil
|
|
140
|
+
assert_nil actor.user
|
|
141
|
+
assert_nil actor.connection.user
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def test_password_variable_can_be_reset
|
|
145
|
+
actor = Class.new(ActiveResource::Base)
|
|
146
|
+
actor.site = "http://cinema"
|
|
147
|
+
assert_nil actor.password
|
|
148
|
+
actor.password = "username"
|
|
149
|
+
actor.password = nil
|
|
150
|
+
assert_nil actor.password
|
|
151
|
+
assert_nil actor.connection.password
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def test_bearer_token_variable_can_be_reset
|
|
155
|
+
actor = Class.new(ActiveResource::Base)
|
|
156
|
+
actor.site = "http://cinema"
|
|
157
|
+
assert_nil actor.bearer_token
|
|
158
|
+
actor.bearer_token = "token"
|
|
159
|
+
actor.bearer_token = nil
|
|
160
|
+
assert_nil actor.bearer_token
|
|
161
|
+
assert_nil actor.connection.bearer_token
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def test_timeout_variable_can_be_reset
|
|
165
|
+
actor = Class.new(ActiveResource::Base)
|
|
166
|
+
actor.site = "http://cinema"
|
|
167
|
+
assert_nil actor.timeout
|
|
168
|
+
actor.timeout = 5
|
|
169
|
+
actor.timeout = nil
|
|
170
|
+
assert_nil actor.timeout
|
|
171
|
+
assert_nil actor.connection.timeout
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def test_open_timeout_variable_can_be_reset
|
|
175
|
+
actor = Class.new(ActiveResource::Base)
|
|
176
|
+
actor.site = "http://cinema"
|
|
177
|
+
assert_nil actor.open_timeout
|
|
178
|
+
actor.open_timeout = 5
|
|
179
|
+
actor.open_timeout = nil
|
|
180
|
+
assert_nil actor.open_timeout
|
|
181
|
+
assert_nil actor.connection.open_timeout
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def test_read_timeout_variable_can_be_reset
|
|
185
|
+
actor = Class.new(ActiveResource::Base)
|
|
186
|
+
actor.site = "http://cinema"
|
|
187
|
+
assert_nil actor.read_timeout
|
|
188
|
+
actor.read_timeout = 5
|
|
189
|
+
actor.read_timeout = nil
|
|
190
|
+
assert_nil actor.read_timeout
|
|
191
|
+
assert_nil actor.connection.read_timeout
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def test_ssl_options_hash_can_be_reset
|
|
195
|
+
# SSL options are nil, resulting in an empty hash on the connection.
|
|
196
|
+
actor = Class.new(ActiveResource::Base)
|
|
197
|
+
actor.site = "https://cinema"
|
|
198
|
+
assert_nil actor.ssl_options
|
|
199
|
+
connection = actor.connection
|
|
200
|
+
assert_equal Hash.new, connection.ssl_options
|
|
201
|
+
|
|
202
|
+
# Setting SSL options wipes the connection.
|
|
203
|
+
actor.ssl_options = { foo: 5 }
|
|
204
|
+
assert_not_equal connection, actor.connection
|
|
205
|
+
connection = actor.connection
|
|
206
|
+
assert_equal 5, connection.ssl_options[:foo]
|
|
207
|
+
|
|
208
|
+
# Setting SSL options to nil also wipes the connection.
|
|
209
|
+
actor.ssl_options = nil
|
|
210
|
+
assert_not_equal connection, actor.connection
|
|
211
|
+
assert_equal Hash.new, actor.connection.ssl_options
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def test_credentials_from_site_are_decoded
|
|
215
|
+
actor = Class.new(ActiveResource::Base)
|
|
216
|
+
actor.site = "http://my%40email.com:%31%32%33@cinema"
|
|
217
|
+
assert_equal("my@email.com", actor.user)
|
|
218
|
+
assert_equal("123", actor.password)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def test_site_reader_uses_superclass_site_until_written
|
|
222
|
+
# Superclass is Object so returns nil.
|
|
223
|
+
assert_nil ActiveResource::Base.site
|
|
224
|
+
assert_nil Class.new(ActiveResource::Base).site
|
|
225
|
+
|
|
226
|
+
# Subclass uses superclass site.
|
|
227
|
+
actor = Class.new(Person)
|
|
228
|
+
assert_equal Person.site, actor.site
|
|
229
|
+
|
|
230
|
+
# Subclass returns frozen superclass copy.
|
|
231
|
+
assert_not Person.site.frozen?
|
|
232
|
+
assert actor.site.frozen?
|
|
233
|
+
|
|
234
|
+
# Changing subclass site doesn't change superclass site.
|
|
235
|
+
actor.site = "http://localhost:31337"
|
|
236
|
+
assert_not_equal Person.site, actor.site
|
|
237
|
+
|
|
238
|
+
# Changed subclass site is not frozen.
|
|
239
|
+
assert_not actor.site.frozen?
|
|
240
|
+
|
|
241
|
+
# Changing superclass site doesn't overwrite subclass site.
|
|
242
|
+
Person.site = "http://somewhere.else"
|
|
243
|
+
assert_not_equal Person.site, actor.site
|
|
244
|
+
|
|
245
|
+
# Changing superclass site after subclassing changes subclass site.
|
|
246
|
+
jester = Class.new(actor)
|
|
247
|
+
actor.site = "http://nomad"
|
|
248
|
+
assert_equal actor.site, jester.site
|
|
249
|
+
assert jester.site.frozen?
|
|
250
|
+
|
|
251
|
+
# Subclasses are always equal to superclass site when not overridden
|
|
252
|
+
fruit = Class.new(ActiveResource::Base)
|
|
253
|
+
apple = Class.new(fruit)
|
|
254
|
+
|
|
255
|
+
fruit.site = "http://market"
|
|
256
|
+
assert_equal fruit.site, apple.site, "subclass did not adopt changes from parent class"
|
|
257
|
+
|
|
258
|
+
fruit.site = "http://supermarket"
|
|
259
|
+
assert_equal fruit.site, apple.site, "subclass did not adopt changes from parent class"
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def test_proxy_reader_uses_superclass_site_until_written
|
|
263
|
+
# Superclass is Object so returns nil.
|
|
264
|
+
assert_nil ActiveResource::Base.proxy
|
|
265
|
+
assert_nil Class.new(ActiveResource::Base).proxy
|
|
266
|
+
|
|
267
|
+
Person.proxy = "http://proxy.local"
|
|
268
|
+
|
|
269
|
+
# Subclass uses superclass proxy.
|
|
270
|
+
actor = Class.new(Person)
|
|
271
|
+
assert_equal Person.proxy, actor.proxy
|
|
272
|
+
|
|
273
|
+
# Subclass returns frozen superclass copy.
|
|
274
|
+
assert_not Person.proxy.frozen?
|
|
275
|
+
assert actor.proxy.frozen?
|
|
276
|
+
|
|
277
|
+
# Changing subclass proxy doesn't change superclass site.
|
|
278
|
+
actor.proxy = "http://localhost:31337"
|
|
279
|
+
assert_not_equal Person.proxy, actor.proxy
|
|
280
|
+
|
|
281
|
+
# Changed subclass proxy is not frozen.
|
|
282
|
+
assert_not actor.proxy.frozen?
|
|
283
|
+
|
|
284
|
+
# Changing superclass proxy doesn't overwrite subclass site.
|
|
285
|
+
Person.proxy = "http://somewhere.else"
|
|
286
|
+
assert_not_equal Person.proxy, actor.proxy
|
|
287
|
+
|
|
288
|
+
# Changing superclass proxy after subclassing changes subclass site.
|
|
289
|
+
jester = Class.new(actor)
|
|
290
|
+
actor.proxy = "http://nomad"
|
|
291
|
+
assert_equal actor.proxy, jester.proxy
|
|
292
|
+
assert jester.proxy.frozen?
|
|
293
|
+
|
|
294
|
+
# Subclasses are always equal to superclass proxy when not overridden
|
|
295
|
+
fruit = Class.new(ActiveResource::Base)
|
|
296
|
+
apple = Class.new(fruit)
|
|
297
|
+
|
|
298
|
+
fruit.proxy = "http://market"
|
|
299
|
+
assert_equal fruit.proxy, apple.proxy, "subclass did not adopt changes from parent class"
|
|
300
|
+
|
|
301
|
+
fruit.proxy = "http://supermarket"
|
|
302
|
+
assert_equal fruit.proxy, apple.proxy, "subclass did not adopt changes from parent class"
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def test_user_reader_uses_superclass_user_until_written
|
|
306
|
+
# Superclass is Object so returns nil.
|
|
307
|
+
assert_nil ActiveResource::Base.user
|
|
308
|
+
assert_nil Class.new(ActiveResource::Base).user
|
|
309
|
+
person_user = Person.user
|
|
310
|
+
Person.user = "anonymous".dup
|
|
311
|
+
|
|
312
|
+
# Subclass uses superclass user.
|
|
313
|
+
actor = Class.new(Person)
|
|
314
|
+
assert_equal Person.user, actor.user
|
|
315
|
+
|
|
316
|
+
# Subclass returns frozen superclass copy.
|
|
317
|
+
assert_not Person.user.frozen?
|
|
318
|
+
assert actor.user.frozen?
|
|
319
|
+
|
|
320
|
+
# Changing subclass user doesn't change superclass user.
|
|
321
|
+
actor.user = "david"
|
|
322
|
+
assert_not_equal Person.user, actor.user
|
|
323
|
+
|
|
324
|
+
# Changing superclass user doesn't overwrite subclass user.
|
|
325
|
+
Person.user = "john"
|
|
326
|
+
assert_not_equal Person.user, actor.user
|
|
327
|
+
|
|
328
|
+
# Changing superclass user after subclassing changes subclass user.
|
|
329
|
+
jester = Class.new(actor)
|
|
330
|
+
actor.user = "john.doe"
|
|
331
|
+
assert_equal actor.user, jester.user
|
|
332
|
+
|
|
333
|
+
# Subclasses are always equal to superclass user when not overridden
|
|
334
|
+
fruit = Class.new(ActiveResource::Base)
|
|
335
|
+
apple = Class.new(fruit)
|
|
336
|
+
|
|
337
|
+
fruit.user = "manager"
|
|
338
|
+
assert_equal fruit.user, apple.user, "subclass did not adopt changes from parent class"
|
|
339
|
+
|
|
340
|
+
fruit.user = "client"
|
|
341
|
+
assert_equal fruit.user, apple.user, "subclass did not adopt changes from parent class"
|
|
342
|
+
ensure
|
|
343
|
+
Person.user = person_user
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def test_password_reader_uses_superclass_password_until_written
|
|
347
|
+
# Superclass is Object so returns nil.
|
|
348
|
+
assert_nil ActiveResource::Base.password
|
|
349
|
+
assert_nil Class.new(ActiveResource::Base).password
|
|
350
|
+
Person.password = "my-password".dup
|
|
351
|
+
|
|
352
|
+
# Subclass uses superclass password.
|
|
353
|
+
actor = Class.new(Person)
|
|
354
|
+
assert_equal Person.password, actor.password
|
|
355
|
+
|
|
356
|
+
# Subclass returns frozen superclass copy.
|
|
357
|
+
assert_not Person.password.frozen?
|
|
358
|
+
assert actor.password.frozen?
|
|
359
|
+
|
|
360
|
+
# Changing subclass password doesn't change superclass password.
|
|
361
|
+
actor.password = "secret"
|
|
362
|
+
assert_not_equal Person.password, actor.password
|
|
363
|
+
|
|
364
|
+
# Changing superclass password doesn't overwrite subclass password.
|
|
365
|
+
Person.password = "super-secret"
|
|
366
|
+
assert_not_equal Person.password, actor.password
|
|
367
|
+
|
|
368
|
+
# Changing superclass password after subclassing changes subclass password.
|
|
369
|
+
jester = Class.new(actor)
|
|
370
|
+
actor.password = "even-more-secret"
|
|
371
|
+
assert_equal actor.password, jester.password
|
|
372
|
+
|
|
373
|
+
# Subclasses are always equal to superclass password when not overridden
|
|
374
|
+
fruit = Class.new(ActiveResource::Base)
|
|
375
|
+
apple = Class.new(fruit)
|
|
376
|
+
|
|
377
|
+
fruit.password = "mega-secret"
|
|
378
|
+
assert_equal fruit.password, apple.password, "subclass did not adopt changes from parent class"
|
|
379
|
+
|
|
380
|
+
fruit.password = "ok-password"
|
|
381
|
+
assert_equal fruit.password, apple.password, "subclass did not adopt changes from parent class"
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def test_bearer_token_reader_uses_superclass_bearer_token_until_written
|
|
385
|
+
# Superclass is Object so returns nil.
|
|
386
|
+
assert_nil ActiveResource::Base.bearer_token
|
|
387
|
+
assert_nil Class.new(ActiveResource::Base).bearer_token
|
|
388
|
+
Person.bearer_token = "my-token".dup
|
|
389
|
+
|
|
390
|
+
# Subclass uses superclass bearer_token.
|
|
391
|
+
actor = Class.new(Person)
|
|
392
|
+
assert_equal Person.bearer_token, actor.bearer_token
|
|
393
|
+
|
|
394
|
+
# Subclass returns frozen superclass copy.
|
|
395
|
+
assert_not Person.bearer_token.frozen?
|
|
396
|
+
assert actor.bearer_token.frozen?
|
|
397
|
+
|
|
398
|
+
# Changing subclass bearer_token doesn't change superclass bearer_token.
|
|
399
|
+
actor.bearer_token = "token123"
|
|
400
|
+
assert_not_equal Person.bearer_token, actor.bearer_token
|
|
401
|
+
|
|
402
|
+
# Changing superclass bearer_token doesn't overwrite subclass bearer_token.
|
|
403
|
+
Person.bearer_token = "super-secret-token"
|
|
404
|
+
assert_not_equal Person.bearer_token, actor.bearer_token
|
|
405
|
+
|
|
406
|
+
# Changing superclass bearer_token after subclassing changes subclass bearer_token.
|
|
407
|
+
jester = Class.new(actor)
|
|
408
|
+
actor.bearer_token = "super-secret-token123"
|
|
409
|
+
assert_equal actor.bearer_token, jester.bearer_token
|
|
410
|
+
|
|
411
|
+
# Subclasses are always equal to superclass bearer_token when not overridden
|
|
412
|
+
fruit = Class.new(ActiveResource::Base)
|
|
413
|
+
apple = Class.new(fruit)
|
|
414
|
+
|
|
415
|
+
fruit.bearer_token = "mega-secret-token"
|
|
416
|
+
assert_equal fruit.bearer_token, apple.bearer_token, "subclass did not adopt changes from parent class"
|
|
417
|
+
|
|
418
|
+
fruit.bearer_token = "ok-token"
|
|
419
|
+
assert_equal fruit.bearer_token, apple.bearer_token, "subclass did not adopt changes from parent class"
|
|
420
|
+
|
|
421
|
+
Person.bearer_token = nil
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def test_timeout_reader_uses_superclass_timeout_until_written
|
|
425
|
+
# Superclass is Object so returns nil.
|
|
426
|
+
assert_nil ActiveResource::Base.timeout
|
|
427
|
+
assert_nil Class.new(ActiveResource::Base).timeout
|
|
428
|
+
Person.timeout = 5
|
|
429
|
+
|
|
430
|
+
# Subclass uses superclass timeout.
|
|
431
|
+
actor = Class.new(Person)
|
|
432
|
+
assert_equal Person.timeout, actor.timeout
|
|
433
|
+
|
|
434
|
+
# Changing subclass timeout doesn't change superclass timeout.
|
|
435
|
+
actor.timeout = 10
|
|
436
|
+
assert_not_equal Person.timeout, actor.timeout
|
|
437
|
+
|
|
438
|
+
# Changing superclass timeout doesn't overwrite subclass timeout.
|
|
439
|
+
Person.timeout = 15
|
|
440
|
+
assert_not_equal Person.timeout, actor.timeout
|
|
441
|
+
|
|
442
|
+
# Changing superclass timeout after subclassing changes subclass timeout.
|
|
443
|
+
jester = Class.new(actor)
|
|
444
|
+
actor.timeout = 20
|
|
445
|
+
assert_equal actor.timeout, jester.timeout
|
|
446
|
+
|
|
447
|
+
# Subclasses are always equal to superclass timeout when not overridden.
|
|
448
|
+
fruit = Class.new(ActiveResource::Base)
|
|
449
|
+
apple = Class.new(fruit)
|
|
450
|
+
|
|
451
|
+
fruit.timeout = 25
|
|
452
|
+
assert_equal fruit.timeout, apple.timeout, "subclass did not adopt changes from parent class"
|
|
453
|
+
|
|
454
|
+
fruit.timeout = 30
|
|
455
|
+
assert_equal fruit.timeout, apple.timeout, "subclass did not adopt changes from parent class"
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
def test_open_and_read_timeout_readers_uses_superclass_timeout_until_written
|
|
459
|
+
# Superclass is Object so returns nil.
|
|
460
|
+
assert_nil ActiveResource::Base.open_timeout
|
|
461
|
+
assert_nil Class.new(ActiveResource::Base).open_timeout
|
|
462
|
+
assert_nil ActiveResource::Base.read_timeout
|
|
463
|
+
assert_nil Class.new(ActiveResource::Base).read_timeout
|
|
464
|
+
Person.open_timeout = 5
|
|
465
|
+
Person.read_timeout = 5
|
|
466
|
+
|
|
467
|
+
# Subclass uses superclass open and read timeouts.
|
|
468
|
+
actor = Class.new(Person)
|
|
469
|
+
assert_equal Person.open_timeout, actor.open_timeout
|
|
470
|
+
assert_equal Person.read_timeout, actor.read_timeout
|
|
471
|
+
|
|
472
|
+
# Changing subclass open and read timeouts doesn't change superclass timeouts.
|
|
473
|
+
actor.open_timeout = 10
|
|
474
|
+
actor.read_timeout = 10
|
|
475
|
+
assert_not_equal Person.open_timeout, actor.open_timeout
|
|
476
|
+
assert_not_equal Person.read_timeout, actor.read_timeout
|
|
477
|
+
|
|
478
|
+
# Changing superclass open and read timeouts doesn't overwrite subclass timeouts.
|
|
479
|
+
Person.open_timeout = 15
|
|
480
|
+
Person.read_timeout = 15
|
|
481
|
+
assert_not_equal Person.open_timeout, actor.open_timeout
|
|
482
|
+
assert_not_equal Person.read_timeout, actor.read_timeout
|
|
483
|
+
|
|
484
|
+
# Changing superclass open and read timeouts after subclassing changes subclass timeouts.
|
|
485
|
+
jester = Class.new(actor)
|
|
486
|
+
actor.open_timeout = 20
|
|
487
|
+
actor.read_timeout = 20
|
|
488
|
+
assert_equal actor.open_timeout, jester.open_timeout
|
|
489
|
+
assert_equal actor.read_timeout, jester.read_timeout
|
|
490
|
+
|
|
491
|
+
# Subclasses are always equal to superclass open and read timeouts when not overridden.
|
|
492
|
+
fruit = Class.new(ActiveResource::Base)
|
|
493
|
+
apple = Class.new(fruit)
|
|
494
|
+
|
|
495
|
+
fruit.open_timeout = 25
|
|
496
|
+
fruit.read_timeout = 25
|
|
497
|
+
assert_equal fruit.open_timeout, apple.open_timeout, "subclass did not adopt changes from parent class"
|
|
498
|
+
assert_equal fruit.read_timeout, apple.read_timeout, "subclass did not adopt changes from parent class"
|
|
499
|
+
|
|
500
|
+
fruit.open_timeout = 30
|
|
501
|
+
fruit.read_timeout = 30
|
|
502
|
+
assert_equal fruit.open_timeout, apple.open_timeout, "subclass did not adopt changes from parent class"
|
|
503
|
+
assert_equal fruit.read_timeout, apple.read_timeout, "subclass did not adopt changes from parent class"
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
def test_primary_key_uses_superclass_primary_key_until_written
|
|
507
|
+
# Superclass is Object so defaults to 'id'
|
|
508
|
+
assert_equal "id", ActiveResource::Base.primary_key
|
|
509
|
+
assert_equal "id", Class.new(ActiveResource::Base).primary_key
|
|
510
|
+
Person.primary_key = :first
|
|
511
|
+
|
|
512
|
+
# Subclass uses superclass primary_key
|
|
513
|
+
actor = Class.new(Person)
|
|
514
|
+
assert_equal Person.primary_key, actor.primary_key
|
|
515
|
+
|
|
516
|
+
# Changing subclass primary_key doesn't change superclass primary_key
|
|
517
|
+
actor.primary_key = :second
|
|
518
|
+
assert_not_equal Person.primary_key, actor.primary_key
|
|
519
|
+
|
|
520
|
+
# Changing superclass primary_key doesn't overwrite subclass primary_key
|
|
521
|
+
Person.primary_key = :third
|
|
522
|
+
assert_not_equal Person.primary_key, actor.primary_key
|
|
523
|
+
|
|
524
|
+
# Changing superclass primary_key after subclassing changes subclass primary_key
|
|
525
|
+
jester = Class.new(actor)
|
|
526
|
+
actor.primary_key = :fourth
|
|
527
|
+
assert_equal actor.primary_key, jester.primary_key
|
|
528
|
+
|
|
529
|
+
# Subclass primary_keys are always equal to superclass primary_key when not overridden
|
|
530
|
+
fruit = Class.new(ActiveResource::Base)
|
|
531
|
+
apple = Class.new(fruit)
|
|
532
|
+
|
|
533
|
+
fruit.primary_key = :fifth
|
|
534
|
+
assert_equal fruit.primary_key, apple.primary_key, "subclass did not adopt changes from parent class"
|
|
535
|
+
|
|
536
|
+
fruit.primary_key = :sixth
|
|
537
|
+
assert_equal fruit.primary_key, apple.primary_key, "subclass did not adopt changes from parent class"
|
|
538
|
+
|
|
539
|
+
# Reset the primary key for subsequent tests
|
|
540
|
+
Person.primary_key = "id"
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
def test_ssl_options_reader_uses_superclass_ssl_options_until_written
|
|
544
|
+
# Superclass is Object so returns nil.
|
|
545
|
+
assert_nil ActiveResource::Base.ssl_options
|
|
546
|
+
assert_nil Class.new(ActiveResource::Base).ssl_options
|
|
547
|
+
Person.ssl_options = { foo: "bar" }
|
|
548
|
+
|
|
549
|
+
# Subclass uses superclass ssl_options.
|
|
550
|
+
actor = Class.new(Person)
|
|
551
|
+
assert_equal Person.ssl_options, actor.ssl_options
|
|
552
|
+
|
|
553
|
+
# Changing subclass ssl_options doesn't change superclass ssl_options.
|
|
554
|
+
actor.ssl_options = { baz: "" }
|
|
555
|
+
assert_not_equal Person.ssl_options, actor.ssl_options
|
|
556
|
+
|
|
557
|
+
# Changing superclass ssl_options doesn't overwrite subclass ssl_options.
|
|
558
|
+
Person.ssl_options = { color: "blue" }
|
|
559
|
+
assert_not_equal Person.ssl_options, actor.ssl_options
|
|
560
|
+
|
|
561
|
+
# Changing superclass ssl_options after subclassing changes subclass ssl_options.
|
|
562
|
+
jester = Class.new(actor)
|
|
563
|
+
actor.ssl_options = { color: "red" }
|
|
564
|
+
assert_equal actor.ssl_options, jester.ssl_options
|
|
565
|
+
|
|
566
|
+
# Subclasses are always equal to superclass ssl_options when not overridden.
|
|
567
|
+
fruit = Class.new(ActiveResource::Base)
|
|
568
|
+
apple = Class.new(fruit)
|
|
569
|
+
|
|
570
|
+
fruit.ssl_options = { alpha: "betas" }
|
|
571
|
+
assert_equal fruit.ssl_options, apple.ssl_options, "subclass did not adopt changes from parent class"
|
|
572
|
+
|
|
573
|
+
fruit.ssl_options = { omega: "moos" }
|
|
574
|
+
assert_equal fruit.ssl_options, apple.ssl_options, "subclass did not adopt changes from parent class"
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
def test_updating_baseclass_site_object_wipes_descendent_cached_connection_objects
|
|
578
|
+
# Subclasses are always equal to superclass site when not overridden
|
|
579
|
+
fruit = Class.new(ActiveResource::Base)
|
|
580
|
+
apple = Class.new(fruit)
|
|
581
|
+
|
|
582
|
+
fruit.site = "http://market"
|
|
583
|
+
assert_equal fruit.connection.site, apple.connection.site
|
|
584
|
+
first_connection = apple.connection.object_id
|
|
585
|
+
|
|
586
|
+
fruit.site = "http://supermarket"
|
|
587
|
+
assert_equal fruit.connection.site, apple.connection.site
|
|
588
|
+
second_connection = apple.connection.object_id
|
|
589
|
+
assert_not_equal(first_connection, second_connection, "Connection should be re-created")
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
def test_updating_baseclass_user_wipes_descendent_cached_connection_objects
|
|
593
|
+
# Subclasses are always equal to superclass user when not overridden
|
|
594
|
+
fruit = Class.new(ActiveResource::Base)
|
|
595
|
+
apple = Class.new(fruit)
|
|
596
|
+
fruit.site = "http://market"
|
|
597
|
+
|
|
598
|
+
fruit.user = "david"
|
|
599
|
+
assert_equal fruit.connection.user, apple.connection.user
|
|
600
|
+
first_connection = apple.connection.object_id
|
|
601
|
+
|
|
602
|
+
fruit.user = "john"
|
|
603
|
+
assert_equal fruit.connection.user, apple.connection.user
|
|
604
|
+
second_connection = apple.connection.object_id
|
|
605
|
+
assert_not_equal(first_connection, second_connection, "Connection should be re-created")
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
def test_updating_baseclass_password_wipes_descendent_cached_connection_objects
|
|
609
|
+
# Subclasses are always equal to superclass password when not overridden
|
|
610
|
+
fruit = Class.new(ActiveResource::Base)
|
|
611
|
+
apple = Class.new(fruit)
|
|
612
|
+
fruit.site = "http://market"
|
|
613
|
+
|
|
614
|
+
fruit.password = "secret"
|
|
615
|
+
assert_equal fruit.connection.password, apple.connection.password
|
|
616
|
+
first_connection = apple.connection.object_id
|
|
617
|
+
|
|
618
|
+
fruit.password = "supersecret"
|
|
619
|
+
assert_equal fruit.connection.password, apple.connection.password
|
|
620
|
+
second_connection = apple.connection.object_id
|
|
621
|
+
assert_not_equal(first_connection, second_connection, "Connection should be re-created")
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
def test_updating_baseclass_bearer_token_wipes_descendent_cached_connection_objects
|
|
625
|
+
# Subclasses are always equal to superclass bearer_token when not overridden
|
|
626
|
+
fruit = Class.new(ActiveResource::Base)
|
|
627
|
+
apple = Class.new(fruit)
|
|
628
|
+
fruit.site = "http://market"
|
|
629
|
+
|
|
630
|
+
fruit.bearer_token = "my-token"
|
|
631
|
+
assert_equal fruit.connection.bearer_token, apple.connection.bearer_token
|
|
632
|
+
first_connection = apple.connection.object_id
|
|
633
|
+
|
|
634
|
+
fruit.bearer_token = "another-token"
|
|
635
|
+
assert_equal fruit.connection.bearer_token, apple.connection.bearer_token
|
|
636
|
+
second_connection = apple.connection.object_id
|
|
637
|
+
assert_not_equal(first_connection, second_connection, "Connection should be re-created")
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
def test_updating_baseclass_timeout_wipes_descendent_cached_connection_objects
|
|
641
|
+
# Subclasses are always equal to superclass timeout when not overridden
|
|
642
|
+
fruit = Class.new(ActiveResource::Base)
|
|
643
|
+
apple = Class.new(fruit)
|
|
644
|
+
fruit.site = "http://market"
|
|
645
|
+
|
|
646
|
+
fruit.timeout = 5
|
|
647
|
+
assert_equal fruit.connection.timeout, apple.connection.timeout
|
|
648
|
+
first_connection = apple.connection.object_id
|
|
649
|
+
|
|
650
|
+
fruit.timeout = 10
|
|
651
|
+
assert_equal fruit.connection.timeout, apple.connection.timeout
|
|
652
|
+
second_connection = apple.connection.object_id
|
|
653
|
+
assert_not_equal(first_connection, second_connection, "Connection should be re-created")
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
def test_updating_baseclass_read_and_open_timeouts_wipes_descendent_cached_connection_objects
|
|
657
|
+
# Subclasses are always equal to superclass timeout when not overridden
|
|
658
|
+
fruit = Class.new(ActiveResource::Base)
|
|
659
|
+
apple = Class.new(fruit)
|
|
660
|
+
fruit.site = "http://market"
|
|
661
|
+
|
|
662
|
+
fruit.open_timeout = 1
|
|
663
|
+
fruit.read_timeout = 5
|
|
664
|
+
assert_equal fruit.connection.open_timeout, apple.connection.open_timeout
|
|
665
|
+
assert_equal fruit.connection.read_timeout, apple.connection.read_timeout
|
|
666
|
+
first_connection = apple.connection.object_id
|
|
667
|
+
|
|
668
|
+
fruit.open_timeout = 2
|
|
669
|
+
fruit.read_timeout = 10
|
|
670
|
+
assert_equal fruit.connection.open_timeout, apple.connection.open_timeout
|
|
671
|
+
assert_equal fruit.connection.read_timeout, apple.connection.read_timeout
|
|
672
|
+
second_connection = apple.connection.object_id
|
|
673
|
+
assert_not_equal(first_connection, second_connection, "Connection should be re-created")
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
def test_header_inheritance
|
|
677
|
+
fruit = Class.new(ActiveResource::Base)
|
|
678
|
+
apple = Class.new(fruit)
|
|
679
|
+
fruit.site = "http://market"
|
|
680
|
+
|
|
681
|
+
fruit.headers["key"] = "value"
|
|
682
|
+
assert_equal "value", apple.headers["key"]
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
def test_header_inheritance_set_at_multiple_points
|
|
686
|
+
fruit = Class.new(ActiveResource::Base)
|
|
687
|
+
apple = Class.new(fruit)
|
|
688
|
+
fruit.site = "http://market"
|
|
689
|
+
|
|
690
|
+
fruit.headers["key"] = "value"
|
|
691
|
+
assert_equal "value", apple.headers["key"]
|
|
692
|
+
|
|
693
|
+
apple.headers["key2"] = "value2"
|
|
694
|
+
fruit.headers["key3"] = "value3"
|
|
695
|
+
|
|
696
|
+
assert_equal "value", apple.headers["key"]
|
|
697
|
+
assert_equal "value2", apple.headers["key2"]
|
|
698
|
+
assert_equal "value3", apple.headers["key3"]
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
def test_header_inheritance_should_not_leak_upstream
|
|
702
|
+
fruit = Class.new(ActiveResource::Base)
|
|
703
|
+
apple = Class.new(fruit)
|
|
704
|
+
fruit.site = "http://market"
|
|
705
|
+
|
|
706
|
+
fruit.headers["key"] = "value"
|
|
707
|
+
|
|
708
|
+
apple.headers["key2"] = "value2"
|
|
709
|
+
assert_nil fruit.headers["key2"]
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
def test_header_inheritance_can_override_upstream
|
|
713
|
+
fruit = Class.new(ActiveResource::Base)
|
|
714
|
+
apple = Class.new(fruit)
|
|
715
|
+
fruit.site = "http://market"
|
|
716
|
+
|
|
717
|
+
fruit.headers["key"] = "fruit-value"
|
|
718
|
+
assert_equal "fruit-value", apple.headers["key"]
|
|
719
|
+
|
|
720
|
+
apple.headers["key"] = "apple-value"
|
|
721
|
+
assert_equal "apple-value", apple.headers["key"]
|
|
722
|
+
assert_equal "fruit-value", fruit.headers["key"]
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
def test_header_inheritance_should_not_override_upstream_on_read
|
|
727
|
+
fruit = Class.new(ActiveResource::Base)
|
|
728
|
+
apple = Class.new(fruit)
|
|
729
|
+
fruit.site = "http://market"
|
|
730
|
+
|
|
731
|
+
fruit.headers["key"] = "value"
|
|
732
|
+
assert_equal "value", apple.headers["key"]
|
|
733
|
+
|
|
734
|
+
fruit.headers["key"] = "new-value"
|
|
735
|
+
assert_equal "new-value", apple.headers["key"]
|
|
736
|
+
end
|
|
737
|
+
|
|
738
|
+
def test_header_should_be_copied_to_main_thread_if_not_defined
|
|
739
|
+
fruit = Class.new(ActiveResource::Base)
|
|
740
|
+
|
|
741
|
+
Thread.new do
|
|
742
|
+
fruit.site = "http://market"
|
|
743
|
+
assert_equal "http://market", fruit.site.to_s
|
|
744
|
+
|
|
745
|
+
fruit.headers["key"] = "value"
|
|
746
|
+
assert_equal "value", fruit.headers["key"]
|
|
747
|
+
end.join
|
|
748
|
+
|
|
749
|
+
assert_equal "http://market", fruit.site.to_s
|
|
750
|
+
assert_equal "value", fruit.headers["key"]
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
def test_connection_should_use_connection_class
|
|
754
|
+
apple = Class.new(ActiveResource::Base)
|
|
755
|
+
orange = Class.new(ActiveResource::Base)
|
|
756
|
+
telephone = Class.new(ActiveResource::Connection)
|
|
757
|
+
orange.connection_class = telephone
|
|
758
|
+
apple.site = orange.site = "https://some-site.com/api"
|
|
759
|
+
|
|
760
|
+
assert_equal ActiveResource::Connection, apple.connection.class
|
|
761
|
+
assert_equal telephone, orange.connection.class
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
########################################################################
|
|
765
|
+
# Tests for setting up remote URLs for a given model (including adding
|
|
766
|
+
# parameters appropriately)
|
|
767
|
+
########################################################################
|
|
768
|
+
def test_collection_name
|
|
769
|
+
assert_equal "people", Person.collection_name
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
def test_collection_path
|
|
773
|
+
assert_equal "/people.json", Person.collection_path
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
def test_collection_path_with_parameters
|
|
777
|
+
assert_equal "/people.json?gender=male", Person.collection_path(gender: "male")
|
|
778
|
+
assert_equal "/people.json?gender=false", Person.collection_path(gender: false)
|
|
779
|
+
assert_equal "/people.json?gender=", Person.collection_path(gender: nil)
|
|
780
|
+
|
|
781
|
+
assert_equal "/people.json?gender=male", Person.collection_path("gender" => "male")
|
|
782
|
+
|
|
783
|
+
# Use includes? because ordering of param hash is not guaranteed
|
|
784
|
+
assert Person.collection_path(gender: "male", student: true).include?("/people.json?")
|
|
785
|
+
assert Person.collection_path(gender: "male", student: true).include?("gender=male")
|
|
786
|
+
assert Person.collection_path(gender: "male", student: true).include?("student=true")
|
|
787
|
+
|
|
788
|
+
assert_equal "/people.json?name%5B%5D=bob&name%5B%5D=your+uncle%2Bme&name%5B%5D=&name%5B%5D=false", Person.collection_path(name: ["bob", "your uncle+me", nil, false])
|
|
789
|
+
assert_equal "/people.json?struct%5Ba%5D%5B%5D=2&struct%5Ba%5D%5B%5D=1&struct%5Bb%5D=fred", Person.collection_path(struct: { :a => [2, 1], "b" => "fred" })
|
|
790
|
+
end
|
|
791
|
+
|
|
792
|
+
def test_custom_element_path
|
|
793
|
+
assert_equal "/people/1/addresses/1.json", StreetAddress.element_path(1, person_id: 1)
|
|
794
|
+
assert_equal "/people/1/addresses/1.json", StreetAddress.element_path(1, "person_id" => 1)
|
|
795
|
+
assert_equal "/people/Greg/addresses/1.json", StreetAddress.element_path(1, "person_id" => "Greg")
|
|
796
|
+
assert_equal "/people/ann%20mary/addresses/ann+mary.json", StreetAddress.element_path(:'ann mary', "person_id" => "ann mary")
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
def test_custom_element_path_without_required_prefix_param
|
|
800
|
+
assert_raise ActiveResource::MissingPrefixParam do
|
|
801
|
+
StreetAddress.element_path(1)
|
|
802
|
+
end
|
|
803
|
+
end
|
|
804
|
+
|
|
805
|
+
def test_module_element_path
|
|
806
|
+
assert_equal "/sounds/1.json", Asset::Sound.element_path(1)
|
|
807
|
+
end
|
|
808
|
+
|
|
809
|
+
def test_module_element_url
|
|
810
|
+
assert_equal "http://37s.sunrise.i:3000/sounds/1.json", Asset::Sound.element_url(1)
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
def test_custom_element_path_with_redefined_to_param
|
|
814
|
+
Person.module_eval do
|
|
815
|
+
alias_method :original_to_param_element_path, :to_param
|
|
816
|
+
def to_param
|
|
817
|
+
name
|
|
818
|
+
end
|
|
819
|
+
end
|
|
820
|
+
|
|
821
|
+
# Class method.
|
|
822
|
+
assert_equal "/people/Greg.json", Person.element_path("Greg")
|
|
823
|
+
|
|
824
|
+
# Protected Instance method.
|
|
825
|
+
assert_equal "/people/Greg.json", Person.find("Greg").send(:element_path)
|
|
826
|
+
|
|
827
|
+
ensure
|
|
828
|
+
# revert back to original
|
|
829
|
+
Person.module_eval do
|
|
830
|
+
# save the 'new' to_param so we don't get a warning about discarding the method
|
|
831
|
+
alias_method :element_path_to_param, :to_param
|
|
832
|
+
alias_method :to_param, :original_to_param_element_path
|
|
833
|
+
end
|
|
834
|
+
end
|
|
835
|
+
|
|
836
|
+
def test_custom_element_path_with_parameters
|
|
837
|
+
assert_equal "/people/1/addresses/1.json?type=work", StreetAddress.element_path(1, person_id: 1, type: "work")
|
|
838
|
+
assert_equal "/people/1/addresses/1.json?type=work", StreetAddress.element_path(1, "person_id" => 1, :type => "work")
|
|
839
|
+
assert_equal "/people/1/addresses/1.json?type=work", StreetAddress.element_path(1, type: "work", person_id: 1)
|
|
840
|
+
assert_equal "/people/1/addresses/1.json?type%5B%5D=work&type%5B%5D=play+time", StreetAddress.element_path(1, person_id: 1, type: ["work", "play time"])
|
|
841
|
+
end
|
|
842
|
+
|
|
843
|
+
def test_custom_element_path_with_prefix_and_parameters
|
|
844
|
+
assert_equal "/people/1/addresses/1.json?type=work", StreetAddress.element_path(1, { person_id: 1 }, { type: "work" })
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
def test_custom_collection_path_without_required_prefix_param
|
|
848
|
+
assert_raise ActiveResource::MissingPrefixParam do
|
|
849
|
+
StreetAddress.collection_path
|
|
850
|
+
end
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
def test_custom_collection_path
|
|
854
|
+
assert_equal "/people/1/addresses.json", StreetAddress.collection_path(person_id: 1)
|
|
855
|
+
assert_equal "/people/1/addresses.json", StreetAddress.collection_path("person_id" => 1)
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
def test_custom_collection_path_with_parameters
|
|
859
|
+
assert_equal "/people/1/addresses.json?type=work", StreetAddress.collection_path(person_id: 1, type: "work")
|
|
860
|
+
assert_equal "/people/1/addresses.json?type=work", StreetAddress.collection_path("person_id" => 1, :type => "work")
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
def test_custom_collection_path_with_prefix_and_parameters
|
|
864
|
+
assert_equal "/people/1/addresses.json?type=work", StreetAddress.collection_path({ person_id: 1 }, { type: "work" })
|
|
865
|
+
end
|
|
866
|
+
|
|
867
|
+
def test_custom_element_name
|
|
868
|
+
assert_equal "address", StreetAddress.element_name
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
def test_custom_collection_name
|
|
872
|
+
assert_equal "addresses", StreetAddress.collection_name
|
|
873
|
+
end
|
|
874
|
+
|
|
875
|
+
def test_prefix
|
|
876
|
+
assert_equal "/", Person.prefix
|
|
877
|
+
assert_equal Set.new, Person.__send__(:prefix_parameters)
|
|
878
|
+
end
|
|
879
|
+
|
|
880
|
+
def test_set_prefix
|
|
881
|
+
SetterTrap.rollback_sets(Person) do |person_class|
|
|
882
|
+
person_class.prefix = "the_prefix"
|
|
883
|
+
assert_equal "the_prefix", person_class.prefix
|
|
884
|
+
end
|
|
885
|
+
end
|
|
886
|
+
|
|
887
|
+
def test_set_prefix_with_inline_keys
|
|
888
|
+
SetterTrap.rollback_sets(Person) do |person_class|
|
|
889
|
+
person_class.prefix = "the_prefix:the_param"
|
|
890
|
+
assert_equal "the_prefixthe_param_value", person_class.prefix(the_param: "the_param_value")
|
|
891
|
+
end
|
|
892
|
+
end
|
|
893
|
+
|
|
894
|
+
def test_set_prefix_twice_should_clear_params
|
|
895
|
+
SetterTrap.rollback_sets(Person) do |person_class|
|
|
896
|
+
person_class.prefix = "the_prefix/:the_param1"
|
|
897
|
+
assert_equal Set.new([:the_param1]), person_class.prefix_parameters
|
|
898
|
+
person_class.prefix = "the_prefix/:the_param2"
|
|
899
|
+
assert_equal Set.new([:the_param2]), person_class.prefix_parameters
|
|
900
|
+
person_class.prefix = "the_prefix/:the_param1/other_prefix/:the_param2"
|
|
901
|
+
assert_equal Set.new([:the_param2, :the_param1]), person_class.prefix_parameters
|
|
902
|
+
end
|
|
903
|
+
end
|
|
904
|
+
|
|
905
|
+
def test_set_prefix_with_default_value
|
|
906
|
+
SetterTrap.rollback_sets(Person) do |person_class|
|
|
907
|
+
person_class.set_prefix
|
|
908
|
+
assert_equal "/", person_class.prefix
|
|
909
|
+
end
|
|
910
|
+
end
|
|
911
|
+
|
|
912
|
+
def test_custom_prefix
|
|
913
|
+
assert_equal "/people//", StreetAddress.prefix
|
|
914
|
+
assert_equal "/people/1/", StreetAddress.prefix(person_id: 1)
|
|
915
|
+
assert_equal [:person_id].to_set, StreetAddress.__send__(:prefix_parameters)
|
|
916
|
+
end
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
########################################################################
|
|
920
|
+
# Tests basic CRUD functions (find/save/create etc)
|
|
921
|
+
########################################################################
|
|
922
|
+
def test_respond_to
|
|
923
|
+
matz = Person.find(1)
|
|
924
|
+
assert_respond_to matz, :name
|
|
925
|
+
assert_respond_to matz, :name=
|
|
926
|
+
assert_respond_to matz, :name?
|
|
927
|
+
assert_not matz.respond_to?(:super_scalable_stuff)
|
|
928
|
+
end
|
|
929
|
+
|
|
930
|
+
def test_custom_header
|
|
931
|
+
Person.headers["key"] = "value"
|
|
932
|
+
assert_raise(ActiveResource::ResourceNotFound) { Person.find(4) }
|
|
933
|
+
ensure
|
|
934
|
+
Person.headers.delete("key")
|
|
935
|
+
end
|
|
936
|
+
|
|
937
|
+
def test_build_with_custom_header
|
|
938
|
+
Person.headers["key"] = "value"
|
|
939
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
940
|
+
mock.get "/people/new.json", {}, Person.new.to_json
|
|
941
|
+
mock.get "/people/new.json", { "key" => "value" }, Person.new.to_json, 404
|
|
942
|
+
end
|
|
943
|
+
assert_raise(ActiveResource::ResourceNotFound) { Person.build }
|
|
944
|
+
ensure
|
|
945
|
+
Person.headers.delete("key")
|
|
946
|
+
end
|
|
947
|
+
|
|
948
|
+
def test_build_without_attributes_for_prefix_call
|
|
949
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
950
|
+
mock.get "/people/1/addresses/new.json", {}, StreetAddress.new.to_json
|
|
951
|
+
end
|
|
952
|
+
assert_raise(ActiveResource::InvalidRequestError) { StreetAddress.build }
|
|
953
|
+
end
|
|
954
|
+
|
|
955
|
+
def test_build_with_attributes_for_prefix_call
|
|
956
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
957
|
+
mock.get "/people/1/addresses/new.json", {}, StreetAddress.new.to_json
|
|
958
|
+
end
|
|
959
|
+
assert_nothing_raised { StreetAddress.build(person_id: 1) }
|
|
960
|
+
end
|
|
961
|
+
|
|
962
|
+
def test_build_with_non_prefix_attributes
|
|
963
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
964
|
+
mock.get "/people/1/addresses/new.json", {}, StreetAddress.new.to_json
|
|
965
|
+
end
|
|
966
|
+
assert_nothing_raised do
|
|
967
|
+
address = StreetAddress.build(person_id: 1, city: "Toronto")
|
|
968
|
+
assert_equal "Toronto", address.city
|
|
969
|
+
end
|
|
970
|
+
end
|
|
971
|
+
|
|
972
|
+
def test_save
|
|
973
|
+
rick = Person.new
|
|
974
|
+
assert rick.save
|
|
975
|
+
assert_equal "5", rick.id
|
|
976
|
+
end
|
|
977
|
+
|
|
978
|
+
def test_save!
|
|
979
|
+
rick = Person.new
|
|
980
|
+
assert rick.save!
|
|
981
|
+
assert_equal "5", rick.id
|
|
982
|
+
end
|
|
983
|
+
|
|
984
|
+
def test_id_from_response
|
|
985
|
+
p = Person.new
|
|
986
|
+
resp = { "Location" => "/foo/bar/1" }
|
|
987
|
+
assert_equal "1", p.__send__(:id_from_response, resp)
|
|
988
|
+
|
|
989
|
+
resp["Location"] += ".json"
|
|
990
|
+
assert_equal "1", p.__send__(:id_from_response, resp)
|
|
991
|
+
end
|
|
992
|
+
|
|
993
|
+
def test_id_from_response_without_location
|
|
994
|
+
p = Person.new
|
|
995
|
+
resp = {}
|
|
996
|
+
assert_nil p.__send__(:id_from_response, resp)
|
|
997
|
+
end
|
|
998
|
+
|
|
999
|
+
def test_not_persisted_with_no_body_and_positive_content_length
|
|
1000
|
+
resp = ActiveResource::Response.new(nil)
|
|
1001
|
+
resp["Content-Length"] = "100"
|
|
1002
|
+
Person.connection.expects(:post).returns(resp)
|
|
1003
|
+
assert_not Person.create.persisted?
|
|
1004
|
+
end
|
|
1005
|
+
|
|
1006
|
+
def test_not_persisted_with_body_and_zero_content_length
|
|
1007
|
+
resp = ActiveResource::Response.new(@rick)
|
|
1008
|
+
resp["Content-Length"] = "0"
|
|
1009
|
+
Person.connection.expects(:post).returns(resp)
|
|
1010
|
+
assert_not Person.create.persisted?
|
|
1011
|
+
end
|
|
1012
|
+
|
|
1013
|
+
# These response codes aren't allowed to have bodies per HTTP spec
|
|
1014
|
+
def test_not_persisted_with_empty_response_codes
|
|
1015
|
+
[100, 101, 204, 304].each do |status_code|
|
|
1016
|
+
resp = ActiveResource::Response.new(@rick, status_code)
|
|
1017
|
+
Person.connection.expects(:post).returns(resp)
|
|
1018
|
+
assert_not Person.create.persisted?
|
|
1019
|
+
end
|
|
1020
|
+
end
|
|
1021
|
+
|
|
1022
|
+
# Content-Length is not required by HTTP 1.1, so we should read
|
|
1023
|
+
# the body anyway in its absence.
|
|
1024
|
+
def test_persisted_with_no_content_length
|
|
1025
|
+
resp = ActiveResource::Response.new(@rick)
|
|
1026
|
+
resp["Content-Length"] = nil
|
|
1027
|
+
Person.connection.expects(:post).returns(resp)
|
|
1028
|
+
assert Person.create.persisted?
|
|
1029
|
+
end
|
|
1030
|
+
|
|
1031
|
+
def test_create_with_custom_prefix
|
|
1032
|
+
matzs_house = StreetAddress.new(person_id: 1)
|
|
1033
|
+
matzs_house.save
|
|
1034
|
+
assert_equal "5", matzs_house.id
|
|
1035
|
+
end
|
|
1036
|
+
|
|
1037
|
+
# Test that loading a resource preserves its prefix_options.
|
|
1038
|
+
def test_load_preserves_prefix_options
|
|
1039
|
+
address = StreetAddress.find(1, params: { person_id: 1 })
|
|
1040
|
+
ryan = Person.new(id: 1, name: "Ryan", address: address)
|
|
1041
|
+
assert_equal address.prefix_options, ryan.address.prefix_options
|
|
1042
|
+
end
|
|
1043
|
+
|
|
1044
|
+
def test_reload_works_with_prefix_options
|
|
1045
|
+
address = StreetAddress.find(1, params: { person_id: 1 })
|
|
1046
|
+
assert_equal address, address.reload
|
|
1047
|
+
end
|
|
1048
|
+
|
|
1049
|
+
def test_reload_with_redefined_to_param
|
|
1050
|
+
Person.module_eval do
|
|
1051
|
+
alias_method :original_to_param_reload, :to_param
|
|
1052
|
+
def to_param
|
|
1053
|
+
name
|
|
1054
|
+
end
|
|
1055
|
+
end
|
|
1056
|
+
|
|
1057
|
+
person = Person.find("Greg")
|
|
1058
|
+
assert_equal person, person.reload
|
|
1059
|
+
|
|
1060
|
+
ensure
|
|
1061
|
+
# revert back to original
|
|
1062
|
+
Person.module_eval do
|
|
1063
|
+
# save the 'new' to_param so we don't get a warning about discarding the method
|
|
1064
|
+
alias_method :reload_to_param, :to_param
|
|
1065
|
+
alias_method :to_param, :original_to_param_reload
|
|
1066
|
+
end
|
|
1067
|
+
end
|
|
1068
|
+
|
|
1069
|
+
def test_reload_works_without_prefix_options
|
|
1070
|
+
person = Person.find(:first)
|
|
1071
|
+
assert_equal person, person.reload
|
|
1072
|
+
end
|
|
1073
|
+
|
|
1074
|
+
def test_create
|
|
1075
|
+
rick = Person.create(name: "Rick")
|
|
1076
|
+
assert rick.valid?
|
|
1077
|
+
assert_not rick.new?
|
|
1078
|
+
assert_equal "5", rick.id
|
|
1079
|
+
|
|
1080
|
+
# test additional attribute returned on create
|
|
1081
|
+
assert_equal 25, rick.age
|
|
1082
|
+
|
|
1083
|
+
# Test that save exceptions get bubbled up too
|
|
1084
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1085
|
+
mock.post "/people.json", {}, nil, 409
|
|
1086
|
+
end
|
|
1087
|
+
assert_raise(ActiveResource::ResourceConflict) { Person.create(name: "Rick") }
|
|
1088
|
+
end
|
|
1089
|
+
|
|
1090
|
+
def test_create_without_location
|
|
1091
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1092
|
+
mock.post "/people.json", {}, nil, 201
|
|
1093
|
+
end
|
|
1094
|
+
person = Person.create(name: "Rick")
|
|
1095
|
+
assert_nil person.id
|
|
1096
|
+
end
|
|
1097
|
+
|
|
1098
|
+
def test_create!
|
|
1099
|
+
rick = Person.create(name: "Rick")
|
|
1100
|
+
rick_bang = Person.create!(name: "Rick")
|
|
1101
|
+
|
|
1102
|
+
assert_equal rick.id, rick_bang.id
|
|
1103
|
+
assert_equal rick.age, rick_bang.age
|
|
1104
|
+
|
|
1105
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1106
|
+
mock.post "/people.json", {}, nil, 422
|
|
1107
|
+
end
|
|
1108
|
+
assert_raise(ActiveResource::ResourceInvalid) { Person.create!(name: "Rick") }
|
|
1109
|
+
end
|
|
1110
|
+
|
|
1111
|
+
def test_clone
|
|
1112
|
+
matz = Person.find(1)
|
|
1113
|
+
matz_c = matz.clone
|
|
1114
|
+
assert matz_c.new?
|
|
1115
|
+
matz.attributes.each do |k, v|
|
|
1116
|
+
assert_equal v, matz_c.send(k) if k != Person.primary_key
|
|
1117
|
+
end
|
|
1118
|
+
end
|
|
1119
|
+
|
|
1120
|
+
def test_nested_clone
|
|
1121
|
+
addy = StreetAddress.find(1, params: { person_id: 1 })
|
|
1122
|
+
addy_c = addy.clone
|
|
1123
|
+
assert addy_c.new?
|
|
1124
|
+
addy.attributes.each do |k, v|
|
|
1125
|
+
assert_equal v, addy_c.send(k) if k != StreetAddress.primary_key
|
|
1126
|
+
end
|
|
1127
|
+
assert_equal addy.prefix_options, addy_c.prefix_options
|
|
1128
|
+
end
|
|
1129
|
+
|
|
1130
|
+
def test_complex_clone
|
|
1131
|
+
matz = Person.find(1)
|
|
1132
|
+
matz.address = StreetAddress.find(1, params: { person_id: matz.id })
|
|
1133
|
+
matz.non_ar_hash = { not: "an ARes instance" }
|
|
1134
|
+
matz.non_ar_arr = ["not", "ARes"]
|
|
1135
|
+
matz_c = matz.clone
|
|
1136
|
+
assert matz_c.new?
|
|
1137
|
+
assert_raise(NoMethodError) { matz_c.address }
|
|
1138
|
+
assert_equal matz.non_ar_hash, matz_c.non_ar_hash
|
|
1139
|
+
assert_equal matz.non_ar_arr, matz_c.non_ar_arr
|
|
1140
|
+
|
|
1141
|
+
# Test that actual copy, not just reference copy
|
|
1142
|
+
matz.non_ar_hash[:not] = "changed"
|
|
1143
|
+
assert_not_equal matz.non_ar_hash, matz_c.non_ar_hash
|
|
1144
|
+
end
|
|
1145
|
+
|
|
1146
|
+
def test_update
|
|
1147
|
+
matz = Person.find(:first)
|
|
1148
|
+
matz.name = "David"
|
|
1149
|
+
assert_kind_of Person, matz
|
|
1150
|
+
assert_equal "David", matz.name
|
|
1151
|
+
assert_equal true, matz.save
|
|
1152
|
+
end
|
|
1153
|
+
|
|
1154
|
+
def test_update_with_custom_prefix_with_specific_id
|
|
1155
|
+
addy = StreetAddress.find(1, params: { person_id: 1 })
|
|
1156
|
+
addy.street = "54321 Street"
|
|
1157
|
+
assert_kind_of StreetAddress, addy
|
|
1158
|
+
assert_equal "54321 Street", addy.street
|
|
1159
|
+
addy.save
|
|
1160
|
+
end
|
|
1161
|
+
|
|
1162
|
+
def test_update_with_custom_prefix_without_specific_id
|
|
1163
|
+
addy = StreetAddress.find(:first, params: { person_id: 1 })
|
|
1164
|
+
addy.street = "54321 Lane"
|
|
1165
|
+
assert_kind_of StreetAddress, addy
|
|
1166
|
+
assert_equal "54321 Lane", addy.street
|
|
1167
|
+
addy.save
|
|
1168
|
+
end
|
|
1169
|
+
|
|
1170
|
+
def test_update_conflict
|
|
1171
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1172
|
+
mock.get "/people/2.json", {}, @david
|
|
1173
|
+
mock.put "/people/2.json", @default_request_headers, nil, 409
|
|
1174
|
+
end
|
|
1175
|
+
assert_raise(ActiveResource::ResourceConflict) { Person.find(2).save }
|
|
1176
|
+
end
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
######
|
|
1180
|
+
# update_attribute(s)(!)
|
|
1181
|
+
|
|
1182
|
+
def test_update_attribute_as_symbol
|
|
1183
|
+
matz = Person.first
|
|
1184
|
+
matz.expects(:save).returns(true)
|
|
1185
|
+
|
|
1186
|
+
assert_equal "Matz", matz.name
|
|
1187
|
+
assert matz.update_attribute(:name, "David")
|
|
1188
|
+
assert_equal "David", matz.name
|
|
1189
|
+
end
|
|
1190
|
+
|
|
1191
|
+
def test_update_attribute_as_string
|
|
1192
|
+
matz = Person.first
|
|
1193
|
+
matz.expects(:save).returns(true)
|
|
1194
|
+
|
|
1195
|
+
assert_equal "Matz", matz.name
|
|
1196
|
+
assert matz.update_attribute("name", "David")
|
|
1197
|
+
assert_equal "David", matz.name
|
|
1198
|
+
end
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
def test_update_attributes_as_symbols
|
|
1202
|
+
addy = StreetAddress.first(params: { person_id: 1 })
|
|
1203
|
+
addy.expects(:save).returns(true)
|
|
1204
|
+
|
|
1205
|
+
assert_equal "12345 Street", addy.street
|
|
1206
|
+
assert_equal "Australia", addy.country
|
|
1207
|
+
assert addy.update_attributes(street: "54321 Street", country: "USA")
|
|
1208
|
+
assert_equal "54321 Street", addy.street
|
|
1209
|
+
assert_equal "USA", addy.country
|
|
1210
|
+
end
|
|
1211
|
+
|
|
1212
|
+
def test_update_attributes_as_strings
|
|
1213
|
+
addy = StreetAddress.first(params: { person_id: 1 })
|
|
1214
|
+
addy.expects(:save).returns(true)
|
|
1215
|
+
|
|
1216
|
+
assert_equal "12345 Street", addy.street
|
|
1217
|
+
assert_equal "Australia", addy.country
|
|
1218
|
+
assert addy.update_attributes("street" => "54321 Street", "country" => "USA")
|
|
1219
|
+
assert_equal "54321 Street", addy.street
|
|
1220
|
+
assert_equal "USA", addy.country
|
|
1221
|
+
end
|
|
1222
|
+
|
|
1223
|
+
|
|
1224
|
+
#####
|
|
1225
|
+
# Mayhem and destruction
|
|
1226
|
+
|
|
1227
|
+
def test_destroy
|
|
1228
|
+
assert Person.find(1).destroy
|
|
1229
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1230
|
+
mock.get "/people/1.json", {}, nil, 404
|
|
1231
|
+
end
|
|
1232
|
+
assert_raise(ActiveResource::ResourceNotFound) { Person.find(1).destroy }
|
|
1233
|
+
end
|
|
1234
|
+
|
|
1235
|
+
def test_destroy_with_custom_prefix
|
|
1236
|
+
assert StreetAddress.find(1, params: { person_id: 1 }).destroy
|
|
1237
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1238
|
+
mock.get "/people/1/addresses/1.json", {}, nil, 404
|
|
1239
|
+
end
|
|
1240
|
+
assert_raise(ActiveResource::ResourceNotFound) { StreetAddress.find(1, params: { person_id: 1 }) }
|
|
1241
|
+
end
|
|
1242
|
+
|
|
1243
|
+
def test_destroy_with_410_gone
|
|
1244
|
+
assert Person.find(1).destroy
|
|
1245
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1246
|
+
mock.get "/people/1.json", {}, nil, 410
|
|
1247
|
+
end
|
|
1248
|
+
assert_raise(ActiveResource::ResourceGone) { Person.find(1).destroy }
|
|
1249
|
+
end
|
|
1250
|
+
|
|
1251
|
+
def test_delete
|
|
1252
|
+
assert Person.delete(1)
|
|
1253
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1254
|
+
mock.get "/people/1.json", {}, nil, 404
|
|
1255
|
+
end
|
|
1256
|
+
assert_raise(ActiveResource::ResourceNotFound) { Person.find(1) }
|
|
1257
|
+
end
|
|
1258
|
+
|
|
1259
|
+
def test_delete_with_custom_prefix
|
|
1260
|
+
assert StreetAddress.delete(1, person_id: 1)
|
|
1261
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1262
|
+
mock.get "/people/1/addresses/1.json", {}, nil, 404
|
|
1263
|
+
end
|
|
1264
|
+
assert_raise(ActiveResource::ResourceNotFound) { StreetAddress.find(1, params: { person_id: 1 }) }
|
|
1265
|
+
end
|
|
1266
|
+
|
|
1267
|
+
def test_delete_with_410_gone
|
|
1268
|
+
assert Person.delete(1)
|
|
1269
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1270
|
+
mock.get "/people/1.json", {}, nil, 410
|
|
1271
|
+
end
|
|
1272
|
+
assert_raise(ActiveResource::ResourceGone) { Person.find(1) }
|
|
1273
|
+
end
|
|
1274
|
+
|
|
1275
|
+
def test_delete_with_custom_header
|
|
1276
|
+
Person.headers["key"] = "value"
|
|
1277
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1278
|
+
mock.delete "/people/1.json", {}, nil, 200
|
|
1279
|
+
mock.delete "/people/1.json", { "key" => "value" }, nil, 404
|
|
1280
|
+
end
|
|
1281
|
+
assert_raise(ActiveResource::ResourceNotFound) { Person.delete(1) }
|
|
1282
|
+
ensure
|
|
1283
|
+
Person.headers.delete("key")
|
|
1284
|
+
end
|
|
1285
|
+
|
|
1286
|
+
########################################################################
|
|
1287
|
+
# Tests the more miscellaneous helper methods
|
|
1288
|
+
########################################################################
|
|
1289
|
+
def test_exists
|
|
1290
|
+
# Class method.
|
|
1291
|
+
assert_equal false, Person.exists?(nil)
|
|
1292
|
+
assert_equal true, Person.exists?(1)
|
|
1293
|
+
assert_equal false, Person.exists?(99)
|
|
1294
|
+
|
|
1295
|
+
# Instance method.
|
|
1296
|
+
assert_equal false, Person.new.exists?
|
|
1297
|
+
assert_equal true, Person.find(1).exists?
|
|
1298
|
+
assert_equal false, Person.new(id: 99).exists?
|
|
1299
|
+
|
|
1300
|
+
# Nested class method.
|
|
1301
|
+
assert_equal true, StreetAddress.exists?(1, params: { person_id: 1 })
|
|
1302
|
+
assert_equal false, StreetAddress.exists?(1, params: { person_id: 2 })
|
|
1303
|
+
assert_equal false, StreetAddress.exists?(2, params: { person_id: 1 })
|
|
1304
|
+
|
|
1305
|
+
# Nested instance method.
|
|
1306
|
+
assert_equal true, StreetAddress.find(1, params: { person_id: 1 }).exists?
|
|
1307
|
+
assert_equal false, StreetAddress.new(id: 1, person_id: 2).exists?
|
|
1308
|
+
assert_equal false, StreetAddress.new(id: 2, person_id: 1).exists?
|
|
1309
|
+
end
|
|
1310
|
+
|
|
1311
|
+
def test_exists_with_redefined_to_param
|
|
1312
|
+
Person.module_eval do
|
|
1313
|
+
alias_method :original_to_param_exists, :to_param
|
|
1314
|
+
def to_param
|
|
1315
|
+
name
|
|
1316
|
+
end
|
|
1317
|
+
end
|
|
1318
|
+
|
|
1319
|
+
# Class method.
|
|
1320
|
+
assert Person.exists?("Greg")
|
|
1321
|
+
|
|
1322
|
+
# Instance method.
|
|
1323
|
+
assert Person.find("Greg").exists?
|
|
1324
|
+
|
|
1325
|
+
# Nested class method.
|
|
1326
|
+
assert StreetAddress.exists?(1, params: { person_id: Person.find("Greg").to_param })
|
|
1327
|
+
|
|
1328
|
+
# Nested instance method.
|
|
1329
|
+
assert StreetAddress.find(1, params: { person_id: Person.find("Greg").to_param }).exists?
|
|
1330
|
+
|
|
1331
|
+
ensure
|
|
1332
|
+
# revert back to original
|
|
1333
|
+
Person.module_eval do
|
|
1334
|
+
# save the 'new' to_param so we don't get a warning about discarding the method
|
|
1335
|
+
alias_method :exists_to_param, :to_param
|
|
1336
|
+
alias_method :to_param, :original_to_param_exists
|
|
1337
|
+
end
|
|
1338
|
+
end
|
|
1339
|
+
|
|
1340
|
+
def test_exists_without_http_mock
|
|
1341
|
+
http = Net::HTTP.new(Person.site.host, Person.site.port)
|
|
1342
|
+
ActiveResource::Connection.any_instance.expects(:http).returns(http)
|
|
1343
|
+
http.expects(:request).returns(ActiveResource::Response.new(""))
|
|
1344
|
+
|
|
1345
|
+
assert Person.exists?("not-mocked")
|
|
1346
|
+
end
|
|
1347
|
+
|
|
1348
|
+
def test_exists_with_410_gone
|
|
1349
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1350
|
+
mock.head "/people/1.json", {}, nil, 410
|
|
1351
|
+
end
|
|
1352
|
+
|
|
1353
|
+
assert_not Person.exists?(1)
|
|
1354
|
+
end
|
|
1355
|
+
|
|
1356
|
+
def test_exists_with_204_no_content
|
|
1357
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1358
|
+
mock.head "/people/1.json", {}, nil, 204
|
|
1359
|
+
end
|
|
1360
|
+
|
|
1361
|
+
assert Person.exists?(1)
|
|
1362
|
+
end
|
|
1363
|
+
|
|
1364
|
+
def test_read_attribute_for_serialization
|
|
1365
|
+
joe = Person.find(6)
|
|
1366
|
+
joe.singleton_class.class_eval do
|
|
1367
|
+
def non_attribute_field
|
|
1368
|
+
"foo"
|
|
1369
|
+
end
|
|
1370
|
+
|
|
1371
|
+
def id
|
|
1372
|
+
"bar"
|
|
1373
|
+
end
|
|
1374
|
+
end
|
|
1375
|
+
|
|
1376
|
+
assert_equal joe.read_attribute_for_serialization(:id), 6
|
|
1377
|
+
assert_equal joe.read_attribute_for_serialization(:name), "Joe"
|
|
1378
|
+
assert_equal joe.read_attribute_for_serialization(:likes_hats), true
|
|
1379
|
+
assert_equal joe.read_attribute_for_serialization(:non_attribute_field), "foo"
|
|
1380
|
+
end
|
|
1381
|
+
|
|
1382
|
+
def test_to_xml
|
|
1383
|
+
Person.format = :xml
|
|
1384
|
+
matz = Person.find(1)
|
|
1385
|
+
encode = matz.encode
|
|
1386
|
+
xml = matz.to_xml
|
|
1387
|
+
|
|
1388
|
+
assert_equal encode, xml
|
|
1389
|
+
assert xml.include?('<?xml version="1.0" encoding="UTF-8"?>')
|
|
1390
|
+
assert xml.include?("<name>Matz</name>")
|
|
1391
|
+
assert xml.include?('<id type="integer">1</id>')
|
|
1392
|
+
ensure
|
|
1393
|
+
Person.format = :json
|
|
1394
|
+
end
|
|
1395
|
+
|
|
1396
|
+
def test_to_xml_with_element_name
|
|
1397
|
+
Person.format = :xml
|
|
1398
|
+
old_elem_name = Person.element_name
|
|
1399
|
+
matz = Person.find(1)
|
|
1400
|
+
Person.element_name = "ruby_creator"
|
|
1401
|
+
encode = matz.encode
|
|
1402
|
+
xml = matz.to_xml
|
|
1403
|
+
|
|
1404
|
+
assert_equal encode, xml
|
|
1405
|
+
assert xml.include?('<?xml version="1.0" encoding="UTF-8"?>')
|
|
1406
|
+
assert xml.include?("<ruby-creator>")
|
|
1407
|
+
assert xml.include?("<name>Matz</name>")
|
|
1408
|
+
assert xml.include?('<id type="integer">1</id>')
|
|
1409
|
+
assert xml.include?("</ruby-creator>")
|
|
1410
|
+
ensure
|
|
1411
|
+
Person.format = :json
|
|
1412
|
+
Person.element_name = old_elem_name
|
|
1413
|
+
end
|
|
1414
|
+
|
|
1415
|
+
def test_to_xml_with_private_method_name_as_attribute
|
|
1416
|
+
Person.format = :xml
|
|
1417
|
+
|
|
1418
|
+
customer = Customer.new(foo: "foo")
|
|
1419
|
+
customer.singleton_class.class_eval do
|
|
1420
|
+
def foo
|
|
1421
|
+
"bar"
|
|
1422
|
+
end
|
|
1423
|
+
private :foo
|
|
1424
|
+
end
|
|
1425
|
+
|
|
1426
|
+
assert_not customer.to_xml.include?("<foo>bar</foo>")
|
|
1427
|
+
assert customer.to_xml.include?("<foo>foo</foo>")
|
|
1428
|
+
ensure
|
|
1429
|
+
Person.format = :json
|
|
1430
|
+
end
|
|
1431
|
+
|
|
1432
|
+
def test_to_json
|
|
1433
|
+
joe = Person.find(6)
|
|
1434
|
+
encode = joe.encode
|
|
1435
|
+
json = joe.to_json
|
|
1436
|
+
|
|
1437
|
+
assert_equal encode, json
|
|
1438
|
+
assert_match %r{^\{"person":\{}, json
|
|
1439
|
+
assert_match %r{"id":6}, json
|
|
1440
|
+
assert_match %r{"name":"Joe"}, json
|
|
1441
|
+
assert_match %r{\}\}$}, json
|
|
1442
|
+
end
|
|
1443
|
+
|
|
1444
|
+
def test_to_json_without_root
|
|
1445
|
+
ActiveResource::Base.include_root_in_json = false
|
|
1446
|
+
joe = Person.find(6)
|
|
1447
|
+
encode = joe.encode
|
|
1448
|
+
json = joe.to_json
|
|
1449
|
+
|
|
1450
|
+
assert_equal encode, json
|
|
1451
|
+
assert_match %r{^\{"id":6}, json
|
|
1452
|
+
assert_match %r{"name":"Joe"}, json
|
|
1453
|
+
assert_match %r{\}$}, json
|
|
1454
|
+
ensure
|
|
1455
|
+
ActiveResource::Base.include_root_in_json = true
|
|
1456
|
+
end
|
|
1457
|
+
|
|
1458
|
+
def test_to_json_with_element_name
|
|
1459
|
+
old_elem_name = Person.element_name
|
|
1460
|
+
joe = Person.find(6)
|
|
1461
|
+
Person.element_name = "ruby_creator"
|
|
1462
|
+
encode = joe.encode
|
|
1463
|
+
json = joe.to_json
|
|
1464
|
+
|
|
1465
|
+
assert_equal encode, json
|
|
1466
|
+
assert_match %r{^\{"ruby_creator":\{}, json
|
|
1467
|
+
assert_match %r{"id":6}, json
|
|
1468
|
+
assert_match %r{"name":"Joe"}, json
|
|
1469
|
+
assert_match %r{\}\}$}, json
|
|
1470
|
+
ensure
|
|
1471
|
+
Person.element_name = old_elem_name
|
|
1472
|
+
end
|
|
1473
|
+
|
|
1474
|
+
def test_to_param_quacks_like_active_record
|
|
1475
|
+
new_person = Person.new
|
|
1476
|
+
assert_nil new_person.to_param
|
|
1477
|
+
matz = Person.find(1)
|
|
1478
|
+
assert_equal "1", matz.to_param
|
|
1479
|
+
end
|
|
1480
|
+
|
|
1481
|
+
def test_to_key_quacks_like_active_record
|
|
1482
|
+
new_person = Person.new
|
|
1483
|
+
assert_nil new_person.to_key
|
|
1484
|
+
matz = Person.find(1)
|
|
1485
|
+
assert_equal [1], matz.to_key
|
|
1486
|
+
end
|
|
1487
|
+
|
|
1488
|
+
def test_parse_deep_nested_resources
|
|
1489
|
+
luis = Customer.find(1)
|
|
1490
|
+
assert_kind_of Customer, luis
|
|
1491
|
+
luis.friends.each do |friend|
|
|
1492
|
+
assert_kind_of Customer::Friend, friend
|
|
1493
|
+
friend.brothers.each do |brother|
|
|
1494
|
+
assert_kind_of Customer::Friend::Brother, brother
|
|
1495
|
+
brother.children.each do |child|
|
|
1496
|
+
assert_kind_of Customer::Friend::Brother::Child, child
|
|
1497
|
+
end
|
|
1498
|
+
end
|
|
1499
|
+
end
|
|
1500
|
+
end
|
|
1501
|
+
|
|
1502
|
+
def test_persisted_nested_resources_from_response
|
|
1503
|
+
luis = Customer.find(1)
|
|
1504
|
+
luis.friends.each do |friend|
|
|
1505
|
+
assert_not friend.new?
|
|
1506
|
+
friend.brothers.each do |brother|
|
|
1507
|
+
assert_not brother.new?
|
|
1508
|
+
brother.children.each do |child|
|
|
1509
|
+
assert_not child.new?
|
|
1510
|
+
end
|
|
1511
|
+
end
|
|
1512
|
+
end
|
|
1513
|
+
end
|
|
1514
|
+
|
|
1515
|
+
def test_parse_resource_with_given_has_one_resources
|
|
1516
|
+
Customer.send(:has_one, :mother, class_name: "external/person")
|
|
1517
|
+
luis = Customer.find(1)
|
|
1518
|
+
assert_kind_of External::Person, luis.mother
|
|
1519
|
+
end
|
|
1520
|
+
|
|
1521
|
+
def test_parse_resources_with_given_has_many_resources
|
|
1522
|
+
Customer.send(:has_many, :enemies, class_name: "external/person")
|
|
1523
|
+
luis = Customer.find(1)
|
|
1524
|
+
luis.enemies.each do |enemy|
|
|
1525
|
+
assert_kind_of External::Person, enemy
|
|
1526
|
+
end
|
|
1527
|
+
end
|
|
1528
|
+
|
|
1529
|
+
def test_parse_resources_with_has_many_makes_get_request_on_nested_route
|
|
1530
|
+
Post.send(:has_many, :comments)
|
|
1531
|
+
post = Post.find(1)
|
|
1532
|
+
post.comments.each do |comment|
|
|
1533
|
+
assert_kind_of Comment, comment
|
|
1534
|
+
end
|
|
1535
|
+
end
|
|
1536
|
+
|
|
1537
|
+
def test_parse_resource_with_has_one_makes_get_request_on_child_route
|
|
1538
|
+
Product.send(:has_one, :inventory)
|
|
1539
|
+
product = Product.find(1)
|
|
1540
|
+
assert product.inventory.status == ActiveSupport::JSON.decode(@inventory)["status"]
|
|
1541
|
+
end
|
|
1542
|
+
|
|
1543
|
+
def test_parse_non_singleton_resource_with_has_one_makes_get_request_on_child_route
|
|
1544
|
+
accepts = { "Accept" => "application/json" }
|
|
1545
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1546
|
+
mock.get "/posts/1.json", accepts, @post
|
|
1547
|
+
mock.get "/posts/1/author.json", accepts, @matz
|
|
1548
|
+
end
|
|
1549
|
+
|
|
1550
|
+
Post.send(:has_one, :author, class_name: "Person")
|
|
1551
|
+
post = Post.find(1)
|
|
1552
|
+
assert post.author.name == ActiveSupport::JSON.decode(@matz)["person"]["name"]
|
|
1553
|
+
end
|
|
1554
|
+
|
|
1555
|
+
def test_with_custom_formatter
|
|
1556
|
+
addresses = [{ id: "1", street: "1 Infinite Loop", city: "Cupertino", state: "CA" }].to_xml(root: :addresses)
|
|
1557
|
+
|
|
1558
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1559
|
+
mock.get "/addresses.xml", {}, addresses, 200
|
|
1560
|
+
end
|
|
1561
|
+
|
|
1562
|
+
# late bind the site
|
|
1563
|
+
AddressResource.site = "http://localhost"
|
|
1564
|
+
addresses = AddressResource.find(:all)
|
|
1565
|
+
|
|
1566
|
+
assert_equal "Cupertino, CA", addresses.first.city_state
|
|
1567
|
+
end
|
|
1568
|
+
|
|
1569
|
+
def test_create_with_custom_primary_key
|
|
1570
|
+
silver_plan = { plan: { code: "silver", price: 5.00 } }.to_json
|
|
1571
|
+
|
|
1572
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1573
|
+
mock.post "/plans.json", {}, silver_plan, 201, "Location" => "/plans/silver.json"
|
|
1574
|
+
end
|
|
1575
|
+
|
|
1576
|
+
plan = SubscriptionPlan.new(code: "silver", price: 5.00)
|
|
1577
|
+
assert plan.new?
|
|
1578
|
+
|
|
1579
|
+
plan.save!
|
|
1580
|
+
assert_not plan.new?
|
|
1581
|
+
end
|
|
1582
|
+
|
|
1583
|
+
def test_update_with_custom_primary_key
|
|
1584
|
+
silver_plan = { plan: { code: "silver", price: 5.00 } }.to_json
|
|
1585
|
+
silver_plan_updated = { plan: { code: "silver", price: 10.00 } }.to_json
|
|
1586
|
+
|
|
1587
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
1588
|
+
mock.get "/plans/silver.json", {}, silver_plan
|
|
1589
|
+
mock.put "/plans/silver.json", {}, silver_plan_updated, 201, "Location" => "/plans/silver.json"
|
|
1590
|
+
end
|
|
1591
|
+
|
|
1592
|
+
plan = SubscriptionPlan.find("silver")
|
|
1593
|
+
assert_not plan.new?
|
|
1594
|
+
assert_equal 5.00, plan.price
|
|
1595
|
+
|
|
1596
|
+
# update price
|
|
1597
|
+
plan.price = 10.00
|
|
1598
|
+
plan.save!
|
|
1599
|
+
assert_equal 10.00, plan.price
|
|
1600
|
+
end
|
|
1601
|
+
|
|
1602
|
+
def test_namespacing
|
|
1603
|
+
sound = Asset::Sound.find(1)
|
|
1604
|
+
assert_equal "Asset::Sound::Author", sound.author.class.to_s
|
|
1605
|
+
end
|
|
1606
|
+
|
|
1607
|
+
def test_paths_with_format
|
|
1608
|
+
assert_equal "/customers.json", Customer.collection_path
|
|
1609
|
+
assert_equal "/customers/1.json", Customer.element_path(1)
|
|
1610
|
+
assert_equal "/customers/new.json", Customer.new_element_path
|
|
1611
|
+
end
|
|
1612
|
+
|
|
1613
|
+
def test_paths_without_format
|
|
1614
|
+
ActiveResource::Base.include_format_in_path = false
|
|
1615
|
+
assert_equal "/customers", Customer.collection_path
|
|
1616
|
+
assert_equal "/customers/1", Customer.element_path(1)
|
|
1617
|
+
assert_equal "/customers/new", Customer.new_element_path
|
|
1618
|
+
|
|
1619
|
+
ensure
|
|
1620
|
+
ActiveResource::Base.include_format_in_path = true
|
|
1621
|
+
end
|
|
1622
|
+
end
|