standardapi 6.0.0.32 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/standard_api.rb +4 -0
- data/lib/standard_api/access_control_list.rb +114 -0
- data/lib/standard_api/controller.rb +32 -11
- data/lib/standard_api/helpers.rb +4 -3
- data/lib/standard_api/includes.rb +9 -0
- data/lib/standard_api/middleware/query_encoding.rb +3 -3
- data/lib/standard_api/railtie.rb +13 -2
- data/lib/standard_api/route_helpers.rb +5 -5
- data/lib/standard_api/test_case.rb +13 -3
- data/lib/standard_api/test_case/calculate_tests.rb +8 -2
- data/lib/standard_api/test_case/create_tests.rb +7 -9
- data/lib/standard_api/test_case/index_tests.rb +10 -0
- data/lib/standard_api/test_case/schema_tests.rb +7 -1
- data/lib/standard_api/test_case/show_tests.rb +1 -0
- data/lib/standard_api/test_case/update_tests.rb +8 -9
- data/lib/standard_api/version.rb +1 -1
- data/lib/standard_api/views/application/_record.json.jbuilder +14 -14
- data/lib/standard_api/views/application/_record.streamer +36 -34
- data/lib/standard_api/views/application/_schema.json.jbuilder +1 -1
- data/lib/standard_api/views/application/_schema.streamer +1 -1
- data/lib/standard_api/views/application/new.streamer +1 -1
- data/test/standard_api/caching_test.rb +14 -4
- data/test/standard_api/helpers_test.rb +25 -9
- data/test/standard_api/standard_api_test.rb +122 -14
- data/test/standard_api/test_app/app/controllers/acl/account_acl.rb +15 -0
- data/test/standard_api/test_app/app/controllers/acl/property_acl.rb +27 -0
- data/test/standard_api/test_app/app/controllers/acl/reference_acl.rb +7 -0
- data/test/standard_api/test_app/controllers.rb +13 -45
- data/test/standard_api/test_app/models.rb +17 -5
- data/test/standard_api/test_app/test/factories.rb +4 -3
- data/test/standard_api/test_app/views/photos/_photo.json.jbuilder +1 -0
- data/test/standard_api/test_app/views/photos/_photo.streamer +2 -1
- data/test/standard_api/test_helper.rb +12 -0
- metadata +19 -15
| @@ -69,9 +69,12 @@ module StandardAPI | |
| 69 69 | 
             
                  end
         | 
| 70 70 |  | 
| 71 71 | 
             
                  test '#index.json params[:include]' do
         | 
| 72 | 
            +
                    next if includes.empty?
         | 
| 73 | 
            +
             | 
| 72 74 | 
             
                    travel_to Time.now do
         | 
| 73 75 | 
             
                      create_model
         | 
| 74 76 | 
             
                      get resource_path(:index, format: :json), params: { limit: 100, include: includes }
         | 
| 77 | 
            +
                      assert_response :ok
         | 
| 75 78 |  | 
| 76 79 | 
             
                      json = JSON.parse(response.body)[0]
         | 
| 77 80 | 
             
                      assert json.is_a?(Hash)
         | 
| @@ -128,6 +131,13 @@ module StandardAPI | |
| 128 131 | 
             
                    models = @controller.instance_variable_get("@#{plural_name}")
         | 
| 129 132 | 
             
                    assert_equal model.where(id: m.id).sort(required_orders).to_sql, models.to_sql
         | 
| 130 133 | 
             
                    @controller.current_mask.delete(plural_name)
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                    @controller.current_mask[plural_name.to_sym] = { id: m.id }
         | 
| 136 | 
            +
                    get :index, format: :json
         | 
| 137 | 
            +
                    models = @controller.instance_variable_get("@#{plural_name}")
         | 
| 138 | 
            +
                    assert_equal model.where(id: m.id).sort(required_orders).to_sql, models.to_sql
         | 
| 139 | 
            +
                    @controller.current_mask.delete(plural_name.to_sym)
         | 
| 140 | 
            +
             | 
| 131 141 | 
             
                  end
         | 
| 132 142 | 
             
                end
         | 
| 133 143 | 
             
              end
         | 
