├── .gitignore ├── .travis.yml ├── Appraisals ├── Gemfile ├── Gemfile.lock ├── LICENSE.txt ├── README.md ├── Rakefile ├── gemfiles ├── rails_3.0.0_jbuilder_1.5.0.gemfile ├── rails_3.0.0_jbuilder_1.5.0.gemfile.lock ├── rails_3.0.0_jbuilder_2.0.0.gemfile ├── rails_3.0.0_jbuilder_2.0.0.gemfile.lock ├── rails_3.1.0_jbuilder_1.5.0.gemfile ├── rails_3.1.0_jbuilder_1.5.0.gemfile.lock ├── rails_3.1.0_jbuilder_2.0.0.gemfile ├── rails_3.1.0_jbuilder_2.0.0.gemfile.lock ├── rails_3.2.0_jbuilder_1.5.0.gemfile ├── rails_3.2.0_jbuilder_1.5.0.gemfile.lock ├── rails_3.2.0_jbuilder_2.0.0.gemfile ├── rails_3.2.0_jbuilder_2.0.0.gemfile.lock ├── rails_4.0.0_jbuilder_1.5.0.gemfile ├── rails_4.0.0_jbuilder_1.5.0.gemfile.lock ├── rails_4.0.0_jbuilder_2.0.0.gemfile ├── rails_4.0.0_jbuilder_2.0.0.gemfile.lock ├── rails_4.1.0_jbuilder_1.5.0.gemfile ├── rails_4.1.0_jbuilder_1.5.0.gemfile.lock ├── rails_4.1.0_jbuilder_2.0.0.gemfile ├── rails_4.1.0_jbuilder_2.0.0.gemfile.lock ├── rails_5.0.0_jbuilder_1.5.0.gemfile ├── rails_5.0.0_jbuilder_1.5.0.gemfile.lock ├── rails_5.0.0_jbuilder_2.0.0.gemfile └── rails_5.0.0_jbuilder_2.0.0.gemfile.lock ├── jbuilder_cache_multi.gemspec ├── lib ├── jbuilder_cache_multi.rb └── jbuilder_cache_multi │ ├── jbuilder_ext.rb │ └── version.rb └── test ├── jbuilder_template_test.rb └── test_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | .ruby-gemset 7 | .ruby-version 8 | InstalledFiles 9 | _yardoc 10 | coverage 11 | doc/ 12 | lib/bundler/man 13 | pkg 14 | rdoc 15 | spec/reports 16 | test/tmp 17 | test/version_tmp 18 | tmp 19 | *.bundle 20 | *.so 21 | *.o 22 | *.a 23 | mkmf.log 24 | 25 | /vendor/ 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - "2.2.3" 4 | gemfile: 5 | - gemfiles/rails_3.0.0_jbuilder_1.5.0.gemfile 6 | - gemfiles/rails_3.0.0_jbuilder_2.0.0.gemfile 7 | - gemfiles/rails_3.1.0_jbuilder_1.5.0.gemfile 8 | - gemfiles/rails_3.1.0_jbuilder_2.0.0.gemfile 9 | - gemfiles/rails_3.2.0_jbuilder_1.5.0.gemfile 10 | - gemfiles/rails_3.2.0_jbuilder_2.0.0.gemfile 11 | - gemfiles/rails_4.0.0_jbuilder_1.5.0.gemfile 12 | - gemfiles/rails_4.0.0_jbuilder_2.0.0.gemfile 13 | - gemfiles/rails_4.1.0_jbuilder_1.5.0.gemfile 14 | - gemfiles/rails_4.1.0_jbuilder_2.0.0.gemfile -------------------------------------------------------------------------------- /Appraisals: -------------------------------------------------------------------------------- 1 | rails_versions = ["~> 3.0.0", "~> 3.1.0", "~> 3.2.0", "~> 4.0.0", "~> 4.1.0", "~> 5.0.0"] 2 | jbuilder_versions = ["~> 1.5.0", "~> 2.0.0"] 3 | 4 | rails_versions.each do |r| 5 | jbuilder_versions.each do |j| 6 | appraise "rails_#{r.match(/\d.*/)} jbuilder_#{j.match(/\d.*/)}" do 7 | gem "railties", r 8 | gem "actionpack", r 9 | gem "jbuilder", j 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec 4 | 5 | gem "rake" 6 | gem "mocha", require: false 7 | gem "appraisal" 8 | gem "test-unit" -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | jbuilder_cache_multi (0.1.0) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | activesupport (5.1.1) 11 | concurrent-ruby (~> 1.0, >= 1.0.2) 12 | i18n (~> 0.7) 13 | minitest (~> 5.1) 14 | tzinfo (~> 1.1) 15 | appraisal (2.1.0) 16 | bundler 17 | rake 18 | thor (>= 0.14.0) 19 | concurrent-ruby (1.0.5) 20 | i18n (0.8.4) 21 | jbuilder (2.7.0) 22 | activesupport (>= 4.2.0) 23 | multi_json (>= 1.2) 24 | metaclass (0.0.4) 25 | minitest (5.10.2) 26 | mocha (1.1.0) 27 | metaclass (~> 0.0.1) 28 | multi_json (1.12.1) 29 | power_assert (0.2.2) 30 | rake (10.4.2) 31 | test-unit (3.0.8) 32 | power_assert 33 | thor (0.19.1) 34 | thread_safe (0.3.6) 35 | tzinfo (1.2.3) 36 | thread_safe (~> 0.1) 37 | 38 | PLATFORMS 39 | ruby 40 | 41 | DEPENDENCIES 42 | appraisal 43 | jbuilder_cache_multi! 44 | mocha 45 | rake 46 | test-unit 47 | 48 | BUNDLED WITH 49 | 1.15.1 50 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Yonah Forst 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JbuilderCacheMulti 2 | 3 | Useful when you need to retrieve fragments for a collection of objects from the cache. This plugin gives you method called 'cache_collection!' which uses fetch_multi (new in Rails 4.1) to retrieve multiple keys in a single go. 4 | 5 | This means less queries to the cache == faster responses. If items are not found, they are writen to the cache (individualy. memcache doesn't support writing items in batch...yet). 6 | 7 | Tested with Rails 4.1 + Memcached + Dalli 8 | 9 | ## Installation 10 | 11 | Add this line to your application's Gemfile: 12 | 13 | gem 'jbuilder_cache_multi' 14 | 15 | And then execute: 16 | 17 | $ bundle 18 | 19 | Or install it yourself as: 20 | 21 | $ gem install jbuilder_cache_multi 22 | 23 | ## Usage 24 | 25 | Renders the given block for each item in the collection. Accepts optional 'key' attribute in options (e.g. key: 'v1'). 26 | 27 | Note: At the moment, does not accept the partial name as an argument (#todo) 28 | 29 | Examples: 30 | 31 | json.cache_collection! @people, expires_in: 10.minutes do |person| 32 | json.partial! 'person', :person => person 33 | end 34 | 35 | # Or with optional key 36 | 37 | json.cache_collection! @people, expires_in: 10.minutes, key: 'v1' do |person| 38 | json.partial! 'person', :person => person 39 | end 40 | 41 | # Or with a proc as a key 42 | 43 | json.cache_collection! @people, expires_in: 10.minutes, key: proc {|person| person.last_posted_at } do |person| 44 | json.partial! 'person', :person => person 45 | end 46 | 47 | NOTE: If the items in your collection don't change frequently, it might be better to cache the entire collection like this: 48 | (in which case you don't need this gem) 49 | 50 | json.cache! @people do 51 | json.partial! 'person', collection: @people, as: :person 52 | end 53 | 54 | Or you can use a combination of both! 55 | This will cache the entire collection. If a single item changes it will use read_multi to get all unchanged items and regenerate only the changed item(s). 56 | 57 | json.cache! @people do 58 | json.cache_collection! @people do |person| 59 | json.partial! 'person', :person => person 60 | end 61 | end 62 | 63 | Last thing: If you are using a collection for the cache key, may I recommend the 'scope_cache_key' gem? (check out my fork for a Rails 4 version: https://github.com/joshblour/scope_cache_key). It very quickly calculates a hash for all items in the collection (MD5 hash of updated_at + IDs). 64 | 65 | You can also conditionally cache a block by using `cache_collection_if!` like this: 66 | 67 | json.cache_collection_if! do_cache?, @people, expires_in: 10.minutes do |person| 68 | json.partial! 'person', :person => person 69 | end 70 | 71 | ## Todo 72 | 73 | - Add support for passing a partial name as an argument (e.g. json.cache_collection! @people, partial: 'person') or maybe even just "json.cache_collection! @people" and infer the partial name from the collection... 74 | 75 | - When rendering other partials, use the hash of THAT partial for the cache_key (I beleieve it currently uses the view from where cache_collection! is called to calculate the cache_key) #not_good 76 | 77 | ## Contributing 78 | 79 | 1. Fork it ( https://github.com/joshblour/jbuilder_cache_multi/fork ) 80 | 2. Create your feature branch (`git checkout -b my-new-feature`) 81 | 3. Commit your changes (`git commit -am 'Add some feature'`) 82 | 4. Push to the branch (`git push origin my-new-feature`) 83 | 5. Create a new Pull Request 84 | 85 | ## Testing 86 | bundle install 87 | appraisal install 88 | appraisal rake test 89 | 90 | ## Credit 91 | Inspired by https://github.com/n8/multi_fetch_fragments. Thank you! 92 | And of course https://github.com/rails/jbuilder 93 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/setup" 2 | require "rake/testtask" 3 | 4 | if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"] 5 | require "appraisal/task" 6 | Appraisal::Task.new 7 | task default: :appraisal 8 | else 9 | Rake::TestTask.new do |test| 10 | require "rails/version" 11 | 12 | test.libs << "test" 13 | 14 | if Rails::VERSION::MAJOR == 3 15 | test.test_files = %w[test/jbuilder_template_test.rb] 16 | else 17 | test.test_files = FileList["test/*_test.rb"] 18 | end 19 | end 20 | 21 | task default: :test 22 | end 23 | -------------------------------------------------------------------------------- /gemfiles/rails_3.0.0_jbuilder_1.5.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 3.0.0" 10 | gem "actionpack", "~> 3.0.0" 11 | gem "jbuilder", "~> 1.5.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_3.0.0_jbuilder_1.5.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | abstract (1.0.0) 11 | actionpack (3.0.20) 12 | activemodel (= 3.0.20) 13 | activesupport (= 3.0.20) 14 | builder (~> 2.1.2) 15 | erubis (~> 2.6.6) 16 | i18n (~> 0.5.0) 17 | rack (~> 1.2.5) 18 | rack-mount (~> 0.6.14) 19 | rack-test (~> 0.5.7) 20 | tzinfo (~> 0.3.23) 21 | activemodel (3.0.20) 22 | activesupport (= 3.0.20) 23 | builder (~> 2.1.2) 24 | i18n (~> 0.5.0) 25 | activesupport (3.0.20) 26 | appraisal (2.1.0) 27 | bundler 28 | rake 29 | thor (>= 0.14.0) 30 | builder (2.1.2) 31 | erubis (2.6.6) 32 | abstract (>= 1.0.0) 33 | i18n (0.5.4) 34 | jbuilder (1.5.3) 35 | activesupport (>= 3.0.0) 36 | multi_json (>= 1.2.0) 37 | json (1.8.3) 38 | metaclass (0.0.4) 39 | mocha (1.1.0) 40 | metaclass (~> 0.0.1) 41 | multi_json (1.11.2) 42 | power_assert (0.2.2) 43 | rack (1.2.8) 44 | rack-mount (0.6.14) 45 | rack (>= 1.0.0) 46 | rack-test (0.5.7) 47 | rack (>= 1.0) 48 | railties (3.0.20) 49 | actionpack (= 3.0.20) 50 | activesupport (= 3.0.20) 51 | rake (>= 0.8.7) 52 | rdoc (~> 3.4) 53 | thor (~> 0.14.4) 54 | rake (10.4.2) 55 | rdoc (3.12.2) 56 | json (~> 1.4) 57 | test-unit (3.0.8) 58 | power_assert 59 | thor (0.14.6) 60 | tzinfo (0.3.44) 61 | 62 | PLATFORMS 63 | ruby 64 | 65 | DEPENDENCIES 66 | actionpack (~> 3.0.0) 67 | appraisal 68 | jbuilder (~> 1.5.0) 69 | jbuilder_cache_multi! 70 | mocha 71 | railties (~> 3.0.0) 72 | rake 73 | test-unit 74 | 75 | BUNDLED WITH 76 | 1.14.6 77 | -------------------------------------------------------------------------------- /gemfiles/rails_3.0.0_jbuilder_2.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 3.0.0" 10 | gem "actionpack", "~> 3.0.0" 11 | gem "jbuilder", "~> 2.0.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_3.0.0_jbuilder_2.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | abstract (1.0.0) 11 | actionpack (3.0.20) 12 | activemodel (= 3.0.20) 13 | activesupport (= 3.0.20) 14 | builder (~> 2.1.2) 15 | erubis (~> 2.6.6) 16 | i18n (~> 0.5.0) 17 | rack (~> 1.2.5) 18 | rack-mount (~> 0.6.14) 19 | rack-test (~> 0.5.7) 20 | tzinfo (~> 0.3.23) 21 | activemodel (3.0.20) 22 | activesupport (= 3.0.20) 23 | builder (~> 2.1.2) 24 | i18n (~> 0.5.0) 25 | activesupport (3.0.20) 26 | appraisal (2.1.0) 27 | bundler 28 | rake 29 | thor (>= 0.14.0) 30 | builder (2.1.2) 31 | erubis (2.6.6) 32 | abstract (>= 1.0.0) 33 | i18n (0.5.4) 34 | jbuilder (2.0.8) 35 | activesupport (>= 3.0.0, < 5) 36 | multi_json (~> 1.2) 37 | json (1.8.3) 38 | metaclass (0.0.4) 39 | mocha (1.1.0) 40 | metaclass (~> 0.0.1) 41 | multi_json (1.11.2) 42 | power_assert (0.2.2) 43 | rack (1.2.8) 44 | rack-mount (0.6.14) 45 | rack (>= 1.0.0) 46 | rack-test (0.5.7) 47 | rack (>= 1.0) 48 | railties (3.0.20) 49 | actionpack (= 3.0.20) 50 | activesupport (= 3.0.20) 51 | rake (>= 0.8.7) 52 | rdoc (~> 3.4) 53 | thor (~> 0.14.4) 54 | rake (10.4.2) 55 | rdoc (3.12.2) 56 | json (~> 1.4) 57 | test-unit (3.0.8) 58 | power_assert 59 | thor (0.14.6) 60 | tzinfo (0.3.44) 61 | 62 | PLATFORMS 63 | ruby 64 | 65 | DEPENDENCIES 66 | actionpack (~> 3.0.0) 67 | appraisal 68 | jbuilder (~> 2.0.0) 69 | jbuilder_cache_multi! 70 | mocha 71 | railties (~> 3.0.0) 72 | rake 73 | test-unit 74 | 75 | BUNDLED WITH 76 | 1.14.6 77 | -------------------------------------------------------------------------------- /gemfiles/rails_3.1.0_jbuilder_1.5.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 3.1.0" 10 | gem "actionpack", "~> 3.1.0" 11 | gem "jbuilder", "~> 1.5.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_3.1.0_jbuilder_1.5.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionpack (3.1.12) 11 | activemodel (= 3.1.12) 12 | activesupport (= 3.1.12) 13 | builder (~> 3.0.0) 14 | erubis (~> 2.7.0) 15 | i18n (~> 0.6) 16 | rack (~> 1.3.6) 17 | rack-cache (~> 1.2) 18 | rack-mount (~> 0.8.2) 19 | rack-test (~> 0.6.1) 20 | sprockets (~> 2.0.4) 21 | activemodel (3.1.12) 22 | activesupport (= 3.1.12) 23 | builder (~> 3.0.0) 24 | i18n (~> 0.6) 25 | activesupport (3.1.12) 26 | multi_json (~> 1.0) 27 | appraisal (2.1.0) 28 | bundler 29 | rake 30 | thor (>= 0.14.0) 31 | builder (3.0.4) 32 | erubis (2.7.0) 33 | hike (1.2.3) 34 | i18n (0.7.0) 35 | jbuilder (1.5.3) 36 | activesupport (>= 3.0.0) 37 | multi_json (>= 1.2.0) 38 | json (1.8.3) 39 | metaclass (0.0.4) 40 | mocha (1.1.0) 41 | metaclass (~> 0.0.1) 42 | multi_json (1.11.2) 43 | power_assert (0.2.2) 44 | rack (1.3.10) 45 | rack-cache (1.2) 46 | rack (>= 0.4) 47 | rack-mount (0.8.3) 48 | rack (>= 1.0.0) 49 | rack-ssl (1.3.4) 50 | rack 51 | rack-test (0.6.3) 52 | rack (>= 1.0) 53 | railties (3.1.12) 54 | actionpack (= 3.1.12) 55 | activesupport (= 3.1.12) 56 | rack-ssl (~> 1.3.2) 57 | rake (>= 0.8.7) 58 | rdoc (~> 3.4) 59 | thor (~> 0.14.6) 60 | rake (10.4.2) 61 | rdoc (3.12.2) 62 | json (~> 1.4) 63 | sprockets (2.0.5) 64 | hike (~> 1.2) 65 | rack (~> 1.0) 66 | tilt (~> 1.1, != 1.3.0) 67 | test-unit (3.0.8) 68 | power_assert 69 | thor (0.14.6) 70 | tilt (1.4.1) 71 | 72 | PLATFORMS 73 | ruby 74 | 75 | DEPENDENCIES 76 | actionpack (~> 3.1.0) 77 | appraisal 78 | jbuilder (~> 1.5.0) 79 | jbuilder_cache_multi! 80 | mocha 81 | railties (~> 3.1.0) 82 | rake 83 | test-unit 84 | 85 | BUNDLED WITH 86 | 1.14.6 87 | -------------------------------------------------------------------------------- /gemfiles/rails_3.1.0_jbuilder_2.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 3.1.0" 10 | gem "actionpack", "~> 3.1.0" 11 | gem "jbuilder", "~> 2.0.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_3.1.0_jbuilder_2.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionpack (3.1.12) 11 | activemodel (= 3.1.12) 12 | activesupport (= 3.1.12) 13 | builder (~> 3.0.0) 14 | erubis (~> 2.7.0) 15 | i18n (~> 0.6) 16 | rack (~> 1.3.6) 17 | rack-cache (~> 1.2) 18 | rack-mount (~> 0.8.2) 19 | rack-test (~> 0.6.1) 20 | sprockets (~> 2.0.4) 21 | activemodel (3.1.12) 22 | activesupport (= 3.1.12) 23 | builder (~> 3.0.0) 24 | i18n (~> 0.6) 25 | activesupport (3.1.12) 26 | multi_json (~> 1.0) 27 | appraisal (2.1.0) 28 | bundler 29 | rake 30 | thor (>= 0.14.0) 31 | builder (3.0.4) 32 | erubis (2.7.0) 33 | hike (1.2.3) 34 | i18n (0.7.0) 35 | jbuilder (2.0.8) 36 | activesupport (>= 3.0.0, < 5) 37 | multi_json (~> 1.2) 38 | json (1.8.3) 39 | metaclass (0.0.4) 40 | mocha (1.1.0) 41 | metaclass (~> 0.0.1) 42 | multi_json (1.11.2) 43 | power_assert (0.2.2) 44 | rack (1.3.10) 45 | rack-cache (1.2) 46 | rack (>= 0.4) 47 | rack-mount (0.8.3) 48 | rack (>= 1.0.0) 49 | rack-ssl (1.3.4) 50 | rack 51 | rack-test (0.6.3) 52 | rack (>= 1.0) 53 | railties (3.1.12) 54 | actionpack (= 3.1.12) 55 | activesupport (= 3.1.12) 56 | rack-ssl (~> 1.3.2) 57 | rake (>= 0.8.7) 58 | rdoc (~> 3.4) 59 | thor (~> 0.14.6) 60 | rake (10.4.2) 61 | rdoc (3.12.2) 62 | json (~> 1.4) 63 | sprockets (2.0.5) 64 | hike (~> 1.2) 65 | rack (~> 1.0) 66 | tilt (~> 1.1, != 1.3.0) 67 | test-unit (3.0.8) 68 | power_assert 69 | thor (0.14.6) 70 | tilt (1.4.1) 71 | 72 | PLATFORMS 73 | ruby 74 | 75 | DEPENDENCIES 76 | actionpack (~> 3.1.0) 77 | appraisal 78 | jbuilder (~> 2.0.0) 79 | jbuilder_cache_multi! 80 | mocha 81 | railties (~> 3.1.0) 82 | rake 83 | test-unit 84 | 85 | BUNDLED WITH 86 | 1.14.6 87 | -------------------------------------------------------------------------------- /gemfiles/rails_3.2.0_jbuilder_1.5.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 3.2.0" 10 | gem "actionpack", "~> 3.2.0" 11 | gem "jbuilder", "~> 1.5.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_3.2.0_jbuilder_1.5.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionpack (3.2.22) 11 | activemodel (= 3.2.22) 12 | activesupport (= 3.2.22) 13 | builder (~> 3.0.0) 14 | erubis (~> 2.7.0) 15 | journey (~> 1.0.4) 16 | rack (~> 1.4.5) 17 | rack-cache (~> 1.2) 18 | rack-test (~> 0.6.1) 19 | sprockets (~> 2.2.1) 20 | activemodel (3.2.22) 21 | activesupport (= 3.2.22) 22 | builder (~> 3.0.0) 23 | activesupport (3.2.22) 24 | i18n (~> 0.6, >= 0.6.4) 25 | multi_json (~> 1.0) 26 | appraisal (2.1.0) 27 | bundler 28 | rake 29 | thor (>= 0.14.0) 30 | builder (3.0.4) 31 | erubis (2.7.0) 32 | hike (1.2.3) 33 | i18n (0.7.0) 34 | jbuilder (1.5.3) 35 | activesupport (>= 3.0.0) 36 | multi_json (>= 1.2.0) 37 | journey (1.0.4) 38 | json (1.8.3) 39 | metaclass (0.0.4) 40 | mocha (1.1.0) 41 | metaclass (~> 0.0.1) 42 | multi_json (1.11.2) 43 | power_assert (0.2.2) 44 | rack (1.4.7) 45 | rack-cache (1.2) 46 | rack (>= 0.4) 47 | rack-ssl (1.3.4) 48 | rack 49 | rack-test (0.6.3) 50 | rack (>= 1.0) 51 | railties (3.2.22) 52 | actionpack (= 3.2.22) 53 | activesupport (= 3.2.22) 54 | rack-ssl (~> 1.3.2) 55 | rake (>= 0.8.7) 56 | rdoc (~> 3.4) 57 | thor (>= 0.14.6, < 2.0) 58 | rake (10.4.2) 59 | rdoc (3.12.2) 60 | json (~> 1.4) 61 | sprockets (2.2.3) 62 | hike (~> 1.2) 63 | multi_json (~> 1.0) 64 | rack (~> 1.0) 65 | tilt (~> 1.1, != 1.3.0) 66 | test-unit (3.0.8) 67 | power_assert 68 | thor (0.19.1) 69 | tilt (1.4.1) 70 | 71 | PLATFORMS 72 | ruby 73 | 74 | DEPENDENCIES 75 | actionpack (~> 3.2.0) 76 | appraisal 77 | jbuilder (~> 1.5.0) 78 | jbuilder_cache_multi! 79 | mocha 80 | railties (~> 3.2.0) 81 | rake 82 | test-unit 83 | 84 | BUNDLED WITH 85 | 1.14.6 86 | -------------------------------------------------------------------------------- /gemfiles/rails_3.2.0_jbuilder_2.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 3.2.0" 10 | gem "actionpack", "~> 3.2.0" 11 | gem "jbuilder", "~> 2.0.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_3.2.0_jbuilder_2.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionpack (3.2.22) 11 | activemodel (= 3.2.22) 12 | activesupport (= 3.2.22) 13 | builder (~> 3.0.0) 14 | erubis (~> 2.7.0) 15 | journey (~> 1.0.4) 16 | rack (~> 1.4.5) 17 | rack-cache (~> 1.2) 18 | rack-test (~> 0.6.1) 19 | sprockets (~> 2.2.1) 20 | activemodel (3.2.22) 21 | activesupport (= 3.2.22) 22 | builder (~> 3.0.0) 23 | activesupport (3.2.22) 24 | i18n (~> 0.6, >= 0.6.4) 25 | multi_json (~> 1.0) 26 | appraisal (2.1.0) 27 | bundler 28 | rake 29 | thor (>= 0.14.0) 30 | builder (3.0.4) 31 | erubis (2.7.0) 32 | hike (1.2.3) 33 | i18n (0.7.0) 34 | jbuilder (2.0.8) 35 | activesupport (>= 3.0.0, < 5) 36 | multi_json (~> 1.2) 37 | journey (1.0.4) 38 | json (1.8.3) 39 | metaclass (0.0.4) 40 | mocha (1.1.0) 41 | metaclass (~> 0.0.1) 42 | multi_json (1.11.2) 43 | power_assert (0.2.2) 44 | rack (1.4.7) 45 | rack-cache (1.2) 46 | rack (>= 0.4) 47 | rack-ssl (1.3.4) 48 | rack 49 | rack-test (0.6.3) 50 | rack (>= 1.0) 51 | railties (3.2.22) 52 | actionpack (= 3.2.22) 53 | activesupport (= 3.2.22) 54 | rack-ssl (~> 1.3.2) 55 | rake (>= 0.8.7) 56 | rdoc (~> 3.4) 57 | thor (>= 0.14.6, < 2.0) 58 | rake (10.4.2) 59 | rdoc (3.12.2) 60 | json (~> 1.4) 61 | sprockets (2.2.3) 62 | hike (~> 1.2) 63 | multi_json (~> 1.0) 64 | rack (~> 1.0) 65 | tilt (~> 1.1, != 1.3.0) 66 | test-unit (3.0.8) 67 | power_assert 68 | thor (0.19.1) 69 | tilt (1.4.1) 70 | 71 | PLATFORMS 72 | ruby 73 | 74 | DEPENDENCIES 75 | actionpack (~> 3.2.0) 76 | appraisal 77 | jbuilder (~> 2.0.0) 78 | jbuilder_cache_multi! 79 | mocha 80 | railties (~> 3.2.0) 81 | rake 82 | test-unit 83 | 84 | BUNDLED WITH 85 | 1.14.6 86 | -------------------------------------------------------------------------------- /gemfiles/rails_4.0.0_jbuilder_1.5.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 4.0.0" 10 | gem "actionpack", "~> 4.0.0" 11 | gem "jbuilder", "~> 1.5.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_4.0.0_jbuilder_1.5.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionpack (4.0.13) 11 | activesupport (= 4.0.13) 12 | builder (~> 3.1.0) 13 | erubis (~> 2.7.0) 14 | rack (~> 1.5.2) 15 | rack-test (~> 0.6.2) 16 | activesupport (4.0.13) 17 | i18n (~> 0.6, >= 0.6.9) 18 | minitest (~> 4.2) 19 | multi_json (~> 1.3) 20 | thread_safe (~> 0.1) 21 | tzinfo (~> 0.3.37) 22 | appraisal (2.1.0) 23 | bundler 24 | rake 25 | thor (>= 0.14.0) 26 | builder (3.1.4) 27 | erubis (2.7.0) 28 | i18n (0.7.0) 29 | jbuilder (1.5.3) 30 | activesupport (>= 3.0.0) 31 | multi_json (>= 1.2.0) 32 | metaclass (0.0.4) 33 | minitest (4.7.5) 34 | mocha (1.1.0) 35 | metaclass (~> 0.0.1) 36 | multi_json (1.11.2) 37 | power_assert (0.2.2) 38 | rack (1.5.5) 39 | rack-test (0.6.3) 40 | rack (>= 1.0) 41 | railties (4.0.13) 42 | actionpack (= 4.0.13) 43 | activesupport (= 4.0.13) 44 | rake (>= 0.8.7) 45 | thor (>= 0.18.1, < 2.0) 46 | rake (10.4.2) 47 | test-unit (3.0.8) 48 | power_assert 49 | thor (0.19.1) 50 | thread_safe (0.3.5) 51 | tzinfo (0.3.44) 52 | 53 | PLATFORMS 54 | ruby 55 | 56 | DEPENDENCIES 57 | actionpack (~> 4.0.0) 58 | appraisal 59 | jbuilder (~> 1.5.0) 60 | jbuilder_cache_multi! 61 | mocha 62 | railties (~> 4.0.0) 63 | rake 64 | test-unit 65 | 66 | BUNDLED WITH 67 | 1.14.6 68 | -------------------------------------------------------------------------------- /gemfiles/rails_4.0.0_jbuilder_2.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 4.0.0" 10 | gem "actionpack", "~> 4.0.0" 11 | gem "jbuilder", "~> 2.0.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_4.0.0_jbuilder_2.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionpack (4.0.13) 11 | activesupport (= 4.0.13) 12 | builder (~> 3.1.0) 13 | erubis (~> 2.7.0) 14 | rack (~> 1.5.2) 15 | rack-test (~> 0.6.2) 16 | activesupport (4.0.13) 17 | i18n (~> 0.6, >= 0.6.9) 18 | minitest (~> 4.2) 19 | multi_json (~> 1.3) 20 | thread_safe (~> 0.1) 21 | tzinfo (~> 0.3.37) 22 | appraisal (2.1.0) 23 | bundler 24 | rake 25 | thor (>= 0.14.0) 26 | builder (3.1.4) 27 | erubis (2.7.0) 28 | i18n (0.7.0) 29 | jbuilder (2.0.8) 30 | activesupport (>= 3.0.0, < 5) 31 | multi_json (~> 1.2) 32 | metaclass (0.0.4) 33 | minitest (4.7.5) 34 | mocha (1.1.0) 35 | metaclass (~> 0.0.1) 36 | multi_json (1.11.2) 37 | power_assert (0.2.2) 38 | rack (1.5.5) 39 | rack-test (0.6.3) 40 | rack (>= 1.0) 41 | railties (4.0.13) 42 | actionpack (= 4.0.13) 43 | activesupport (= 4.0.13) 44 | rake (>= 0.8.7) 45 | thor (>= 0.18.1, < 2.0) 46 | rake (10.4.2) 47 | test-unit (3.0.8) 48 | power_assert 49 | thor (0.19.1) 50 | thread_safe (0.3.5) 51 | tzinfo (0.3.44) 52 | 53 | PLATFORMS 54 | ruby 55 | 56 | DEPENDENCIES 57 | actionpack (~> 4.0.0) 58 | appraisal 59 | jbuilder (~> 2.0.0) 60 | jbuilder_cache_multi! 61 | mocha 62 | railties (~> 4.0.0) 63 | rake 64 | test-unit 65 | 66 | BUNDLED WITH 67 | 1.14.6 68 | -------------------------------------------------------------------------------- /gemfiles/rails_4.1.0_jbuilder_1.5.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 4.1.0" 10 | gem "actionpack", "~> 4.1.0" 11 | gem "jbuilder", "~> 1.5.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_4.1.0_jbuilder_1.5.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionpack (4.1.13) 11 | actionview (= 4.1.13) 12 | activesupport (= 4.1.13) 13 | rack (~> 1.5.2) 14 | rack-test (~> 0.6.2) 15 | actionview (4.1.13) 16 | activesupport (= 4.1.13) 17 | builder (~> 3.1) 18 | erubis (~> 2.7.0) 19 | activesupport (4.1.13) 20 | i18n (~> 0.6, >= 0.6.9) 21 | json (~> 1.7, >= 1.7.7) 22 | minitest (~> 5.1) 23 | thread_safe (~> 0.1) 24 | tzinfo (~> 1.1) 25 | appraisal (2.1.0) 26 | bundler 27 | rake 28 | thor (>= 0.14.0) 29 | builder (3.2.2) 30 | erubis (2.7.0) 31 | i18n (0.7.0) 32 | jbuilder (1.5.3) 33 | activesupport (>= 3.0.0) 34 | multi_json (>= 1.2.0) 35 | json (1.8.3) 36 | metaclass (0.0.4) 37 | minitest (5.8.0) 38 | mocha (1.1.0) 39 | metaclass (~> 0.0.1) 40 | multi_json (1.11.2) 41 | power_assert (0.2.2) 42 | rack (1.5.5) 43 | rack-test (0.6.3) 44 | rack (>= 1.0) 45 | railties (4.1.13) 46 | actionpack (= 4.1.13) 47 | activesupport (= 4.1.13) 48 | rake (>= 0.8.7) 49 | thor (>= 0.18.1, < 2.0) 50 | rake (10.4.2) 51 | test-unit (3.0.8) 52 | power_assert 53 | thor (0.19.1) 54 | thread_safe (0.3.5) 55 | tzinfo (1.2.2) 56 | thread_safe (~> 0.1) 57 | 58 | PLATFORMS 59 | ruby 60 | 61 | DEPENDENCIES 62 | actionpack (~> 4.1.0) 63 | appraisal 64 | jbuilder (~> 1.5.0) 65 | jbuilder_cache_multi! 66 | mocha 67 | railties (~> 4.1.0) 68 | rake 69 | test-unit 70 | 71 | BUNDLED WITH 72 | 1.14.6 73 | -------------------------------------------------------------------------------- /gemfiles/rails_4.1.0_jbuilder_2.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 4.1.0" 10 | gem "actionpack", "~> 4.1.0" 11 | gem "jbuilder", "~> 2.0.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_4.1.0_jbuilder_2.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionpack (4.1.13) 11 | actionview (= 4.1.13) 12 | activesupport (= 4.1.13) 13 | rack (~> 1.5.2) 14 | rack-test (~> 0.6.2) 15 | actionview (4.1.13) 16 | activesupport (= 4.1.13) 17 | builder (~> 3.1) 18 | erubis (~> 2.7.0) 19 | activesupport (4.1.13) 20 | i18n (~> 0.6, >= 0.6.9) 21 | json (~> 1.7, >= 1.7.7) 22 | minitest (~> 5.1) 23 | thread_safe (~> 0.1) 24 | tzinfo (~> 1.1) 25 | appraisal (2.1.0) 26 | bundler 27 | rake 28 | thor (>= 0.14.0) 29 | builder (3.2.2) 30 | erubis (2.7.0) 31 | i18n (0.7.0) 32 | jbuilder (2.0.8) 33 | activesupport (>= 3.0.0, < 5) 34 | multi_json (~> 1.2) 35 | json (1.8.3) 36 | metaclass (0.0.4) 37 | minitest (5.8.0) 38 | mocha (1.1.0) 39 | metaclass (~> 0.0.1) 40 | multi_json (1.11.2) 41 | power_assert (0.2.2) 42 | rack (1.5.5) 43 | rack-test (0.6.3) 44 | rack (>= 1.0) 45 | railties (4.1.13) 46 | actionpack (= 4.1.13) 47 | activesupport (= 4.1.13) 48 | rake (>= 0.8.7) 49 | thor (>= 0.18.1, < 2.0) 50 | rake (10.4.2) 51 | test-unit (3.0.8) 52 | power_assert 53 | thor (0.19.1) 54 | thread_safe (0.3.5) 55 | tzinfo (1.2.2) 56 | thread_safe (~> 0.1) 57 | 58 | PLATFORMS 59 | ruby 60 | 61 | DEPENDENCIES 62 | actionpack (~> 4.1.0) 63 | appraisal 64 | jbuilder (~> 2.0.0) 65 | jbuilder_cache_multi! 66 | mocha 67 | railties (~> 4.1.0) 68 | rake 69 | test-unit 70 | 71 | BUNDLED WITH 72 | 1.14.6 73 | -------------------------------------------------------------------------------- /gemfiles/rails_5.0.0_jbuilder_1.5.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 5.0.0" 10 | gem "actionpack", "~> 5.0.0" 11 | gem "jbuilder", "~> 1.5.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_5.0.0_jbuilder_1.5.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionpack (5.0.2) 11 | actionview (= 5.0.2) 12 | activesupport (= 5.0.2) 13 | rack (~> 2.0) 14 | rack-test (~> 0.6.3) 15 | rails-dom-testing (~> 2.0) 16 | rails-html-sanitizer (~> 1.0, >= 1.0.2) 17 | actionview (5.0.2) 18 | activesupport (= 5.0.2) 19 | builder (~> 3.1) 20 | erubis (~> 2.7.0) 21 | rails-dom-testing (~> 2.0) 22 | rails-html-sanitizer (~> 1.0, >= 1.0.3) 23 | activesupport (5.0.2) 24 | concurrent-ruby (~> 1.0, >= 1.0.2) 25 | i18n (~> 0.7) 26 | minitest (~> 5.1) 27 | tzinfo (~> 1.1) 28 | appraisal (2.2.0) 29 | bundler 30 | rake 31 | thor (>= 0.14.0) 32 | builder (3.2.3) 33 | concurrent-ruby (1.0.5) 34 | erubis (2.7.0) 35 | i18n (0.8.1) 36 | jbuilder (1.5.3) 37 | activesupport (>= 3.0.0) 38 | multi_json (>= 1.2.0) 39 | loofah (2.0.3) 40 | nokogiri (>= 1.5.9) 41 | metaclass (0.0.4) 42 | method_source (0.8.2) 43 | mini_portile2 (2.1.0) 44 | minitest (5.10.1) 45 | mocha (1.2.1) 46 | metaclass (~> 0.0.1) 47 | multi_json (1.12.1) 48 | nokogiri (1.7.1) 49 | mini_portile2 (~> 2.1.0) 50 | power_assert (1.0.2) 51 | rack (2.0.2) 52 | rack-test (0.6.3) 53 | rack (>= 1.0) 54 | rails-dom-testing (2.0.2) 55 | activesupport (>= 4.2.0, < 6.0) 56 | nokogiri (~> 1.6) 57 | rails-html-sanitizer (1.0.3) 58 | loofah (~> 2.0) 59 | railties (5.0.2) 60 | actionpack (= 5.0.2) 61 | activesupport (= 5.0.2) 62 | method_source 63 | rake (>= 0.8.7) 64 | thor (>= 0.18.1, < 2.0) 65 | rake (12.0.0) 66 | test-unit (3.2.3) 67 | power_assert 68 | thor (0.19.4) 69 | thread_safe (0.3.6) 70 | tzinfo (1.2.3) 71 | thread_safe (~> 0.1) 72 | 73 | PLATFORMS 74 | ruby 75 | 76 | DEPENDENCIES 77 | actionpack (~> 5.0.0) 78 | appraisal 79 | jbuilder (~> 1.5.0) 80 | jbuilder_cache_multi! 81 | mocha 82 | railties (~> 5.0.0) 83 | rake 84 | test-unit 85 | 86 | BUNDLED WITH 87 | 1.14.6 88 | -------------------------------------------------------------------------------- /gemfiles/rails_5.0.0_jbuilder_2.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rake" 6 | gem "mocha", :require => false 7 | gem "appraisal" 8 | gem "test-unit" 9 | gem "railties", "~> 5.0.0" 10 | gem "actionpack", "~> 5.0.0" 11 | gem "jbuilder", "~> 2.0.0" 12 | 13 | gemspec :path => "../" 14 | -------------------------------------------------------------------------------- /gemfiles/rails_5.0.0_jbuilder_2.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | jbuilder_cache_multi (0.0.3) 5 | jbuilder (>= 1.5.0, < 3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionpack (5.0.2) 11 | actionview (= 5.0.2) 12 | activesupport (= 5.0.2) 13 | rack (~> 2.0) 14 | rack-test (~> 0.6.3) 15 | rails-dom-testing (~> 2.0) 16 | rails-html-sanitizer (~> 1.0, >= 1.0.2) 17 | actionview (5.0.2) 18 | activesupport (= 5.0.2) 19 | builder (~> 3.1) 20 | erubis (~> 2.7.0) 21 | rails-dom-testing (~> 2.0) 22 | rails-html-sanitizer (~> 1.0, >= 1.0.3) 23 | activesupport (5.0.2) 24 | concurrent-ruby (~> 1.0, >= 1.0.2) 25 | i18n (~> 0.7) 26 | minitest (~> 5.1) 27 | tzinfo (~> 1.1) 28 | appraisal (2.2.0) 29 | bundler 30 | rake 31 | thor (>= 0.14.0) 32 | builder (3.2.3) 33 | concurrent-ruby (1.0.5) 34 | erubis (2.7.0) 35 | i18n (0.8.1) 36 | jbuilder (2.0.5) 37 | activesupport (>= 3.0.0) 38 | multi_json (>= 1.2.0) 39 | loofah (2.0.3) 40 | nokogiri (>= 1.5.9) 41 | metaclass (0.0.4) 42 | method_source (0.8.2) 43 | mini_portile2 (2.1.0) 44 | minitest (5.10.1) 45 | mocha (1.2.1) 46 | metaclass (~> 0.0.1) 47 | multi_json (1.12.1) 48 | nokogiri (1.7.1) 49 | mini_portile2 (~> 2.1.0) 50 | power_assert (1.0.2) 51 | rack (2.0.2) 52 | rack-test (0.6.3) 53 | rack (>= 1.0) 54 | rails-dom-testing (2.0.2) 55 | activesupport (>= 4.2.0, < 6.0) 56 | nokogiri (~> 1.6) 57 | rails-html-sanitizer (1.0.3) 58 | loofah (~> 2.0) 59 | railties (5.0.2) 60 | actionpack (= 5.0.2) 61 | activesupport (= 5.0.2) 62 | method_source 63 | rake (>= 0.8.7) 64 | thor (>= 0.18.1, < 2.0) 65 | rake (12.0.0) 66 | test-unit (3.2.3) 67 | power_assert 68 | thor (0.19.4) 69 | thread_safe (0.3.6) 70 | tzinfo (1.2.3) 71 | thread_safe (~> 0.1) 72 | 73 | PLATFORMS 74 | ruby 75 | 76 | DEPENDENCIES 77 | actionpack (~> 5.0.0) 78 | appraisal 79 | jbuilder (~> 2.0.0) 80 | jbuilder_cache_multi! 81 | mocha 82 | railties (~> 5.0.0) 83 | rake 84 | test-unit 85 | 86 | BUNDLED WITH 87 | 1.14.6 88 | -------------------------------------------------------------------------------- /jbuilder_cache_multi.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'jbuilder_cache_multi/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "jbuilder_cache_multi" 8 | spec.version = JbuilderCacheMulti::VERSION 9 | spec.authors = ["Yonah Forst"] 10 | spec.email = ["joshblour@hotmail.com"] 11 | spec.summary = %q{Adds cache_collection! to jbuilder. Uses memcache fetch_multi/read_multi} 12 | spec.homepage = "http://www.github.com/joshblour/jbuilder_cache_multi" 13 | spec.license = "MIT" 14 | 15 | spec.files = `git ls-files -z`.split("\x0") 16 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 17 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 18 | spec.require_paths = ["lib"] 19 | 20 | spec.required_ruby_version = '>= 1.9.3' 21 | 22 | spec.add_dependency 'jbuilder', '>= 1.5.0', '< 3' 23 | 24 | end 25 | -------------------------------------------------------------------------------- /lib/jbuilder_cache_multi.rb: -------------------------------------------------------------------------------- 1 | require "jbuilder_cache_multi/version" 2 | require "jbuilder_cache_multi/jbuilder_ext" 3 | 4 | module JbuilderCacheMulti 5 | end 6 | -------------------------------------------------------------------------------- /lib/jbuilder_cache_multi/jbuilder_ext.rb: -------------------------------------------------------------------------------- 1 | JbuilderTemplate.class_eval do 2 | # Caches a collection of objects using fetch_multi, if supported. 3 | # Requires a block for each item in the array. Accepts optional 'key' attribute in options (e.g. key: 'v1'). 4 | # 5 | # Example: 6 | # 7 | # json.cache_collection! @people, expires_in: 10.minutes do |person| 8 | # json.partial! 'person', :person => person 9 | # end 10 | def cache_collection!(collection, options = {}, &block) 11 | if @context.controller.perform_caching && !collection.to_a.empty? 12 | keys_to_collection_map = _keys_to_collection_map(collection, options) 13 | 14 | if ::Rails.cache.respond_to?(:fetch_multi) 15 | results = ::Rails.cache.fetch_multi(*keys_to_collection_map.keys, options) do |key| 16 | _scope { yield keys_to_collection_map[key] } 17 | end 18 | else 19 | results = keys_to_collection_map.map do |key, item| 20 | ::Rails.cache.fetch(key, options) { _scope { yield item } } 21 | end 22 | end 23 | 24 | _process_collection_results(results) 25 | else 26 | array! collection, options, &block 27 | end 28 | end 29 | 30 | # Conditionally caches a collection of objects depending in the condition given as first parameter. 31 | # 32 | # Example: 33 | # 34 | # json.cache_collection_if! do_cache?, @people, expires_in: 10.minutes do |person| 35 | # json.partial! 'person', :person => person 36 | # end 37 | def cache_collection_if!(condition, collection, options = {}, &block) 38 | condition ? 39 | cache_collection!(collection, options, &block) : 40 | array!(collection, options, &block) 41 | end 42 | 43 | protected 44 | 45 | ## Implementing our own version of _cache_key because jbuilder's is protected 46 | def _cache_key_fetch_multi(key, options) 47 | key = _fragment_name_with_digest_fetch_multi(key, options) 48 | key = url_for(key).split('://', 2).last if ::Hash === key 49 | ::ActiveSupport::Cache.expand_cache_key(key, :jbuilder) 50 | end 51 | 52 | def _fragment_name_with_digest_fetch_multi(key, options) 53 | if @context.respond_to?(:cache_fragment_name) 54 | # Current compatibility, fragment_name_with_digest is private again and cache_fragment_name 55 | # should be used instead. 56 | @context.cache_fragment_name(key, options.slice(:skip_digest, :virtual_path)) 57 | elsif @context.respond_to?(:fragment_name_with_digest) 58 | # Backwards compatibility for period of time when fragment_name_with_digest was made public. 59 | @context.fragment_name_with_digest(key) 60 | else 61 | key 62 | end 63 | end 64 | 65 | def _keys_to_collection_map(collection, options) 66 | key = options.delete(:key) 67 | 68 | collection.inject({}) do |result, item| 69 | cache_key = 70 | if key.respond_to?(:call) 71 | key.call(item) 72 | elsif key 73 | [key, item] 74 | else 75 | item 76 | end 77 | result[_cache_key_fetch_multi(cache_key, options)] = item 78 | result 79 | end 80 | end 81 | 82 | def _process_collection_results(results) 83 | _results = results.class == Hash ? results.values : results 84 | #support pre 2.0 versions of jbuilder where merge! is still private 85 | if Jbuilder.instance_methods.include? :merge! 86 | merge! _results 87 | elsif Jbuilder.private_instance_methods.include? :_merge 88 | _merge _results 89 | else 90 | _results 91 | end 92 | end 93 | 94 | end 95 | -------------------------------------------------------------------------------- /lib/jbuilder_cache_multi/version.rb: -------------------------------------------------------------------------------- 1 | module JbuilderCacheMulti 2 | VERSION = "0.1.0" 3 | end 4 | -------------------------------------------------------------------------------- /test/jbuilder_template_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'mocha/setup' 3 | require 'action_view' 4 | require 'action_view/testing/resolvers' 5 | require 'active_support/cache' 6 | require 'jbuilder' 7 | require 'jbuilder/jbuilder_template' 8 | require 'jbuilder_cache_multi' 9 | 10 | 11 | BLOG_POST_PARTIAL = <<-JBUILDER 12 | json.extract! blog_post, :id, :body 13 | json.author do 14 | name = blog_post.author_name.split(nil, 2) 15 | json.first_name name[0] 16 | json.last_name name[1] 17 | end 18 | JBUILDER 19 | 20 | CACHE_KEY_PROC = Proc.new { |blog_post| blog_post.id } 21 | 22 | BlogPost = Struct.new(:id, :body, :author_name) 23 | blog_authors = [ 'David Heinemeier Hansson', 'Pavel Pravosud' ].cycle 24 | BLOG_POST_COLLECTION = 10.times.map{ |i| BlogPost.new(i+1, "post body #{i+1}", blog_authors.next) } 25 | 26 | module Rails 27 | def self.cache 28 | @cache ||= ActiveSupport::Cache::MemoryStore.new 29 | end 30 | end 31 | 32 | class JbuilderTemplateTest < ActionView::TestCase 33 | setup do 34 | @context = self 35 | Rails.cache.clear 36 | end 37 | 38 | def partials 39 | { 40 | '_partial.json.jbuilder' => 'json.content "hello"', 41 | '_blog_post.json.jbuilder' => BLOG_POST_PARTIAL 42 | } 43 | end 44 | 45 | # Stub out a couple of methods that'll get called from cache_fragment_name 46 | def view_cache_dependencies 47 | [] 48 | end 49 | def formats 50 | [:json] 51 | end 52 | 53 | def render_jbuilder(source) 54 | @rendered = [] 55 | lookup_context.view_paths = [ActionView::FixtureResolver.new(partials.merge('test.json.jbuilder' => source))] 56 | ActionView::Template.new(source, 'test', JbuilderHandler, :virtual_path => 'test').render(self, {}).strip 57 | end 58 | 59 | def undef_context_methods(*names) 60 | self.class_eval do 61 | names.each do |name| 62 | undef_method name.to_sym if self.method_defined?(name.to_sym) 63 | end 64 | end 65 | end 66 | 67 | def assert_collection_rendered(json, context = nil) 68 | result = MultiJson.load(json) 69 | result = result.fetch(context) if context 70 | 71 | assert_equal 10, result.length 72 | assert_equal Array, result.class 73 | assert_equal 'post body 5', result[4]['body'] 74 | assert_equal 'Heinemeier Hansson', result[2]['author']['last_name'] 75 | assert_equal 'Pavel', result[5]['author']['first_name'] 76 | end 77 | 78 | test 'renders cached array of block partials' do 79 | undef_context_methods :fragment_name_with_digest, :cache_fragment_name 80 | 81 | json = render_jbuilder <<-JBUILDER 82 | json.cache_collection! BLOG_POST_COLLECTION do |blog_post| 83 | json.partial! 'blog_post', :blog_post => blog_post 84 | end 85 | JBUILDER 86 | 87 | assert_collection_rendered json 88 | end 89 | 90 | test 'allows additional options' do 91 | json = render_jbuilder <<-JBUILDER 92 | json.cache_collection! BLOG_POST_COLLECTION, expires_in: 1.hour do |blog_post| 93 | json.partial! 'blog_post', :blog_post => blog_post 94 | end 95 | JBUILDER 96 | 97 | assert_collection_rendered json 98 | end 99 | 100 | test 'renders cached array with a key specified as a proc' do 101 | undef_context_methods :fragment_name_with_digest, :cache_fragment_name 102 | 103 | json = render_jbuilder <<-JBUILDER 104 | json.cache_collection! BLOG_POST_COLLECTION, key: CACHE_KEY_PROC do |blog_post| 105 | json.partial! 'blog_post', :blog_post => blog_post 106 | end 107 | JBUILDER 108 | 109 | assert_collection_rendered json 110 | end 111 | 112 | test 'reverts to cache! if cache does not support fetch_multi' do 113 | undef_context_methods :fragment_name_with_digest, :cache_fragment_name 114 | ActiveSupport::Cache::Store.send(:undef_method, :fetch_multi) if ActiveSupport::Cache::Store.method_defined?(:fetch_multi) 115 | 116 | json = render_jbuilder <<-JBUILDER 117 | json.cache_collection! BLOG_POST_COLLECTION do |blog_post| 118 | json.partial! 'blog_post', :blog_post => blog_post 119 | end 120 | JBUILDER 121 | 122 | assert_collection_rendered json 123 | end 124 | 125 | test 'reverts to array! when controller.perform_caching is false' do 126 | controller.perform_caching = false 127 | 128 | json = render_jbuilder <<-JBUILDER 129 | json.cache_collection! BLOG_POST_COLLECTION do |blog_post| 130 | json.partial! 'blog_post', :blog_post => blog_post 131 | end 132 | JBUILDER 133 | 134 | assert_collection_rendered json 135 | end 136 | 137 | test 'reverts to array! when collection is empty' do 138 | json = render_jbuilder <<-JBUILDER 139 | json.cache_collection! [] do |blog_post| 140 | json.partial! 'blog_post', :blog_post => blog_post 141 | end 142 | JBUILDER 143 | 144 | assert_equal '[]', json 145 | end 146 | 147 | test 'conditionally fragment caching a JSON object' do 148 | undef_context_methods :fragment_name_with_digest, :cache_fragment_name 149 | 150 | render_jbuilder <<-JBUILDER 151 | json.cache_collection_if! true, BLOG_POST_COLLECTION, key: 'cachekey' do |blog_post| 152 | json.partial! 'blog_post', :blog_post => blog_post 153 | end 154 | JBUILDER 155 | 156 | json = render_jbuilder <<-JBUILDER 157 | json.cache_collection_if! true, BLOG_POST_COLLECTION, key: 'cachekey' do |blog_post| 158 | json.test 'Miss' 159 | end 160 | JBUILDER 161 | 162 | assert_collection_rendered json 163 | 164 | json = render_jbuilder <<-JBUILDER 165 | json.cache_collection_if! false, BLOG_POST_COLLECTION, key: 'cachekey' do |blog_post| 166 | json.test 'Miss' 167 | end 168 | JBUILDER 169 | 170 | result = MultiJson.load(json) 171 | assert_equal 'Miss', result[4]['test'] 172 | end 173 | end 174 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require "bundler/setup" 2 | require "rails/version" 3 | 4 | if Rails::VERSION::STRING > "4.0" 5 | require "active_support/testing/autorun" 6 | else 7 | require "test/unit" 8 | end 9 | 10 | require "active_support/test_case" 11 | --------------------------------------------------------------------------------