| @@ -18,7 +18,13 @@ module StandardAPI | |
| 18 18 | 
             
                      assert_equal_or_nil column.null, actual_column['null']
         | 
| 19 19 | 
             
                      assert_equal_or_nil column.array, actual_column['array']
         | 
| 20 20 | 
             
                      assert_equal_or_nil column.comment, actual_column['comment']
         | 
| 21 | 
            -
             | 
| 21 | 
            +
             | 
| 22 | 
            +
                      if column.default
         | 
| 23 | 
            +
                        default = model.connection.lookup_cast_type_from_column(column).deserialize(column.default)
         | 
| 24 | 
            +
                        assert_equal default, actual_column['default']
         | 
| 25 | 
            +
                      else
         | 
| 26 | 
            +
                        assert_nil column.default
         | 
| 27 | 
            +
                      end
         | 
| 22 28 | 
             
                    end
         | 
| 23 29 |  | 
| 24 30 | 
             
                    assert json['limit']
         | 
| @@ -16,7 +16,7 @@ module StandardAPI | |
| 16 16 | 
             
                    put resource_path(:update, :id => m.id, format: format), params: { singular_name => attrs }, as: as
         | 
| 17 17 | 
             
                    assert_response :ok, "Updating #{m.class.name} with #{attrs.inspect}"
         | 
| 18 18 |  | 
| 19 | 
            -
                     | 
| 19 | 
            +
                    update_attributes(m.reload).select { |x| attrs.keys.map(&:to_s).include?(x) }.each do |key, value|
         | 
| 20 20 | 
             
                      message = "Model / Attribute: #{m.class.name}##{key}"
         | 
| 21 21 | 
             
                      if value.is_a?(BigDecimal)
         | 
| 22 22 | 
             
                        assert_equal_or_nil normalize_attribute(m, key, attrs[key.to_sym]).to_s.to_f, value.to_s.to_f, message
         | 
| @@ -34,7 +34,7 @@ module StandardAPI | |
| 34 34 | 
             
                    get resource_path(:show, id: m.id), as: :json
         | 
| 35 35 |  | 
| 36 36 | 
             
                    return if @controller.method(:update).owner != StandardAPI
         | 
| 37 | 
            -
             | 
| 37 | 
            +
             | 
| 38 38 | 
             
                    attrs = attributes_for(singular_name).select{|k,v| !model.readonly_attributes.include?(k.to_s) }
         | 
| 39 39 | 
             
                    create_webmocks(attrs)
         | 
| 40 40 |  | 
| @@ -57,9 +57,9 @@ module StandardAPI | |
| 57 57 | 
             
                    assert_response :ok, "Updating #{m.class.name} with #{attrs.inspect}"
         | 
| 58 58 |  | 
| 59 59 | 
             
                    # (m.attribute_names & attrs.keys.map(&:to_s)).each do |test_key|
         | 
| 60 | 
            -
                     | 
| 60 | 
            +
                    update_attributes(m.reload).select { |x| attrs.keys.map(&:to_s).include?(x) }.each do |key, value|
         | 
| 61 61 | 
             
                      message = "Model / Attribute: #{m.class.name}##{key}"
         | 
| 62 | 
            -
                      assert_equal_or_nil normalize_attribute(m, key, attrs[key.to_sym]), value, message
         | 
| 62 | 
            +
                      assert_equal_or_nil normalize_attribute(m, key, attrs[key.to_sym]), normalize_attribute(m, key, value), message
         | 
| 63 63 | 
             
                    end
         | 
| 64 64 | 
             
                    assert JSON.parse(@response.body).is_a?(Hash)
         | 
| 65 65 | 
             
                  end
         | 
| @@ -68,8 +68,7 @@ module StandardAPI | |
| 68 68 | 
             
                    trait = FactoryBot.factories[singular_name].definition.defined_traits.any? { |x| x.name.to_s == 'invalid' }
         | 
| 69 69 |  | 
| 70 70 | 
             
                    if !trait
         | 
| 71 | 
            -
                       | 
| 72 | 
            -
                      warn("No invalid trait for #{model.name}. Skipping invalid tests")
         | 
| 71 | 
            +
                      skip("No invalid trait for #{model.name}. Skipping invalid tests")
         | 
| 73 72 | 
             
                      return
         | 
| 74 73 | 
             
                    end
         | 
| 75 74 |  | 
| @@ -94,7 +93,7 @@ module StandardAPI | |
| 94 93 |  | 
| 95 94 | 
             
                      put resource_path(:update, :id => m.id, format: format), params: { include: includes, singular_name => attrs }, as: as
         | 
| 96 95 | 
             
                      assert_response :ok, "Updating #{m.class.name} with #{attrs.inspect}"
         | 
| 97 | 
            -
             | 
| 96 | 
            +
             | 
| 98 97 | 
             
                      controller_model = @controller.instance_variable_get("@#{singular_name}")
         | 
| 99 98 | 
             
                      json = JSON.parse(response.body)
         | 
| 100 99 | 
             
                      includes.each do |included|
         | 
| @@ -104,7 +103,7 @@ module StandardAPI | |
| 104 103 | 
             
                        next if !association
         | 
| 105 104 |  | 
| 106 105 | 
             
                        if ['belongs_to', 'has_one'].include?(association.macro.to_s)
         | 
| 107 | 
            -
                           | 
| 106 | 
            +
                          update_attributes(controller_model.send(included)) do |key, value|
         | 
| 108 107 | 
             
                            message = "Model / Attribute: #{controller_model.send(included).class.name}##{key}"
         | 
| 109 108 | 
             
                            assert_equal json[included.to_s][key.to_s], value, message
         | 
| 110 109 | 
             
                          end
         | 
| @@ -118,7 +117,7 @@ module StandardAPI | |
| 118 117 | 
             
                            nil
         | 
| 119 118 | 
             
                          end
         | 
| 120 119 |  | 
| 121 | 
            -
                           | 
| 120 | 
            +
                          update_attributes(m).each do |key, value|
         | 
| 122 121 | 
             
                            message = "Model / Attribute: #{m.class.name}##{key}"
         | 
| 123 122 | 
             
                            if m_json[key.to_s].nil?
         | 
| 124 123 | 
             
                              assert_nil normalize_to_json(m, key, value), message
         | 
    
        data/lib/standard_api/version.rb
    CHANGED
    
    
| @@ -7,20 +7,20 @@ end | |
| 7 7 | 
             
            includes.each do |inc, subinc|
         | 
| 8 8 | 
             
              next if ["limit", "offset", "order", "when", "where", "distinct", "distinct_on"].include?(inc)
         | 
| 9 9 |  | 
| 10 | 
            -
             | 
| 11 10 | 
             
              case association = record.class.reflect_on_association(inc)
         | 
| 12 11 | 
             
              when ActiveRecord::Reflection::AbstractReflection
         | 
| 13 12 | 
             
                if association.collection?
         | 
| 14 | 
            -
                  can_cache = can_cache_relation?(record | 
| 15 | 
            -
                  json. | 
| 16 | 
            -
                     | 
| 17 | 
            -
             | 
| 13 | 
            +
                  can_cache = can_cache_relation?(record, inc, subinc)
         | 
| 14 | 
            +
                  json.set! inc do
         | 
| 15 | 
            +
                    json.cache_if!(can_cache, can_cache ? association_cache_key(record, inc, subinc) : nil) do
         | 
| 16 | 
            +
                      partial = model_partial(association.klass)
         | 
| 17 | 
            +
             | 
| 18 18 | 
             
                      # TODO limit causes preloaded assocations to reload
         | 
| 19 19 | 
             
                      sub_records = record.send(inc)
         | 
| 20 20 |  | 
| 21 21 | 
             
                      sub_records = sub_records.limit(subinc['limit']) if subinc['limit']
         | 
| 22 22 | 
             
                      sub_records = sub_records.offset(subinc['offset']) if subinc['offset']
         | 
| 23 | 
            -
                      sub_records = sub_records. | 
| 23 | 
            +
                      sub_records = sub_records.reorder(subinc['order']) if subinc['order']
         | 
| 24 24 | 
             
                      sub_records = sub_records.filter(subinc['where']) if subinc['where']
         | 
| 25 25 | 
             
                      sub_records = sub_records.distinct if subinc['distinct']
         | 
| 26 26 | 
             
                      sub_records = sub_records.distinct_on(subinc['distinct_on']) if subinc['distinct_on']
         | 
| @@ -29,17 +29,17 @@ includes.each do |inc, subinc| | |
| 29 29 | 
             
                    end
         | 
| 30 30 | 
             
                  end
         | 
| 31 31 | 
             
                else
         | 
| 32 | 
            -
                  can_cache = can_cache_relation?(record | 
| 32 | 
            +
                  can_cache = can_cache_relation?(record, inc, subinc)
         | 
| 33 33 | 
             
                  if association.is_a?(ActiveRecord::Reflection::BelongsToReflection)
         | 
| 34 34 | 
             
                    can_cache = can_cache && !record.send(association.foreign_key).nil?
         | 
| 35 35 | 
             
                  end
         | 
| 36 | 
            -
                  json. | 
| 37 | 
            -
                     | 
| 38 | 
            -
             | 
| 39 | 
            -
                       | 
| 40 | 
            -
             | 
| 41 | 
            -
                       | 
| 42 | 
            -
             | 
| 36 | 
            +
                  json.set! inc do
         | 
| 37 | 
            +
                    json.cache_if!(can_cache, can_cache ? association_cache_key(record, inc, subinc) : nil) do
         | 
| 38 | 
            +
                      value = record.send(inc)
         | 
| 39 | 
            +
                      if value.nil?
         | 
| 40 | 
            +
                        json.null!
         | 
| 41 | 
            +
                      else
         | 
| 42 | 
            +
                        partial = model_partial(value)
         | 
| 43 43 | 
             
                        json.partial! partial, partial.split('/').last.to_sym => value, includes: subinc
         | 
| 44 44 | 
             
                      end
         | 
| 45 45 | 
             
                    end
         | 
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            json.object! do
         | 
| 2 | 
            -
             | 
| 2 | 
            +
             | 
| 3 3 | 
             
              record.attributes.each do |name, value|
         | 
| 4 4 | 
             
                # Skip if attribute is included in excludes
         | 
| 5 5 | 
             
                next if defined?(excludes) && excludes[record.model_name.singular.to_sym].try(:find) { |x| x.to_s == name.to_s }
         | 
| @@ -8,39 +8,41 @@ json.object! do | |
| 8 8 |  | 
| 9 9 | 
             
              includes.each do |inc, subinc|
         | 
| 10 10 | 
             
                next if ["limit", "offset", "order", "when", "where", "distinct", "distinct_on"].include?(inc)
         | 
| 11 | 
            -
             | 
| 11 | 
            +
             | 
| 12 12 | 
             
                case association = record.class.reflect_on_association(inc)
         | 
| 13 | 
            -
                when ActiveRecord::Reflection:: | 
| 14 | 
            -
                   | 
| 15 | 
            -
             | 
| 16 | 
            -
                     | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 13 | 
            +
                when ActiveRecord::Reflection::AbstractReflection
         | 
| 14 | 
            +
                  if association.collection?
         | 
| 15 | 
            +
                    can_cache = can_cache_relation?(record, inc, subinc)
         | 
| 16 | 
            +
                    json.cache_if!(can_cache, can_cache ? [inc, association_cache_key(record, inc, subinc)] : nil) do
         | 
| 17 | 
            +
                      json.set! inc do
         | 
| 18 | 
            +
                        partial = model_partial(association.klass)
         | 
| 19 | 
            +
                        # TODO limit causes preloaded assocations to reload
         | 
| 20 | 
            +
                        sub_records = record.send(inc)
         | 
| 20 21 |  | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 22 | 
            +
                        sub_records = sub_records.limit(subinc["limit"]) if subinc["limit"]
         | 
| 23 | 
            +
                        sub_records = sub_records.offset(subinc["offset"]) if subinc["offset"]
         | 
| 24 | 
            +
                        sub_records = sub_records.reorder(subinc["order"]) if subinc["order"]
         | 
| 25 | 
            +
                        sub_records = sub_records.filter(subinc["where"]) if subinc["where"]
         | 
| 26 | 
            +
                        sub_records = sub_records.distinct if subinc["distinct"]
         | 
| 27 | 
            +
                        sub_records = sub_records.distinct_on(subinc["distinct_on"]) if subinc["distinct_on"]
         | 
| 27 28 |  | 
| 28 | 
            -
             | 
| 29 | 
            +
                        json.array! sub_records, partial: partial, as: partial.split("/").last, locals: { includes: subinc }
         | 
| 30 | 
            +
                      end
         | 
| 29 31 | 
             
                    end
         | 
| 30 | 
            -
                   | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
                     | 
| 35 | 
            -
             | 
| 36 | 
            -
                  json.cache_if!(can_cache, can_cache ? association_cache_key(record, inc, subinc) : nil) do
         | 
| 37 | 
            -
                    value = record.send(inc)
         | 
| 38 | 
            -
                    if value.nil?
         | 
| 39 | 
            -
                      json.set! inc, nil
         | 
| 40 | 
            -
                    else
         | 
| 41 | 
            -
                      partial = model_partial(value)
         | 
| 32 | 
            +
                  else
         | 
| 33 | 
            +
                    can_cache = can_cache_relation?(record, inc, subinc)
         | 
| 34 | 
            +
                    if association.is_a?(ActiveRecord::Reflection::BelongsToReflection)
         | 
| 35 | 
            +
                      can_cache = can_cache && !record.send(association.foreign_key).nil?
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
                    json.cache_if!(can_cache, can_cache ? [inc, association_cache_key(record, inc, subinc)] : nil) do
         | 
| 42 38 | 
             
                      json.set! inc do
         | 
| 43 | 
            -
                         | 
| 39 | 
            +
                        value = record.send(inc)
         | 
| 40 | 
            +
                        if value.nil?
         | 
| 41 | 
            +
                          json.value! nil
         | 
| 42 | 
            +
                        else
         | 
| 43 | 
            +
                          partial = model_partial(value)
         | 
| 44 | 
            +
                          json.partial! partial, partial.split("/").last.to_sym => value, includes: subinc
         | 
| 45 | 
            +
                        end
         | 
| 44 46 | 
             
                      end
         | 
| 45 47 | 
             
                    end
         | 
| 46 48 | 
             
                  end
         | 
| @@ -52,20 +54,20 @@ json.object! do | |
| 52 54 | 
             
                    elsif value.is_a?(ActiveModel::Model)
         | 
| 53 55 | 
             
                      json.set! inc do
         | 
| 54 56 | 
             
                        partial = model_partial(value)
         | 
| 55 | 
            -
                        json.partial! partial, partial.split( | 
| 57 | 
            +
                        json.partial! partial, partial.split("/").last.to_sym => value, includes: subinc
         | 
| 56 58 | 
             
                      end
         | 
| 57 59 | 
             
                    else
         | 
| 58 60 | 
             
                      json.set! inc, value.as_json
         | 
| 59 61 | 
             
                    end
         | 
| 60 62 | 
             
                  end
         | 
| 61 63 | 
             
                end
         | 
| 62 | 
            -
             | 
| 64 | 
            +
             | 
| 63 65 | 
             
              end
         | 
| 64 | 
            -
             | 
| 66 | 
            +
             | 
| 65 67 | 
             
              if !record.errors.blank?
         | 
| 66 68 | 
             
                errs = record.errors.to_hash
         | 
| 67 69 | 
             
                errs.default_proc = nil
         | 
| 68 | 
            -
                json.set!  | 
| 70 | 
            +
                json.set! "errors", errs
         | 
| 69 71 | 
             
              end
         | 
| 70 | 
            -
             | 
| 72 | 
            +
             | 
| 71 73 | 
             
            end
         | 
| @@ -52,7 +52,7 @@ else | |
| 52 52 | 
             
                model.columns.each do |column|
         | 
| 53 53 | 
             
                  json.set! column.name, {
         | 
| 54 54 | 
             
                    type: json_column_type(column.sql_type),
         | 
| 55 | 
            -
                    default: column.default  | 
| 55 | 
            +
                    default: column.default ? model.connection.lookup_cast_type_from_column(column).deserialize(column.default) : nil,
         | 
| 56 56 | 
             
                    primary_key: column.name == model.primary_key,
         | 
| 57 57 | 
             
                    null: column.null,
         | 
| 58 58 | 
             
                    array: column.array,
         | 
| @@ -61,7 +61,7 @@ else | |
| 61 61 | 
             
                    model.columns.each do |column|
         | 
| 62 62 | 
             
                      json.set! column.name, {
         | 
| 63 63 | 
             
                        type: json_column_type(column.sql_type),
         | 
| 64 | 
            -
                        default: column.default  | 
| 64 | 
            +
                        default: column.default ? model.connection.lookup_cast_type_from_column(column).deserialize(column.default) : nil,
         | 
| 65 65 | 
             
                        primary_key: column.name == model.primary_key,
         | 
| 66 66 | 
             
                        null: column.null,
         | 
| 67 67 | 
             
                        array: column.array,
         | 
| @@ -1 +1 @@ | |
| 1 | 
            -
            json.partial! model_partial(model), model_partial(model).split('/').last.to_sym => instance_variable_get("@#{model.model_name.singular}"), includes: includes
         | 
| 1 | 
            +
            json.partial! model_partial(model), model_partial(model).split('/').last.to_sym => instance_variable_get("@#{model.model_name.singular}"), includes: includes
         | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            require 'standard_api/test_helper'
         | 
| 2 2 |  | 
| 3 | 
            -
            class AccountsControllerTest <  | 
| 3 | 
            +
            class AccountsControllerTest < ActionDispatch::IntegrationTest
         | 
| 4 4 |  | 
| 5 5 | 
             
              test 'include with cache' do
         | 
| 6 6 | 
             
                account = create(:account, photos: [])
         | 
| @@ -14,20 +14,30 @@ class AccountsControllerTest < ActionController::TestCase | |
| 14 14 |  | 
| 15 15 | 
             
                # Cache Miss
         | 
| 16 16 | 
             
                Account.any_instance.stubs(:photos_cached_at).returns(t1)
         | 
| 17 | 
            -
                get  | 
| 17 | 
            +
                get account_path(account, include: :photos, format: :json)
         | 
| 18 18 | 
             
                assert_equal [photo.id], JSON(response.body)['photos'].map{|x| x['id']}
         | 
| 19 19 |  | 
| 20 20 | 
             
                # Cache Hit
         | 
| 21 21 | 
             
                Account.any_instance.stubs(:photos).returns([])
         | 
| 22 22 | 
             
                Account.any_instance.stubs(:photos_cached_at).returns(t1)
         | 
| 23 | 
            -
                get  | 
| 23 | 
            +
                get account_path(account, include: :photos, format: :json)
         | 
| 24 24 | 
             
                assert_equal [photo.id], JSON(response.body)['photos'].map{|x| x['id']}
         | 
| 25 25 |  | 
| 26 26 | 
             
                # Cache Miss, photos_cached_at updated
         | 
| 27 27 | 
             
                Account.any_instance.stubs(:photos).returns(Photo.where('false = true'))
         | 
| 28 28 | 
             
                Account.any_instance.stubs(:photos_cached_at).returns(t2)
         | 
| 29 | 
            -
                get  | 
| 29 | 
            +
                get account_path(account, include: :photos, format: :json)
         | 
| 30 30 | 
             
                assert_equal [], JSON(response.body)['photos'].map{|x| x['id']}
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                # Two associations that reference the same model
         | 
| 33 | 
            +
                property = create(:property)
         | 
| 34 | 
            +
                account = create(:account, property: property, subject: property)
         | 
| 35 | 
            +
                Account.any_instance.expects(:property_cached_at).returns(t1)
         | 
| 36 | 
            +
                Account.any_instance.expects(:subject_cached_at).returns(t1)
         | 
| 37 | 
            +
                get account_path(account, include: { property: true, subject: true }, format: 'json')
         | 
| 38 | 
            +
                json = JSON(response.body)
         | 
| 39 | 
            +
                assert json.has_key?('property')
         | 
| 40 | 
            +
                assert json.has_key?('subject')
         | 
| 31 41 | 
             
              end
         | 
| 32 42 |  | 
| 33 43 | 
             
            end
         | 
| @@ -45,26 +45,38 @@ class HelpersTest < ActionView::TestCase | |
| 45 45 | 
             
                assert can_cache?(Account, {photos: {account: {}}})
         | 
| 46 46 | 
             
              end
         | 
| 47 47 |  | 
| 48 | 
            -
              test '::can_cache_relation?' do
         | 
| 48 | 
            +
              test '::can_cache_relation? with non-persisted record' do
         | 
| 49 | 
            +
                account = build(:account)
         | 
| 50 | 
            +
                assert !can_cache_relation?(account, :photos, {})
         | 
| 51 | 
            +
                assert !can_cache_relation?(account, :photos, {})
         | 
| 52 | 
            +
                assert !can_cache_relation?(account, :photos, {account: {}})
         | 
| 53 | 
            +
                assert !can_cache_relation?(account, :photos, {account: {}})
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              test '::can_cache_relation? with persisted record' do
         | 
| 57 | 
            +
                account = create(:account)
         | 
| 58 | 
            +
             | 
| 49 59 | 
             
                Account.expects(:column_names).returns(['id', 'cached_at'])
         | 
| 50 | 
            -
                assert !can_cache_relation?( | 
| 60 | 
            +
                assert !can_cache_relation?(account, :photos, {})
         | 
| 51 61 |  | 
| 52 62 | 
             
                Account.expects(:column_names).returns(['id', 'cached_at', 'photos_cached_at'])
         | 
| 53 | 
            -
                assert can_cache_relation?( | 
| 63 | 
            +
                assert can_cache_relation?(account, :photos, {})
         | 
| 54 64 |  | 
| 55 65 | 
             
                Account.expects(:column_names).returns(['id', 'cached_at', 'photos_cached_at'])
         | 
| 56 | 
            -
                assert !can_cache_relation?( | 
| 66 | 
            +
                assert !can_cache_relation?(account, :photos, {account: {}})
         | 
| 57 67 |  | 
| 58 68 | 
             
                Account.expects(:column_names).returns(['id', 'cached_at', 'photos_cached_at', 'photos_account_cached_at'])
         | 
| 59 | 
            -
                assert can_cache_relation?( | 
| 69 | 
            +
                assert can_cache_relation?(account, :photos, {account: {}})
         | 
| 60 70 | 
             
              end
         | 
| 61 71 |  | 
| 62 72 | 
             
              test '::association_cache_key(record, relation, subincludes)' do
         | 
| 63 73 | 
             
                account = create(:account)
         | 
| 74 | 
            +
                photo = create(:photo, account: account)
         | 
| 64 75 | 
             
                t1 = Time.now
         | 
| 65 76 | 
             
                t2 = 1.day.from_now
         | 
| 66 77 | 
             
                t3 = 2.days.from_now
         | 
| 67 78 |  | 
| 79 | 
            +
                Account.expects(:column_names).returns(['id', 'cached_at', 'photos_cached_at', 'photos_property_cached_at'])
         | 
| 68 80 | 
             
                account.expects(:photos_cached_at).returns(t1)
         | 
| 69 81 |  | 
| 70 82 | 
             
                assert_equal(
         | 
| @@ -72,7 +84,7 @@ class HelpersTest < ActionView::TestCase | |
| 72 84 | 
             
                  association_cache_key(account, :photos, {})
         | 
| 73 85 | 
             
                )
         | 
| 74 86 |  | 
| 75 | 
            -
             | 
| 87 | 
            +
                Account.expects(:column_names).returns(['id', 'cached_at', 'photos_cached_at', 'photos_property_cached_at'])
         | 
| 76 88 | 
             
                account.expects(:photos_cached_at).returns(t1)
         | 
| 77 89 | 
             
                account.expects(:photos_property_cached_at).returns(t2)
         | 
| 78 90 | 
             
                assert_equal(
         | 
| @@ -80,6 +92,7 @@ class HelpersTest < ActionView::TestCase | |
| 80 92 | 
             
                  association_cache_key(account, :photos, {property: {}})
         | 
| 81 93 | 
             
                )
         | 
| 82 94 |  | 
| 95 | 
            +
                Account.expects(:column_names).returns(['id', 'cached_at', 'photos_cached_at', 'photos_property_cached_at'])
         | 
| 83 96 | 
             
                account.expects(:photos_cached_at).returns(t1)
         | 
| 84 97 | 
             
                account.expects(:photos_property_cached_at).returns(t2)
         | 
| 85 98 | 
             
                assert_equal(
         | 
| @@ -87,6 +100,7 @@ class HelpersTest < ActionView::TestCase | |
| 87 100 | 
             
                  association_cache_key(account, :photos, { "property" =>  { "order" => { "x" => "desc" }}})
         | 
| 88 101 | 
             
                )
         | 
| 89 102 |  | 
| 103 | 
            +
                Account.expects(:column_names).returns(['id', 'cached_at', 'photos_cached_at', 'photos_property_cached_at', 'photos_agents_cached_at'])
         | 
| 90 104 | 
             
                account.expects(:photos_cached_at).returns(t1)
         | 
| 91 105 | 
             
                account.expects(:photos_property_cached_at).returns(t2)
         | 
| 92 106 | 
             
                account.expects(:photos_agents_cached_at).returns(t3)
         | 
| @@ -95,6 +109,7 @@ class HelpersTest < ActionView::TestCase | |
| 95 109 | 
             
                  association_cache_key(account, :photos, {property: {}, agents: {}})
         | 
| 96 110 | 
             
                )
         | 
| 97 111 |  | 
| 112 | 
            +
                Account.expects(:column_names).returns(['id', 'cached_at', 'photos_cached_at', 'photos_property_cached_at', 'photos_property_agents_cached_at'])
         | 
| 98 113 | 
             
                account.expects(:photos_cached_at).returns(t1)
         | 
| 99 114 | 
             
                account.expects(:photos_property_cached_at).returns(t2)
         | 
| 100 115 | 
             
                account.expects(:photos_property_agents_cached_at).returns(t3)
         | 
| @@ -103,6 +118,7 @@ class HelpersTest < ActionView::TestCase | |
| 103 118 | 
             
                  association_cache_key(account, :photos, {property: {agents: {}}})
         | 
| 104 119 | 
             
                )
         | 
| 105 120 |  | 
| 121 | 
            +
                Account.expects(:column_names).returns(['id', 'cached_at', 'photos_cached_at', 'photos_property_cached_at', 'photos_agents_cached_at', 'photos_property_addresses_cached_at'])
         | 
| 106 122 | 
             
                account.expects(:photos_cached_at).returns(t1)
         | 
| 107 123 | 
             
                account.expects(:photos_property_cached_at).returns(t2)
         | 
| 108 124 | 
             
                account.expects(:photos_agents_cached_at).returns(t2)
         | 
| @@ -113,14 +129,14 @@ class HelpersTest < ActionView::TestCase | |
| 113 129 | 
             
                )
         | 
| 114 130 |  | 
| 115 131 | 
             
                # Belongs to
         | 
| 116 | 
            -
                 | 
| 132 | 
            +
                Photo.expects(:column_names).returns(['id', 'cached_at', 'account_cached_at'])
         | 
| 117 133 | 
             
                photo.expects(:account_cached_at).returns(t1)
         | 
| 118 134 | 
             
                assert_equal(
         | 
| 119 135 | 
             
                  "accounts/#{account.id}-#{t1.utc.to_s(ActiveRecord::Base.cache_timestamp_format)}",
         | 
| 120 136 | 
             
                  association_cache_key(photo, :account, {})
         | 
| 121 137 | 
             
                )
         | 
| 122 138 |  | 
| 123 | 
            -
                 | 
| 139 | 
            +
                Photo.expects(:column_names).returns(['id', 'cached_at', 'account_cached_at', 'account_photos_cached_at'])
         | 
| 124 140 | 
             
                photo.expects(:account_cached_at).returns(t1)
         | 
| 125 141 | 
             
                photo.expects(:account_photos_cached_at).returns(t2)
         | 
| 126 142 | 
             
                assert_equal(
         | 
| @@ -151,6 +167,6 @@ class HelpersTest < ActionView::TestCase | |
| 151 167 | 
             
                assert_equal 'boolean', json_column_type('boolean')
         | 
| 152 168 | 
             
                assert_equal 'ewkb', json_column_type('geometry')
         | 
| 153 169 | 
             
                assert_equal 'string', json_column_type('uuid')
         | 
| 154 | 
            -
             | 
| 170 | 
            +
              end
         | 
| 155 171 |  | 
| 156 172 | 
             
            end
         |