├── .gitignore ├── .rspec ├── .rubocop.yml ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── examples └── address.rb ├── firecord.gemspec ├── lib ├── firecord.rb └── firecord │ ├── configuration.rb │ ├── credentials.rb │ ├── error.rb │ ├── model.rb │ ├── patch │ └── as.rb │ ├── record.rb │ ├── record │ ├── deserializer.rb │ └── serializer.rb │ ├── repository │ ├── firebase.rb │ └── response.rb │ └── version.rb └── spec ├── firecord ├── credentials_spec.rb ├── record_spec.rb └── repository │ └── firebase_spec.rb ├── firecord_spec.rb ├── fixtures ├── fake_credentials.json └── vcr_cassettes │ ├── credentials_access_token.yml │ ├── firebase_all_valid.yml │ ├── firebase_delete_valid.yml │ ├── firebase_get_invalid.yml │ ├── firebase_get_valid.yml │ ├── firebase_init.yml │ ├── firebase_patch_invalid_attributes.yml │ ├── firebase_patch_invalid_id.yml │ ├── firebase_patch_valid.yml │ ├── firebase_post_valid_attributes.yml │ ├── invalid_model_all.yml │ ├── invalid_model_find.yml │ ├── invalid_model_where_valid.yml │ ├── valid_model_all.yml │ ├── valid_model_bootstrap_0.yml │ ├── valid_model_bootstrap_1.yml │ ├── valid_model_bootstrap_2.yml │ ├── valid_model_cleanup_0.yml │ ├── valid_model_cleanup_1.yml │ ├── valid_model_cleanup_2.yml │ ├── valid_model_find.yml │ └── valid_model_where.yml └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | 11 | # rspec failure tracking 12 | .rspec_status 13 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | Style/EmptyLinesAroundClassBody: 2 | Enabled: false 3 | 4 | Style/EmptyLinesAroundModuleBody: 5 | Enabled: false 6 | 7 | Style/FrozenStringLiteralComment: 8 | Enabled: true 9 | 10 | Style/MultilineMethodCallIndentation: 11 | EnforcedStyle: indented_relative_to_receiver 12 | 13 | Style/NumericPredicate: 14 | EnforcedStyle: comparison 15 | 16 | Style/Lambda: 17 | EnforcedStyle: lambda 18 | 19 | Style/BlockDelimiters: 20 | EnforcedStyle: semantic 21 | 22 | Style/FrozenStringLiteralComment: 23 | Enabled: false 24 | 25 | Metrics/LineLength: 26 | Max: 80 27 | 28 | AllCops: 29 | TargetRubyVersion: 2.4 30 | DisplayCopNames: true 31 | 32 | Documentation: 33 | Enabled: false 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: ruby 3 | rvm: 4 | - 2.4.0 5 | before_install: gem install bundler -v 1.14.4 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at tomas@stepnivlk.net. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in firecord.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Tomas Koutsky 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Firecord 2 | 3 | ![firecord](https://www.swiss-paracord.ch/media/image/product/50/md/firecord-550-acu-digital-25ft-762m~2.jpg) 4 | 5 | [![Build Status](https://travis-ci.org/stepnivlk/firecord.svg?branch=master)](https://travis-ci.org/stepnivlk/firecord) [![Ebert](https://ebertapp.io/github/stepnivlk/firecord.svg)](https://ebertapp.io/github/stepnivlk/firecord) 6 | 7 | Firecord is an ODM (Object-Document-Mapper) framework for Firebase in Ruby. 8 | 9 | Connects to the Firebase REST API, (for now) it's totally synchronous and provides similar API to all those classical Ruby ORMs. 10 | 11 | ## Usage 12 | 13 | You need to download ```credentials.json``` for your Firebase project (Firebase console > Project settings > Service accounts > Generate new private key) 14 | 15 | ```ruby 16 | require 'firecord' 17 | 18 | Firecord.configure do |config| 19 | config.credentials_file = '/path/to/credentials.json' 20 | end 21 | 22 | class Address 23 | include Firecord::Record 24 | 25 | root_key 'addresses' 26 | 27 | field :name, :string 28 | field :location, :string 29 | field :door_number, :integer 30 | field :timestamps 31 | end 32 | 33 | address = Address.new(name: 'home', location: 'Prerov', door_number: 1) 34 | # => #
35 | 36 | address.save 37 | # => #
38 | 39 | another_address = Address.find("-KdvwtldpM4yVWJfoQIg") 40 | # => #
41 | 42 | another_address.door_number = 23 43 | # => 23 44 | 45 | another_address.save 46 | # => #
47 | 48 | another_address.update(location: 'Prerov nad Labem') 49 | # => #
50 | 51 | Address.where(name: "not_home", door_number: 23) 52 | # => [#
] 53 | 54 | Address.all 55 | # => [#
, #
] 56 | 57 | address.delete 58 | # => true 59 | 60 | Address.all 61 | # => [#
] 62 | ``` 63 | 64 | ## Current version: 0.2.6 65 | This version adds: 66 | * Basic retypying/checking of invalid assignments, eg: ```address.door_number = '23' #=> 23```. 67 | * ```.where``` method which for now accepts hash and works only for equality, eg: ```Address.where(door_number: 23)``` 68 | * Adds proper ```DateTime``` object for ```created_at``` and ```updated_at``` fields 69 | * Adds more 'integration' tests for dummy classes. 70 | * Introduces ```Serializer``` and ```Deserializer``` classes. 71 | 72 | ### Roadmap to version 0.3.0 73 | - [x] Working timestamps 74 | - [ ] Error handling 75 | - [x] `where` method 76 | - [ ] Test everything 77 | - [x] Better configuration 78 | - [x] Documentation 79 | - [x] Basic type validation 80 | - [ ] Get rid of nil checks in firebase repo 81 | - [ ] Add fields: boolean, datetime, time, date, json 82 | - [ ] Add ```.delete_all``` method 83 | - [ ] Add ```.create``` method 84 | 85 | ### Future versions 86 | - [ ] Add proper validation 87 | - [ ] Robust persistence state abstraction 88 | - [ ] Some basic associations 89 | - [ ] Define nested documents 90 | 91 | #### Version log 92 | ##### 0.2.2 codename Spike 93 | This release is not meant to be used by anyone in production. I'm trying to lay down the interface, experiment and learn basics of ORM/ODM by coding and producing something (maybe) usefull. I still need to finalize some functionality, do refactoring and add features. 94 | 95 | 96 | ## Installation 97 | 98 | Add this line to your application's Gemfile: 99 | 100 | ```ruby 101 | gem 'firecord' 102 | ``` 103 | 104 | And then execute: 105 | 106 | $ bundle 107 | 108 | Or install it yourself as: 109 | 110 | $ gem install firecord 111 | 112 | 113 | ## Development 114 | 115 | After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. 116 | 117 | To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). 118 | 119 | ## Contributing 120 | 121 | Bug reports and pull requests are welcome on GitHub at https://github.com/stepnivlk/firecord. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. 122 | 123 | 124 | ## License 125 | 126 | The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). 127 | 128 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rspec/core/rake_task' 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task default: :spec 7 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "firecord" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start(__FILE__) 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /examples/address.rb: -------------------------------------------------------------------------------- 1 | require '../lib/firecord' 2 | 3 | Firecord.configure do |config| 4 | config.credentials_file = '../../credentials.json' 5 | end 6 | 7 | class Address 8 | include Firecord::Record 9 | 10 | root_key 'addresses' 11 | 12 | field :name, :string 13 | field :location, :string 14 | field :door_number, :integer 15 | field :timestamps 16 | end 17 | -------------------------------------------------------------------------------- /firecord.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'firecord/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = 'firecord' 8 | spec.version = Firecord::VERSION 9 | spec.authors = ['Tomas Koutsky'] 10 | spec.email = ['tomas@stepnivlk.net'] 11 | 12 | spec.summary = 'Firecord is an ODM framework for Firebase in Ruby.' 13 | spec.description = 'Firecord is an ODM (Object-Document-Mapper) framework' \ 14 | ' for Firebase in Ruby.' 15 | spec.homepage = "http://stepnivlk.net" 16 | spec.license = 'MIT' 17 | 18 | spec.files = `git ls-files -z`.split("\x0").reject do |f| 19 | f.match(%r{^(test|spec|features)/}) 20 | end 21 | spec.bindir = 'exe' 22 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 23 | spec.require_paths = ['lib'] 24 | 25 | spec.add_runtime_dependency 'jwt', '~> 1.5' 26 | spec.add_runtime_dependency 'httparty', '~> 0.14' 27 | 28 | spec.add_development_dependency 'bundler', '~> 1.14' 29 | spec.add_development_dependency 'rake', '~> 10.0' 30 | spec.add_development_dependency 'rspec', '~> 3.0' 31 | spec.add_development_dependency 'webmock', '~> 2.3' 32 | spec.add_development_dependency 'vcr', '~> 3.0' 33 | end 34 | -------------------------------------------------------------------------------- /lib/firecord.rb: -------------------------------------------------------------------------------- 1 | require "firecord/version" 2 | require 'firecord/configuration' 3 | require 'firecord/credentials' 4 | require 'firecord/repository/firebase' 5 | require 'firecord/repository/response' 6 | require 'firecord/record' 7 | require 'firecord/record/serializer' 8 | require 'firecord/record/deserializer' 9 | require 'firecord/model' 10 | require 'firecord/error' 11 | require 'firecord/patch/as' 12 | 13 | module Firecord 14 | extend Configuration 15 | end 16 | -------------------------------------------------------------------------------- /lib/firecord/configuration.rb: -------------------------------------------------------------------------------- 1 | module Firecord 2 | module Configuration 3 | CREDENTIALS_FILE = './credentials.json'.freeze 4 | 5 | VALID_ACCESSORS = [:credentials_file].freeze 6 | 7 | attr_accessor(*VALID_ACCESSORS) 8 | 9 | def configure 10 | yield self 11 | end 12 | 13 | def options 14 | VALID_ACCESSORS.inject({}) do |accessor, key| 15 | accessor.merge!(key => send(key)) 16 | end 17 | end 18 | 19 | def self.extended(mod) 20 | mod.set_defaults 21 | end 22 | 23 | def set_defaults 24 | self.credentials_file = CREDENTIALS_FILE 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/firecord/credentials.rb: -------------------------------------------------------------------------------- 1 | require 'jwt' 2 | 3 | module Firecord 4 | class Credentials 5 | def initialize(credentials_file = nil) 6 | @credentials = \ 7 | JSON.parse(File.read(credentials_file || Firecord.credentials_file)) 8 | @private_key = OpenSSL::PKey::RSA.new @credentials['private_key'] 9 | end 10 | 11 | def project_id 12 | @credentials['project_id'] 13 | end 14 | 15 | def generate_jwt_assertion 16 | now_seconds = Time.now.to_i 17 | payload = { 18 | iss: @credentials['client_email'], 19 | aud: @credentials['token_uri'], 20 | iat: now_seconds, 21 | exp: now_seconds + (60 * 60), 22 | scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/firebase.database' 23 | } 24 | JWT.encode payload, @private_key, 'RS256' 25 | end 26 | 27 | def generate_access_token 28 | uri = URI.parse(@credentials['token_uri']) 29 | https = Net::HTTP.new(uri.host, uri.port) 30 | https.use_ssl = true 31 | req = Net::HTTP::Post.new(uri.path) 32 | req['Cache-Control'] = 'no-store' 33 | req.set_form_data( 34 | grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', 35 | assertion: generate_jwt_assertion 36 | ) 37 | 38 | resp = JSON.parse(https.request(req).body) 39 | resp['access_token'] 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/firecord/error.rb: -------------------------------------------------------------------------------- 1 | module Firecord 2 | class Error < StandardError; end 3 | 4 | class InvalidQuery < Error; end 5 | end 6 | -------------------------------------------------------------------------------- /lib/firecord/model.rb: -------------------------------------------------------------------------------- 1 | module Firecord 2 | module Model 3 | def self.extended(model) 4 | model.instance_variable_set(:@fields, []) 5 | model.fields << OpenStruct.new(name: :id, type: :private_key) 6 | end 7 | 8 | def field(name, type = nil) 9 | return timestamps if name == :timestamps 10 | 11 | @fields << OpenStruct.new(name: name, type: type) 12 | end 13 | 14 | def timestamps 15 | %i(created_at updated_at).each do |stamp| 16 | @fields << OpenStruct.new(name: stamp, type: :datetime) 17 | end 18 | end 19 | 20 | def all 21 | repository 22 | .all 23 | .reject { |response| response.keys.include?(:error) } 24 | .map { |response| new(response).persist } 25 | end 26 | 27 | def find(id) 28 | response = repository.get(id) 29 | response.nil? ? nil : new(response).persist 30 | end 31 | 32 | def where(query) 33 | validate_query!(query) 34 | 35 | all.select do |record| 36 | result = query.map { |name, value| record.send(name) == value }.uniq 37 | 38 | result.size == 1 && result[0] == true ? true : false 39 | end 40 | end 41 | 42 | def root_key(root_name) 43 | @root = root_name 44 | end 45 | 46 | def fields 47 | @fields 48 | end 49 | 50 | def root 51 | @root || name.downcase 52 | end 53 | 54 | def repository 55 | @repository ||= Repository::Firebase.new(root) 56 | end 57 | 58 | def validate_query!(query) 59 | result = query.keys - fields.map(&:name) 60 | raise InvalidQuery, 'Your query contains invalid key(s)' \ 61 | unless result.empty? 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/firecord/patch/as.rb: -------------------------------------------------------------------------------- 1 | class Object 2 | def as 3 | yield self 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/firecord/record.rb: -------------------------------------------------------------------------------- 1 | module Firecord 2 | module Record 3 | def self.included(model) 4 | model.extend(Model) 5 | super 6 | end 7 | 8 | alias model class 9 | 10 | def initialize(params = {}) 11 | fields.each do |field| 12 | initialize_accessor(field, params) 13 | end 14 | end 15 | 16 | def save 17 | return _create if new? 18 | 19 | _update 20 | end 21 | 22 | def update(attributes = {}) 23 | attributes.each do |name, value| 24 | send("#{name}=", value) 25 | end 26 | 27 | tap { |record| repository.patch(record) } 28 | end 29 | 30 | def delete 31 | repository.delete(id) 32 | end 33 | 34 | def inspect 35 | attrs = fields.map { |field| 36 | value = get_value(field.name) 37 | formatted = value.is_a?(String) ? "\"#{value}\"" : value 38 | 39 | "#{field.name}=#{formatted || 'nil'}" 40 | } 41 | 42 | "#<#{model.name} #{attrs.join(' ')}>" 43 | end 44 | 45 | def new? 46 | persistence_state == :transient 47 | end 48 | 49 | def persist 50 | @persistence_state = :persisted 51 | 52 | self 53 | end 54 | 55 | def method_missing(method, *args, &block) 56 | return super unless available_names.include?(method) 57 | 58 | return set_value(method, args[0]) if method.to_s.end_with?('=') 59 | get_value(method) 60 | end 61 | 62 | def respond_to_missing?(method, include_private = false) 63 | available_names.include?(method) || super 64 | end 65 | 66 | def fields 67 | model.fields 68 | end 69 | 70 | private 71 | 72 | def set_value(name, value, type = nil) 73 | type ||= field_for(name).type 74 | sanitizer = Serializer.new(value, type) 75 | 76 | send("_#{name}", sanitizer.value) 77 | end 78 | 79 | def get_value(name) 80 | value = send("_#{name}") 81 | 82 | return value if value.nil? 83 | 84 | Deserializer.new(value, field_for(name).type).value 85 | end 86 | 87 | def available_names 88 | fields.map(&:name) + fields.map { |field| :"#{field.name}=" } 89 | end 90 | 91 | def _create 92 | tap do |record| 93 | record.created_at = DateTime.now 94 | record.id = repository.post(persist)[:name] 95 | end 96 | end 97 | 98 | def _update 99 | tap do |record| 100 | record.updated_at = DateTime.now 101 | repository.patch(record) 102 | end 103 | end 104 | 105 | def field_for(name) 106 | sanitized_name = name.to_s.end_with?('=') ? :"#{name[0..-2]}" : name 107 | fields.find { |field| field.name == sanitized_name } 108 | end 109 | 110 | def repository 111 | model.repository 112 | end 113 | 114 | def persistence_state 115 | @persistence_state ||= :transient 116 | end 117 | 118 | def initialize_accessor(field, params) 119 | name = field.name 120 | 121 | restrict_accessor(name) 122 | 123 | value = params[name] || nil 124 | set_value("#{name}=", value, field.type) if value 125 | end 126 | 127 | def restrict_accessor(name) 128 | self.class.class_eval do 129 | attr_accessor("_#{name}") 130 | end 131 | 132 | self.class.instance_eval do 133 | private(:"_#{name}") 134 | private(:"_#{name}=") 135 | end 136 | end 137 | end 138 | end 139 | -------------------------------------------------------------------------------- /lib/firecord/record/deserializer.rb: -------------------------------------------------------------------------------- 1 | module Firecord 2 | module Record 3 | class Deserializer 4 | def initialize(value, type) 5 | @value = value 6 | @type = type 7 | end 8 | 9 | def value 10 | send(@type) 11 | end 12 | 13 | private 14 | 15 | %w(string integer float private_key).each do |type| 16 | define_method(type) do 17 | @value 18 | end 19 | end 20 | 21 | def datetime 22 | DateTime.parse(@value) 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/firecord/record/serializer.rb: -------------------------------------------------------------------------------- 1 | module Firecord 2 | module Record 3 | class Serializer 4 | def initialize(value, type) 5 | @value = value 6 | @type = type 7 | end 8 | 9 | def value 10 | @value.nil? ? @value : send(@type) 11 | end 12 | 13 | private 14 | 15 | %w(string datetime).each do |type| 16 | define_method(type) do 17 | @value.to_s 18 | end 19 | end 20 | 21 | def private_key 22 | @value 23 | end 24 | 25 | def integer 26 | @value.respond_to?(:to_i) ? @value.to_i : nil 27 | end 28 | 29 | def float 30 | @value.respond_to?(:to_f) ? @value.to_f : nil 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/firecord/repository/firebase.rb: -------------------------------------------------------------------------------- 1 | require 'httparty' 2 | 3 | module Firecord 4 | module Repository 5 | class Firebase 6 | include HTTParty 7 | 8 | def initialize(root) 9 | @credentials = Credentials.new 10 | @root = root 11 | self.class.base_uri "https://#{@credentials.project_id}.firebaseio.com/" 12 | end 13 | 14 | def all 15 | self 16 | .class.get("/#{@root}.json", options) 17 | .as { |response| Response.new(response).sanitize } 18 | .map { |id, data| Response.new(data.merge(id: id)).sanitize } 19 | end 20 | 21 | def get(id) 22 | self 23 | .class.get("/#{@root}/#{id}.json", options) 24 | .as { |response| Response.new(response, id: id).sanitize_with_nil } 25 | end 26 | 27 | def post(record) 28 | self 29 | .class.post("/#{@root}.json", payload(record)) 30 | .as { |response| Response.new(response).sanitize } 31 | end 32 | 33 | def patch(record) 34 | self 35 | .class.patch("/#{@root}/#{record.id}.json", payload(record)) 36 | .as { |response| Response.new(response).sanitize } 37 | end 38 | 39 | def delete(id) 40 | self 41 | .class.delete("/#{@root}/#{id}.json", options) 42 | .as { |response| response ? false : true } 43 | end 44 | 45 | private 46 | 47 | def payload(record) 48 | options.dup.tap do |data| 49 | data[:body] = body(record).to_json 50 | end 51 | end 52 | 53 | def body(record) 54 | record.fields.each_with_object({}) do |field, data| 55 | next if field.type == :private_key 56 | 57 | data[field.name] = record.send(field.name) 58 | end 59 | end 60 | 61 | def options 62 | { 63 | headers: { 64 | 'Authorization' => "Bearer #{@credentials.generate_access_token}", 65 | 'Content-Type' => 'application/json', 66 | 'User-Agent' => 'X-FIREBASE-CLIENT' 67 | } 68 | } 69 | end 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /lib/firecord/repository/response.rb: -------------------------------------------------------------------------------- 1 | module Firecord 2 | module Repository 3 | class Response 4 | def initialize(response, default = {}) 5 | @response = response 6 | @default = default 7 | end 8 | 9 | def sanitize 10 | @response ? symbolize_keys : invalid_record 11 | end 12 | 13 | def sanitize_with_nil 14 | @response ? symbolize_keys : nil 15 | end 16 | 17 | private 18 | 19 | def symbolize_keys 20 | @response.each_with_object(@default) do |(key, value), result| 21 | result[key.to_sym] = value 22 | result 23 | end 24 | end 25 | 26 | def invalid_record 27 | { nil => { error: 'invalid response' } } 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/firecord/version.rb: -------------------------------------------------------------------------------- 1 | module Firecord 2 | VERSION = '0.2.6'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /spec/firecord/credentials_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Firecord::Credentials do 4 | context 'valid credentials.json given' do 5 | let(:fixtures_path) { 6 | File.join(File.dirname(__dir__), 'fixtures', 'fake_credentials.json') 7 | } 8 | let(:credentials) { described_class.new(fixtures_path) } 9 | let(:credentials_file) { JSON.parse(File.read(fixtures_path)) } 10 | let(:decoded) { JWT.decode(credentials.generate_jwt_assertion, nil, false) } 11 | let(:scope) { 12 | 'https://www.googleapis.com/auth/userinfo.email ' \ 13 | 'https://www.googleapis.com/auth/firebase.database' 14 | } 15 | 16 | it 'Initializes itself properly' do 17 | expect(credentials.project_id).to eq('addrssr-8612c') 18 | end 19 | 20 | it 'Encodes credentials data to JWT' do 21 | expect(decoded).to be_a(Array) 22 | expect(decoded.size).to eq(2) 23 | expect(decoded[0]).to include( 24 | 'iss' => credentials_file['client_email'], 25 | 'aud' => credentials_file['token_uri'], 26 | 'scope' => scope 27 | ) 28 | expect(decoded[0]['iat']).to_not be_nil 29 | expect(decoded[0]['exp']).to_not be_nil 30 | 31 | expect(decoded[1]).to include( 32 | 'typ' => 'JWT', 33 | 'alg' => 'RS256' 34 | ) 35 | end 36 | 37 | it 'Contacts remote API and generates access token' do 38 | VCR.use_cassette('credentials_access_token') do 39 | expect(credentials.generate_access_token).to_not be_nil 40 | end 41 | end 42 | end 43 | 44 | context 'invalid credentials.json given' do 45 | it 'raises an exception' do 46 | expect { 47 | described_class.new('invalid_path') 48 | }.to raise_error(Errno::ENOENT) 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /spec/firecord/record_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | context 'Valid credentials given' do 4 | Firecord.configure do |config| 5 | config.credentials_file = \ 6 | File.join( 7 | File.dirname(__dir__), 'fixtures', 'fake_credentials.json' 8 | ) 9 | end 10 | 11 | context 'Fields in class are present, but database is empty' do 12 | class Dummy 13 | include Firecord::Record 14 | 15 | root_key 'empty_root' 16 | 17 | field :name, :string 18 | field :timestamps 19 | end 20 | 21 | context 'Methods extended to the class' do 22 | describe '.fields' do 23 | it 'Lists all the fields' do 24 | expect(Dummy.fields).to eq([ 25 | OpenStruct.new(name: :id, type: :private_key), 26 | OpenStruct.new(name: :name, type: :string), 27 | OpenStruct.new(name: :created_at, type: :datetime), 28 | OpenStruct.new(name: :updated_at, type: :datetime), 29 | ]) 30 | end 31 | end 32 | 33 | describe '.all' do 34 | let(:all) { VCR.use_cassette('invalid_model_all') { Dummy.all } } 35 | 36 | it 'Returns an empty array when there are no records' do 37 | expect(all).to eq([]) 38 | end 39 | end 40 | 41 | describe '.find' do 42 | let(:find) { VCR.use_cassette('invalid_model_find') { Dummy.find('id') } } 43 | 44 | it 'Returns nil when there are no records with given ID' do 45 | expect(find).to eq(nil) 46 | end 47 | end 48 | 49 | describe '.where' do 50 | context 'valid accessors given' do 51 | let(:where) { 52 | VCR.use_cassette('invalid_model_where_valid') { 53 | Dummy.where(name: 'name') 54 | } 55 | } 56 | 57 | it 'Returns nil when there are no records with given ID' do 58 | expect(where).to eq([]) 59 | end 60 | end 61 | 62 | context 'invalid accessors given' do 63 | it 'Throws an exception' do 64 | expect { 65 | Dummy.where(name_invalid: 'name') 66 | }.to raise_error(Firecord::InvalidQuery) 67 | end 68 | end 69 | end 70 | end 71 | 72 | context 'Fields in class are present and there are records in database' do 73 | class DummyValid 74 | include Firecord::Record 75 | 76 | root_key 'root' 77 | 78 | field :name, :string 79 | field :age, :integer 80 | field :skill, :float 81 | field :timestamps 82 | end 83 | 84 | before(:all) do 85 | 3.times do |index| 86 | VCR.use_cassette("valid_model_bootstrap_#{index}") { 87 | DummyValid 88 | .new(name: "name_#{index}", age: index, skill: index) 89 | .save 90 | } 91 | end 92 | end 93 | 94 | after(:all) do 95 | DummyValid.all.each_with_index do |record, index| 96 | VCR.use_cassette("valid_model_cleanup_#{index}") { 97 | record.delete 98 | } 99 | end 100 | end 101 | 102 | let(:all) { VCR.use_cassette('valid_model_all') { DummyValid.all } } 103 | let(:first) { all[0] } 104 | 105 | context 'Methods extended to the class' do 106 | describe '.all' do 107 | it 'Returns an array of all records' do 108 | expect(all).to_not eq([]) 109 | expect(all.size).to eq(3) 110 | end 111 | end 112 | 113 | describe '.find' do 114 | let(:find) { 115 | VCR.use_cassette('valid_model_find') { DummyValid.find(all[0].id) } 116 | } 117 | 118 | it 'Returns record with given ID' do 119 | expect(find).to_not be_nil 120 | expect(find).to be_a(DummyValid) 121 | expect(find.name).to eq('name_0') 122 | end 123 | end 124 | 125 | describe '.where' do 126 | context 'valid accessors given' do 127 | let(:where) { 128 | VCR.use_cassette('valid_model_where') { 129 | DummyValid.where(age: 2) 130 | } 131 | } 132 | 133 | it 'Returns an array of records fulfilling given condition' do 134 | expect(where.size).to eq(1) 135 | expect(where[0].name).to eq(all[2].name) 136 | end 137 | end 138 | end 139 | end 140 | 141 | context 'Methods included to a class' do 142 | it 'responds to the \'ID\'' do 143 | expect(first.id).to_not be_nil 144 | end 145 | 146 | it 'responds to the \'name\'' do 147 | expect(first.name).to eq('name_0') 148 | end 149 | 150 | it 'responds to the \'age\'' do 151 | expect(first.age).to eq(0) 152 | end 153 | 154 | it 'responds to the \'skill\'' do 155 | expect(first.skill).to eq(0.0) 156 | end 157 | 158 | it 'responds to the \'created_at\'' do 159 | expect(first.created_at).to be_a(DateTime) 160 | end 161 | 162 | it 'responds to the \'updated_at\'' do 163 | expect(first.updated_at).to be_nil 164 | end 165 | 166 | it 'serializes itself for inspect' do 167 | output = "#" 174 | 175 | expect(first.inspect).to eq(output) 176 | end 177 | 178 | it 'throws an error while accessing invalid field' do 179 | expect { first.name_invalid }.to raise_error(NoMethodError) 180 | end 181 | 182 | it 'Retypes integer when assigning string field' do 183 | first.name = 23 184 | expect(first.name).to eq('23') 185 | end 186 | 187 | it 'Retypes string when assigning integer field' do 188 | first.age = '23' 189 | expect(first.age).to eq(23) 190 | end 191 | 192 | it 'Retypes string when assigning float field' do 193 | first.skill = '23.23' 194 | expect(first.skill).to eq(23.23) 195 | end 196 | 197 | it 'Assigns nil when invalid type given' do 198 | first.age = {a: 1} 199 | expect(first.age).to eq(nil) 200 | end 201 | end 202 | end 203 | end 204 | end 205 | -------------------------------------------------------------------------------- /spec/firecord/repository/firebase_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Firecord::Repository::Firebase do 4 | context 'Valid credentials and valid set of records given' do 5 | Firecord.configure do |config| 6 | config.credentials_file = \ 7 | File.join( 8 | File.dirname(__dir__), '../', 'fixtures', 'fake_credentials.json' 9 | ) 10 | end 11 | 12 | let(:firebase) { 13 | VCR.use_cassette('firebase_init') { described_class.new('todos') } 14 | } 15 | let(:credentials) { firebase.instance_variable_get(:@credentials) } 16 | let(:root) { firebase.instance_variable_get(:@root) } 17 | 18 | it 'Sets own variables' do 19 | expect(credentials).to_not be_nil 20 | expect(credentials).to be_a(Firecord::Credentials) 21 | expect(root).to eq('todos') 22 | end 23 | 24 | it 'Sets base_uri of it\'s class' do 25 | expect(firebase.class.base_uri) 26 | .to eq("https://#{credentials.project_id}.firebaseio.com") 27 | end 28 | 29 | context 'Accessing public instance methods' do 30 | let(:all) { VCR.use_cassette('firebase_all_valid') { firebase.all } } 31 | let(:fields_valid) { 32 | [ 33 | OpenStruct.new(name: :name), 34 | OpenStruct.new(name: :priority) 35 | ] 36 | } 37 | 38 | describe '#all' do 39 | it 'lists all the records' do 40 | expect(all).to be_a(Array) 41 | expect(all.size).to_not eq(0) 42 | expect(all[0]).to be_a(Hash) 43 | end 44 | end 45 | 46 | describe '#get' do 47 | let(:id) { all[0][:id] } 48 | let(:response) { 49 | VCR.use_cassette('firebase_get_valid') { 50 | firebase.get(id) 51 | } 52 | } 53 | 54 | it 'Gets the record by valid ID' do 55 | expect(response).to_not be_nil 56 | expect(response).to be_a(Hash) 57 | expect(response[:id]).to eq(id) 58 | end 59 | 60 | it 'Tries to get a record by invalid ID and returns nil' do 61 | id = 'invalid' 62 | record = VCR.use_cassette('firebase_get_invalid') { firebase.get(id) } 63 | 64 | expect(record).to be_nil 65 | end 66 | end 67 | 68 | describe '#post' do 69 | let(:record) { 70 | OpenStruct.new( 71 | name: 'fake', 72 | priority: 23, 73 | fields: fields_valid 74 | ) 75 | } 76 | let(:response) { 77 | VCR.use_cassette('firebase_post_valid_attributes') { 78 | firebase.post(record) 79 | } 80 | } 81 | 82 | it 'Creates new record when record with valid attributes given' do 83 | expect(response).to_not be_nil 84 | expect(response).to be_a(Hash) 85 | expect(response[:name]).to be_a(String) 86 | end 87 | end 88 | 89 | describe '#patch' do 90 | let(:record_valid) { 91 | OpenStruct.new( 92 | id: all[1][:id], 93 | name: 'fake', 94 | priority: 23, 95 | fields: fields_valid 96 | ) 97 | } 98 | let(:record_invalid_attributes) { 99 | OpenStruct.new( 100 | id: all[2][:id], 101 | invalid_a: 'invalid_a', 102 | invalid_b: 'invalid_b', 103 | fields: fields_valid 104 | ) 105 | } 106 | let(:record_invalid_id) { 107 | OpenStruct.new( 108 | id: 'invalid_id', 109 | name: 'fake', 110 | priority: 23, 111 | fields: fields_valid 112 | ) 113 | } 114 | let(:response_valid) { 115 | VCR.use_cassette('firebase_patch_valid') { 116 | firebase.patch(record_valid) 117 | } 118 | } 119 | let(:response_invalid_attributes) { 120 | VCR.use_cassette('firebase_patch_invalid_attributes') { 121 | firebase.patch(record_invalid_attributes) 122 | } 123 | } 124 | let(:response_invalid_id) { 125 | VCR.use_cassette('firebase_patch_invalid_id') { 126 | firebase.patch(record_invalid_attributes) 127 | } 128 | } 129 | 130 | it 'Updates existing record when valid record given' do 131 | expect(response_valid).to_not be_nil 132 | expect(response_valid).to be_a(Hash) 133 | expect(response_valid[:name]) 134 | .to eq(record_valid.name) 135 | expect(response_valid[:priority]) 136 | .to eq(record_valid.priority) 137 | end 138 | 139 | it 'Does not update record when record with invalid attributes given' do 140 | expect(response_invalid_attributes).to_not be_nil 141 | expect(response_invalid_attributes[:invalid_a]).to be_nil 142 | expect(response_invalid_attributes[:invalid_b]).to be_nil 143 | end 144 | 145 | it 'Fails when invalid ID given' do 146 | expect(response_invalid_id).to_not be_nil 147 | expect(response_invalid_id).to be_a(Hash) 148 | expect(response_invalid_id[:name]).to be_nil 149 | expect(response_invalid_id[:priority]).to be_nil 150 | end 151 | end 152 | 153 | describe '#delete' do 154 | let(:response_valid) { 155 | VCR.use_cassette('firebase_delete_valid') { 156 | firebase.delete(all[3][:id]) 157 | } 158 | } 159 | 160 | it 'Deletes record and returns true when valid ID given' do 161 | expect(response_valid).to be_truthy 162 | end 163 | end 164 | end 165 | end 166 | end 167 | -------------------------------------------------------------------------------- /spec/firecord_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | RSpec.describe Firecord do 4 | it 'has a version number' do 5 | expect(Firecord::VERSION).not_to be nil 6 | end 7 | 8 | context 'Configuring credentials path' do 9 | let(:fake_path) { '/test/credentials.json' } 10 | 11 | before do 12 | described_class.configure do |config| 13 | config.credentials_file = fake_path 14 | end 15 | end 16 | 17 | it 'Sets credentials_file variable' do 18 | expect(described_class.credentials_file).to eq(fake_path) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/fixtures/fake_credentials.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "service_account", 3 | "project_id": "addrssr-8612c", 4 | "private_key_id": "fa50c258162f5d6a4b187c836ba1881b4c3d8fef", 5 | "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDTjAtgwENUXuTi\ncQygqIXM3coeWdSOU4kb2VV0iYHnOkL+/8Rev87IKiq6w5QAwPShU0rvBv8ZkYiF\nKFIT7sdmyLoUK2ASpFZQHXQ8SYFIjX402pIJKRnZcbfG6xXWKmUn4op5nl/wGPEy\ntggDdEB7kuEr2iJ0z6o+vPilFTVRpSdfW87Que72UYpf4DeQiTS7XyxoBPGoDE+5\n0Od+aayuULSlyBKyslMGoFgpwFxf4r+fT/83ApOqdC3wnZfLFfO/VA15Ai7A/APN\nLvDyYXjx06yKnOqVF/eJWget9MOOr9hhSe8IXUGRTPtow772ISlylWIA5bpxpzz5\nrtD854dfAgMBAAECggEBAKwa9W7DPIO5qDDplEJomGJx1mwW3SzlnViA2lszO/Io\nnjTjVJlZJxwF4jmLwC9UzDErmH0ajhP5KL5cbVo2GxfuGiUqnMDN3kLTk6swifPC\n2XiakdDOFW+oasF0pJFWcHGghtQnGxo00JZXLfHRdFyUxIhusTWjdXgROaDkvjoq\nzlEOE2wIC0kQimnarVBOsHoPxc+LXNpkW8n4pHgCknlKTjBEBx/2kaWf0HO0aPNR\n3y6WjhB0jeV8fCO6Z+uatfoig4pZkVCsgdlXEOzvzT34XS74w85q1rrV3yGbRnXM\nZD1/44T8aRJop1MmoEgeLUPvvYApWheutHFLD+FR3eECgYEA6iswhny7MnP0/9px\nkWDSceTtdp130DNJd3+I+cHSzjjRL0mTMFuRq1Fw7gZX8NRm475zSWneZh+fcrll\nnmh4QQvoDvyo2H1DQ53kPw/1LvhLXm0X2jCnA8IHfP2gNALQ8thKYW4rfnmkHtDi\nBH+TeeXJcDykRthmhmOTtZh5FZcCgYEA50Tz65pz/UZHISN9CcCv0ISbtpT4y4DC\nPSHDV1q0EZM78HAVUC1AWw6+PuY+Z6W+UTPjjcWtUDBaGKPSwM5CioJeXBbcltAp\ntJrC8HmpugBrZTGlvQ3NUNJB0Fv8wLUU5wFAxStXJ6r1KqBSo+5zila3+6OECS97\n8UTSJjGOpXkCgYEAyM6QpkOAJBvcFSu2B/0HejPejsEqZZgVgCwVwle79qwydmKZ\nnfZoTIliVjuKXjNGqDZBlsr6tIiZqz/hLJ5ZwS38qh1wjXWdoPZdLNb6YnT57NeQ\nhMMD9e0FjuHP58oidJ2V60cWdTbKzsJBj6n3RakPvPfDyBz6jnQFzswZybECgYEA\n0EdrHY5WU41NVezuGTBtpm8nBUIY5r2pMQENOci4TvO4kYt/xltakCcw8tjM7u93\n/Q2sK+wRcBx7p6Eylu2rQ66xaGI2e6QxSzPtyEDpuFfUYKhbyW16sQUKvKl7cdoj\nXv/j4y5rKZBvh9onUvfXGomK3Jegu90F1H3UfQ04mJECgYBKL+c4crkmxqQYUrQ6\nbBMQ7WT9tj6CmadoXx3tuu+SK4wDyKMTDrGVeVdGmUHx8KQVEvUec8Z5h1mwYhOA\n9fCRKtW5LhKLPDweiQ6/H9wUSRdFW0klLJt1sUHaNCb+iQTHXLX78emfJ+99vqYY\nMCZ1sQxlygguBNtGRBxmcqXqLA==\n-----END PRIVATE KEY-----\n", 6 | "client_email": "firebase-adminsdk-5sl8y@addrssr-8612c.iam.gserviceaccount.com", 7 | "client_id": "117141047839489509290", 8 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 9 | "token_uri": "https://accounts.google.com/o/oauth2/token", 10 | "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", 11 | "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-5sl8y%40addrssr-8612c.iam.gserviceaccount.com" 12 | } 13 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/credentials_access_token.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDg4MTUxMTAzLCJleHAiOjE0ODgxNTQ3MDMsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.foCs5CZq0TrZ2Rw_Agyze8eEGMqQAMRxHxbiF2dRvUS4Rh6aD7whaCmLKhbgFnttuCNxHCg6S2AJ5EuI1WSLIWfHxJW_WBhwhPZbw-9JhQaRHxPssD7ScCX8vvdqjzy5NXn3GJnae_ql9CVySwIuUECecboRcvG6A_9VhupDou_WQ1yIIFtpersk4heEo0CwtJLs6iuLjkhNKClLcIHR6-g7ap0TTu5U3Ix9SSFvZi9WBUR0S7uhz_8uV6vTSmO7pl4emJ_-k1QH1hHx_L0aIoImoSQU-kBfz_bes0omy98mKfb6ma1Iro7CnicyRV-ySdLZur1cp1NP9NRhX-e5tg 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Feb 2017 23:18:23 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="35,34" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.Elv-Axy3_XrAHogGo4ExlN6mGRbYXBKLWgNr8t9IXXvg80HwTolCdnkYO38cRmZ6Rxf4vty5A71FtlHINichesLvpEen7mFJF4XeDwkAKJLQAdzpoKk4KT64q3ug", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Feb 2017 23:18:23 GMT 59 | recorded_with: VCR 3.0.3 60 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/firebase_all_valid.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDg4MjM3OTUwLCJleHAiOjE0ODgyNDE1NTAsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.SV7nUBW09zBOFlhhpthPoTJ_GSBMTUFOb8ZL36Sy-sdmrC5TT90etFMYujSlZlYWUBwx8hpiZ8KHTpvGluEep300CASn2Z4vdvSEMkoVqUsrc0_X9bySsuVk3o4l05vO66PfDNpZoyyD-SMXWs9cdUfv4Y7pG8RE5GEMcQGWO4xmHm-UMJUbGlExaWfK6un2GmaFTqyfdgocELB3d9TnOkD-VCqbbSWGkIg7fw7dNf2QySQ2VVRw1OSiEvYGaaZE_VEZQmTu7fvcBnTDT4lXDyHxHYL5dHsdKmDgg5XlBYf0csdVYroxiqpdxZwOXAEXLwJ1yc_l1KKE9GyP7uqAgQ 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Mon, 27 Feb 2017 23:25:50 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="35,34" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.Elv_A0xME_TyZ78Dl9H-WeIDQcX_0SQS__gqnFmFzXBTLcs_AdiKB5kfO3BZ1JokbBUkPaO4wzExLKDg8OZ5i7mUo7vLvwgJo0K3WkSJZ9jP6TJamkKzx0YNlZCF", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Mon, 27 Feb 2017 23:25:50 GMT 59 | - request: 60 | method: get 61 | uri: https://addrssr-8612c.firebaseio.com/todos.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.Elv_A0xME_TyZ78Dl9H-WeIDQcX_0SQS__gqnFmFzXBTLcs_AdiKB5kfO3BZ1JokbBUkPaO4wzExLKDg8OZ5i7mUo7vLvwgJo0K3WkSJZ9jP6TJamkKzx0YNlZCF 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Mon, 27 Feb 2017 23:25:52 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '1028' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"-Kdul0qh0g0uvtRExY9w":{"name":"test2","priority":3},"-Kdul7K23HTJrKT06Mr-":{"name":"test1","priority":1},"-Kduol2Ssg-Cmr1ogWcE":{"name":"new_name","priority":23},"-Kdvk3lX069mMEGCh1cM":{"name":"aaa","priority":22},"-KdvkPFAERQxnJqMvlZG":{"name":"vole","priority":22},"-KdvkcjRMVEazUoLtQkz":{"name":"y"},"-KdvlkhuHjqi2kn4y8cn":{"name":"o"},"-Kdvm1p-1ErkmjTM4Dm_":{"name":"o"},"-KdvmXn8Lo4Rt9gfxRIm":{"name":"o"},"-KdvmpYStLPnTAEoF9AS":{"name":"o"},"-KdvmvPXjK0X-Dtdy_Xl":{"name":"o"},"-KdvnRMsvmKm2GAaRN8y":{"name":"o"},"-KdvnuJEytXQJiQVn21I":{"name":"o"},"-KdvpnTm9vBWq1a39K6m":{"name":"asdfs"},"-Kdvpz_Zdmc4fVn4oU4K":{"name":"asdfs3"},"-KdvqJRfPx2D2ZamAUUA":{"name":"asdfs3312"},"-KdvqbFdVSX71laE1TkJ":{"name":"asdfs3312"},"-KdvrASomWd56UbVFHIA":{"name":"asdfs3312123"},"-KdvrQ3qY1Dhw9UqzlY1":{"name":"asdfs33121242313"},"-KdvrZ1HPFeY3VxProrz":{"name":"here 96 | we go"},"-Ke0jTuIRLigXsIi0s13":{"name":"fake","priority":23},"-Ke0k6RicOGtIj4GHlOG":{"name":"fake","priority":23},"-Ke0l9dulaQnd9hLOfEq":{"name":"fake","priority":23}}' 97 | http_version: 98 | recorded_at: Mon, 27 Feb 2017 23:25:52 GMT 99 | recorded_with: VCR 3.0.3 100 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/firebase_delete_valid.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDg4MjM4NzE5LCJleHAiOjE0ODgyNDIzMTksInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.DrADaIngBwLzgZ00O6PbJQI9tqxtJs3tghP0jZxAXfkpbACUbVbs0J2c8E34cNZkGJvO9O2uAFmCZnuWB00OioJuKb5nN7YG5RXFfu6FYXxbMYUirjodLjjiyIcCvL7jrCqjNoqEQtG0iQBMulIZHpuSYVgjtrkOnAkrjND9o1N1sSr5A8XJkDF3CFgibsieZsCLOhoGEM1uC7BBu0GPQRcMwh-GOLtlYEkeyt1rOdPijnouWRZTiDxfGHDfLn4Ib1-KB4DYdZTtbujOmf0ozeD3JbhUzt3JUihx9loUSv9TvWorVaDhmE8bm0bqu2JJziaITXaNh9LEyF-ScuqSkA 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Mon, 27 Feb 2017 23:38:39 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="35,34" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.Elv_AwmS63oxkWD1tzzViifelQT-zuRhYjQgHUSPeWL1jOsQdyBtRVIj2mM3WAojl4_3tb8A0mY3LXTSTvSbq2daA-Xf1jZidccrCKNk9I1R8l2t3KiEovM-_Tgd", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Mon, 27 Feb 2017 23:38:39 GMT 59 | - request: 60 | method: delete 61 | uri: https://addrssr-8612c.firebaseio.com/todos/-Kdvk3lX069mMEGCh1cM.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.Elv_AwmS63oxkWD1tzzViifelQT-zuRhYjQgHUSPeWL1jOsQdyBtRVIj2mM3WAojl4_3tb8A0mY3LXTSTvSbq2daA-Xf1jZidccrCKNk9I1R8l2t3KiEovM-_Tgd 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Mon, 27 Feb 2017 23:38:41 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '4' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: 'null' 96 | http_version: 97 | recorded_at: Mon, 27 Feb 2017 23:38:41 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/firebase_get_invalid.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDg4MjM4MDE3LCJleHAiOjE0ODgyNDE2MTcsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.sIgCyid7v6vtB4jOMPSS71UWrc8FBuVLHBgDOlUr7ofHKty9Q0PfWWKlenTOscgdKTdUra6ixRJl0lBjIYRaEiaK305w1m_iHlV9OzVHNAg_1t9EkVzpKXVswXwZwnTvAKzOoPlMCbCHYgB0_bfxcpmn-LDyY4HdxHaSQrdjSH7XFBhrVwvlg7oH-QSfO0hDRsG1nhcVoUhxKV8GkHaDGAu7wVk7_NSNDxrRjjS9mefUidilxk5q0873qnjOGOfUuLuWJIOFBOjtbf25e5LL-9uyjgbcLce3ioR_MCftQncHAOI9dXGgn1Yy4DZM8-XmmSWOYHuQYou4fgdieYtGDQ 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Mon, 27 Feb 2017 23:26:57 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="35,34" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.Elv_Aw4mLr7MTW_yXCLwp3CEeQSBmNNwXWGgw8b7hD7UcYcirYIXNCaXKIpx6gQzykddE8wvzl7oJhNXwTtfqenyexONSwHYtlltxOtRGbJy1NX1WAuZDCcrjhpl", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Mon, 27 Feb 2017 23:26:57 GMT 59 | - request: 60 | method: get 61 | uri: https://addrssr-8612c.firebaseio.com/todos/invalid.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.Elv_Aw4mLr7MTW_yXCLwp3CEeQSBmNNwXWGgw8b7hD7UcYcirYIXNCaXKIpx6gQzykddE8wvzl7oJhNXwTtfqenyexONSwHYtlltxOtRGbJy1NX1WAuZDCcrjhpl 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Mon, 27 Feb 2017 23:26:58 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '4' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: 'null' 96 | http_version: 97 | recorded_at: Mon, 27 Feb 2017 23:26:58 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/firebase_get_valid.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDg4MjM4MDE1LCJleHAiOjE0ODgyNDE2MTUsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.DvNNMtHym0Z346MrdXOVBKU-55zn3UosjJ-Tui1RxRXiJfC5oEq9dXpWnfhxT6Mhcrl-pPv6K9AZ-W4nx6LuylDdP1bF4SuhOXqqtd7BhX5MT21RVHRopudZsdupKfNh927anhTdDAth1z3hwgiyAgGGBDtQR1RFW1m5puq-kEFbcgKsF9eyYFgD3IY8HzlRGJn6A5vhtcyo_x2bUHVPahUf6yUNttrvpGhu1AxM9y5IPmq4SRwHLWJJNb4Tz6nak7X3l5c4t7Lcnv9Jhc_mlES20oAg47S70ufJv_mAvi1THHwzG7oH0oiFZQnwBD5NnDbzJMaYBmIWoNJZ8CBGXA 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Mon, 27 Feb 2017 23:26:55 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="35,34" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.Elv_AxOQufTSWE3oEwpZ0j6EXp0X0nrdUZiNa60I2wQ3Wk4f9pXplIwx4d0MnDs_8T4xb90qWGrpjxS46NEudoY8Rb2I7ipaHHeuP-8fLL9-zS0vPv2MOexMrb26", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Mon, 27 Feb 2017 23:26:55 GMT 59 | - request: 60 | method: get 61 | uri: https://addrssr-8612c.firebaseio.com/todos/-Kdul0qh0g0uvtRExY9w.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.Elv_AxOQufTSWE3oEwpZ0j6EXp0X0nrdUZiNa60I2wQ3Wk4f9pXplIwx4d0MnDs_8T4xb90qWGrpjxS46NEudoY8Rb2I7ipaHHeuP-8fLL9-zS0vPv2MOexMrb26 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Mon, 27 Feb 2017 23:26:56 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '29' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"name":"test2","priority":3}' 96 | http_version: 97 | recorded_at: Mon, 27 Feb 2017 23:26:57 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/firebase_init.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDg4MjMzNzY3LCJleHAiOjE0ODgyMzczNjcsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.QuYzYRG0Jbmg28X6P4BJkNkdvnrkccIq9bCwFxN6f2K7UI52rrXE6Z3u8SfbB3u3dfrUCY-EjOOEqoSyqk-he-PgmwsGfgPRLyWP6qS0qGw9nikegKuoPO9KHVZ0WZ38OF_zmmTtdZ1IqxnGHyp4aj2WIrfXsi20fmVwFKPnpYT2Fmlqu150RWpkGHxoZ_kE_JTDRtpvN6lEs412JjCio2bBmiHVq6vyB6f9fQ7jdpj5rnBBA6Blb5wx9JtK7B1WxkoadXKMgreKV4TQD5AFsBcv0t9NUsdnR9Oi89cYzGlguoCJBQbzzfAbAeZ82U4fh3sGQyYRxdJi9_v0Mepbbg 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Mon, 27 Feb 2017 22:16:07 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="35,34" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.Elv_A5xYP9MlcQaCLhHIvb10ZD2jGMZyHxg2F_Rf_E3IW-5MFQhqdyoYOD0J2zmiZLHQzIbYFrunuiGf638mKvED0lY-5kMmn2CIrpgSPdcWA0j3LYtD7P5kBGxg", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Mon, 27 Feb 2017 22:16:07 GMT 59 | recorded_with: VCR 3.0.3 60 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/firebase_patch_invalid_attributes.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDg4MjM4MjE1LCJleHAiOjE0ODgyNDE4MTUsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.r8wTYIoaiq9TmBwVNJXoxk_Rx8L66nAQ8PQkx1Aoc1xXKYtCKSGl0DkDQb9qBTUET2auW3HFE7uHehROpbEyiwGlFktnNFRos9fu4DLjekvSoqRn5sX8jYA1i2z-or_8LwQEQiVuLRpylh8scX7DWGQW2WD7SBjTF9dUhfJD9s-1OZKLDWGMUw9yTEWelObf3haNGV8D1-8ykGa95wXy6RV4OJrGl87_64rVGEB7NP3_x9G__Z9XuZ0E-DhOcPt14pPkLvbbb6_EPv4d3KJdujrq3-0wzJ706aYDqrNjkDNFr3u8p9RLgk-Hg8PD8tdvEIFbxYy8bp_3evs51wm8KA 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Mon, 27 Feb 2017 23:30:15 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="35,34" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.Elv_AyENHjt1t3UODbUtWpQpq0ewK7Q7tYsqiHnFwHd_9GZAXOFA-xCP0bCfsFg98tm7MWoI287s5U7D0oXS1-21-a_nCVj3byLvbb6AxFk3yKjtmjBVhLUCKjfu", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Mon, 27 Feb 2017 23:30:15 GMT 59 | - request: 60 | method: patch 61 | uri: https://addrssr-8612c.firebaseio.com/todos/-Kduol2Ssg-Cmr1ogWcE.json 62 | body: 63 | encoding: UTF-8 64 | string: '{"name":null,"priority":null}' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.Elv_AyENHjt1t3UODbUtWpQpq0ewK7Q7tYsqiHnFwHd_9GZAXOFA-xCP0bCfsFg98tm7MWoI287s5U7D0oXS1-21-a_nCVj3byLvbb6AxFk3yKjtmjBVhLUCKjfu 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Mon, 27 Feb 2017 23:30:16 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '29' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"name":null,"priority":null}' 96 | http_version: 97 | recorded_at: Mon, 27 Feb 2017 23:30:16 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/firebase_patch_invalid_id.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDg4MjM4NDY5LCJleHAiOjE0ODgyNDIwNjksInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.Yc6aYxPBP3kJei97ytXVOHJ7F7C5mm8KtktDSZHl_MADbYkeftpWUNwCm2REnxAljn0BSget1o65qqPce-gfiyNcwYCJcXxGpe2nuGHuO7E5r54D6sVDITFLbEfPeLEOEaLjsEyq8jqR_eyWPnFZUhL6Of6Qc6xm-pMMD9M4i0KSnO7dHtH0qnAgD8clSAWCYuN5t47M6QIkdgPjX-oPW4i_pE5FwBHLxHRVwk1rarBnn6L9HQlfgVZnF0I2JvQxmOUZwWzU8gcKrvbNbyBQKe1ieU0AN-4g4YaRlVsSTkFfYnNByreOPzpJVWQ-yHKp9HAiyluSRYp4etZQhUVgTQ 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Mon, 27 Feb 2017 23:34:29 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="35,34" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.Elv_A0mtAUhSmLuyvAfdVFXmgN1HNtkuMfxjlSYazEy1Rl9C4Ta9ko44xeH31SSVsZsQFPnv-jj5imAAl2Nev2dRn5CQgDZrdD5mYo4SVZVBTm68RjelECEsHPwu", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Mon, 27 Feb 2017 23:34:29 GMT 59 | - request: 60 | method: patch 61 | uri: https://addrssr-8612c.firebaseio.com/todos/-Kduol2Ssg-Cmr1ogWcE.json 62 | body: 63 | encoding: UTF-8 64 | string: '{"name":null,"priority":null}' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.Elv_A0mtAUhSmLuyvAfdVFXmgN1HNtkuMfxjlSYazEy1Rl9C4Ta9ko44xeH31SSVsZsQFPnv-jj5imAAl2Nev2dRn5CQgDZrdD5mYo4SVZVBTm68RjelECEsHPwu 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Mon, 27 Feb 2017 23:34:30 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '29' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"name":null,"priority":null}' 96 | http_version: 97 | recorded_at: Mon, 27 Feb 2017 23:34:31 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/firebase_patch_valid.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDg4MjM4MDY3LCJleHAiOjE0ODgyNDE2NjcsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.vgqZcddz6GmyVPsrop-pQYazAv8TOZOJy11uSV-pttjJyrLd6mA0aUFZGfcVFHniydbPBiQm4O1OSQbbFiaXqIfESklfq92vdKsFYc2XF34bgwXJ0DLz0ti6j_ZbJczJOwqElm85yDxPTwwsXn48dIc-HKlk6q1WZg0XNy8Ch-bdleEetyijIXw50wxmMMWjGCFVRsjOS29CnFqeFWrXbTKt2sHQIJIpJP5x_LF1PYnNLraKha8eDGOLNrP_bfn6q-0n8VusMBaAqy_ovptn6HlDNoSb_kez5s2noOSPYu15gg73x-XJxqVufb_wqV98y2GmtTTEfvpZnaZRJfxa_A 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Mon, 27 Feb 2017 23:27:47 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="35,34" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.Elv_A5JjdU2u1GxvwCAELxLIIVSDiuTyhzyykNNzLrY1SIXMZIM60Vxdewkf7Ktp_IUZMzQprpaGhLEGugOSYX-v6y270Am2dvKTwFFFoaBB28CRlM1jZPkFXUwK", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Mon, 27 Feb 2017 23:27:47 GMT 59 | - request: 60 | method: patch 61 | uri: https://addrssr-8612c.firebaseio.com/todos/-Kdul7K23HTJrKT06Mr-.json 62 | body: 63 | encoding: UTF-8 64 | string: '{"name":"fake","priority":23}' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.Elv_A5JjdU2u1GxvwCAELxLIIVSDiuTyhzyykNNzLrY1SIXMZIM60Vxdewkf7Ktp_IUZMzQprpaGhLEGugOSYX-v6y270Am2dvKTwFFFoaBB28CRlM1jZPkFXUwK 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Mon, 27 Feb 2017 23:27:49 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '29' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"name":"fake","priority":23}' 96 | http_version: 97 | recorded_at: Mon, 27 Feb 2017 23:27:49 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/firebase_post_valid_attributes.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDg4MjM4MDY2LCJleHAiOjE0ODgyNDE2NjYsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.r4vBJELyLmaAHQl-Ss-9bnfX7pdqhYaW9vjYX67yEo-17flKis1TVKZt9IJEd6V5JekZzthcqXIV7xaXbfh1-CP2sLz5T-FyXMWTNmlkvsgWpmp4ddDOpa8m7SmNlD_nq3zBL_tKslFGl9mNMohcsIJYwQw8pop1ftrTyXI56G0fGsQywkQFjsYnNgJmaSUkfGsrqRdARGcIGjhOTvomqSBQSp_sP_AKAZC1NHGebofsHo5CzKDSW987kr83LnIi2lRuSaIoX9VekCC3GtqyDGhYA1UzsIJkfPnSViaycf0Hu1YzYudraY5hEzjtaAhzmXxDLEL1O_PRZg3um1d1CQ 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Mon, 27 Feb 2017 23:27:46 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="35,34" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.Elv_A4s44FLP05w62c6kMeVnz_Xv6syGdGJN6UaCHxRpKpMwp0vB98M0Am8B0SsVTEnHIYmQOerF7RgXRijEs_ZuH_HR9bPDrMtcGpc5m5Bw7hJ0FhZf5kECeTSa", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Mon, 27 Feb 2017 23:27:46 GMT 59 | - request: 60 | method: post 61 | uri: https://addrssr-8612c.firebaseio.com/todos.json 62 | body: 63 | encoding: UTF-8 64 | string: '{"name":"fake","priority":23}' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.Elv_A4s44FLP05w62c6kMeVnz_Xv6syGdGJN6UaCHxRpKpMwp0vB98M0Am8B0SsVTEnHIYmQOerF7RgXRijEs_ZuH_HR9bPDrMtcGpc5m5Bw7hJ0FhZf5kECeTSa 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Mon, 27 Feb 2017 23:27:47 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '31' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"name":"-Ke0tftEsxiXZ9iQvZEt"}' 96 | http_version: 97 | recorded_at: Mon, 27 Feb 2017 23:27:47 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/invalid_model_all.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYxMzI1LCJleHAiOjE0OTA1NjQ5MjUsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.ESGPP4RRW86uOo7RPdFivxWsBYKNDG_U_SvAnDqD-ZYSKwxXbOoPoeU27ODSiX6L8jpGhyNivTENK5Dq-orgNYhQ44wyGKfX1M3m-sVKAM0Arn7oXhDN6VTJwnfBht3R_vqvfD-a77f4oZNUpw2KLb3BShYJvyCBukbkoc7-t_spw7Def2DC3Vf-qQ4ZKLLOakdQkl5vKzKYWXhUTRcEC4jIta9kYvV_p235oz26FLenzOpshr4XFWv4g8i3Q-LkMRVuG_1k7Nl3nbvFTDA8w5KEelGDsw9HkJVP8_f8-wXTUfHamJgoBL7JzTf2_3gXRegoW80CSBAXI1hyM15rgg 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 20:48:47 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBLZTDfSa6Dy4O_f-7tcJ8hS-KkxeQVO_cqcPnCvFx6oAmefDeeezG2Zbd6ci8Ha15GxW5xAIodFCWF0biQr1UjRhTYPMVaozI9ni9cOuZKQRx0QaGH7IzH0W", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 20:48:45 GMT 59 | - request: 60 | method: get 61 | uri: https://addrssr-8612c.firebaseio.com/empty_root.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBLZTDfSa6Dy4O_f-7tcJ8hS-KkxeQVO_cqcPnCvFx6oAmefDeeezG2Zbd6ci8Ha15GxW5xAIodFCWF0biQr1UjRhTYPMVaozI9ni9cOuZKQRx0QaGH7IzH0W 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 20:48:48 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '4' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: 'null' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 20:48:47 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/invalid_model_find.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYxMzI3LCJleHAiOjE0OTA1NjQ5MjcsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.zLpUGMscQvdMzNYiQ4JGucjbyusx6ssxFfQhjaUb7KYEpM4i1xKLTUtdOeTPuz9LXUueN6iPjOrw1PULVZ9g1CLerzP_3s-gHUWVTii1hJgXLJ1drXw3wXAnDjhw6v3TMwYTBVZcro7DYPYPEugGlMZke6-T_QkgStk9655VLuVF8JBR8Xl4BnqcQCLXqeyZdhJRWMnYdR1fZsEPhKT-44Htjjco7WyuJS9-YoMd6ZLgomXiqLe4dmNTO37elwdcs6TJgblKjdIXyraguTDCSWxQTz6WTV4qrljzYThniITwTfvPTvcr93hcG2oza_kdD3UvEdL_w6m2cZhsUJL6lg 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 20:48:49 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBOKZVQKgmq1I3ZlT_-YP2HQSRe4G1dbVrc_cJxJ5iBMNeCExsDa58ca2t0CTmTZ3kQSVia9_P1GfmGXCHHYmoZ20o8rBWSxwSA65tsVWtoCB1m1BO-Vi3Y8t", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 20:48:47 GMT 59 | - request: 60 | method: get 61 | uri: https://addrssr-8612c.firebaseio.com/empty_root/id.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBOKZVQKgmq1I3ZlT_-YP2HQSRe4G1dbVrc_cJxJ5iBMNeCExsDa58ca2t0CTmTZ3kQSVia9_P1GfmGXCHHYmoZ20o8rBWSxwSA65tsVWtoCB1m1BO-Vi3Y8t 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 20:48:49 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '4' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: 'null' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 20:48:48 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/invalid_model_where_valid.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYxMzI4LCJleHAiOjE0OTA1NjQ5MjgsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.wfaNWoc3qQd4CAmcKQy7LFYzxOiEwvnMnlrkzBbfj08SuDi1-Jm9BYdo6TIIAxwL8-OjXHs7TpxhKPOlsImvT3Y7121CmIPkudnrs7qqrtCOyUEarFZcBHqZuJtK2ivALyqNQbEmhM_7sEA7sA4_JN6YcQNm6Zk0hT16OWxlI7I8O47GkSvbFY2eBDoVJRasYbUZiw8Zy7ENm1Wd1cM3n4j7G3p3GkMsji_-2fE5jbJjCccdDqwuUIaMGfloYz2erGicufH38hqra3vZ0Jrgqw3K_-CjR7AIxhi933EICr7I2Tl-bs9Wh-76126UEzRULdXNyL3xlmrPWgs6jwZPXA 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 20:48:50 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBNM1B7mH_M4OBAf7wWzRMNWiErp9cH6r5Ff402cAIbD26OnLuTnhCH4zW99HkNc9NaiXyBhjnxzgBSUpZylqostDgXABcbRcK0Y2PB2a-mc6s4Cq6oX7Ihf7", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 20:48:48 GMT 59 | - request: 60 | method: get 61 | uri: https://addrssr-8612c.firebaseio.com/empty_root.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBNM1B7mH_M4OBAf7wWzRMNWiErp9cH6r5Ff402cAIbD26OnLuTnhCH4zW99HkNc9NaiXyBhjnxzgBSUpZylqostDgXABcbRcK0Y2PB2a-mc6s4Cq6oX7Ihf7 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 20:48:51 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '4' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: 'null' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 20:48:50 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/valid_model_all.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYyNjU3LCJleHAiOjE0OTA1NjYyNTcsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.mEPPFkEcdDwB7V5HAqALp98cIWGyzFm5jOuadMO5E0iCkWOEIRgaJHt89ytybf3jwnqaaEhhmKol1_FeSt3y3D3eBhtFM5Kxk1eKp-Rrt27q-zjMO7tDObil9CQ5oKPDSA2pQeU9cY7b-Ho8fQeWHAx3RHudyhN7nZfT0bdS2qWsBRjtSEaEG65xDUXFDEU-UJfBJAVWWAJ1glDvJhYugZQD3KYBAVMSRn_RGu55bjnXFnfjlbeWdO0YfVT6s6bPFuPcdIk9dQvB7AhwdFtcG9-BMmlhG3ylB5gfdT2Q4KH1s8t2OftP686zY136vLvCaZgCm96sDTWgDPkIvL59og 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 21:10:59 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBGYtyIF1UA5VFb6ja3CygSWDum8seI1DLCYYEGu1KffHVM_4tRCbcgRPJtBRpR-j8lcU9B6Gzk3dytuAt0LVXDMj8EDAe609IBawFJkdlTAIO8xT-MmkOOp2", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 21:10:58 GMT 59 | - request: 60 | method: get 61 | uri: https://addrssr-8612c.firebaseio.com/root.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBGYtyIF1UA5VFb6ja3CygSWDum8seI1DLCYYEGu1KffHVM_4tRCbcgRPJtBRpR-j8lcU9B6Gzk3dytuAt0LVXDMj8EDAe609IBawFJkdlTAIO8xT-MmkOOp2 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 21:11:00 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '307' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"-KgBSHdh_ildE5y8eBSc":{"age":0,"created_at":"2017-03-26T22:10:53+01:00","name":"name_0","skill":0.0},"-KgBSHz-k-3768XjH7o0":{"age":1,"created_at":"2017-03-26T22:10:55+01:00","name":"name_1","skill":1.0},"-KgBSIH-vwJV7BE3yEko":{"age":2,"created_at":"2017-03-26T22:10:56+01:00","name":"name_2","skill":2.0}}' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 21:10:58 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/valid_model_bootstrap_0.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYyNjUzLCJleHAiOjE0OTA1NjYyNTMsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.FS0zythogOprmP-bWIYZJpMuCo78ZEwlqsFvYlrxcPKgzF0-7kDFN-rkTzN8G8i0cQdhruvhc8vRdiuo63T0GVoQUoRSJFCzyuSZpfGqq9is3MARYUeoS4hgL4cX61EygECyGqkxdSk1eyv2aDoJEIc_VXFVzjD_K0KRsSGRaL7589IVQWUlISj-mcaabtZk0x7wIsxS82qugBuS1AaHJMv9u53YObm_1YS29bzUp-LNuijPXWcCxaA7UckKUIJvev7BtSpAdQogaJpRYptxiibrjY3DsLcuXjle2KY3UJKoVHUFbhKi4t2brk4VgkIKLkJ9SPLWfvsl28HGgx99wA 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 21:10:55 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBKkf5-G8CrMQAECe94ICyA42apnnduGkqtjof1Rgp5WgYE0TUCR7hLNa7jl3HxTWC7gX4FcvD7fx4BFf3PpojFPiHCIg2-aTuCKy9M2O36epM24UB5rpsjj6", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 21:10:54 GMT 59 | - request: 60 | method: post 61 | uri: https://addrssr-8612c.firebaseio.com/root.json 62 | body: 63 | encoding: UTF-8 64 | string: '{"name":"name_0","age":0,"skill":0.0,"created_at":"2017-03-26T22:10:53+01:00","updated_at":null}' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBKkf5-G8CrMQAECe94ICyA42apnnduGkqtjof1Rgp5WgYE0TUCR7hLNa7jl3HxTWC7gX4FcvD7fx4BFf3PpojFPiHCIg2-aTuCKy9M2O36epM24UB5rpsjj6 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 21:10:56 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '31' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"name":"-KgBSHdh_ildE5y8eBSc"}' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 21:10:55 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/valid_model_bootstrap_1.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYyNjU1LCJleHAiOjE0OTA1NjYyNTUsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.mbIKYTN4I7Olc3QmRlhfianlhn68S3cJ_be2ZeV93U4DBj7ZXkS9lnOeFfWGVP96NGQ0KvcXRgYjJgHatZROvtOKQLIgFXInqg27jaMfQAUrMIvv2SdajgjyPYtXUdnczVyMttfLyp_uSQmyFdsaLWBppEJqdHOW5Crb77rhGn3peJaIa_R90JwodI5ctcXVQVNHBIRY5ZZB5uRfAm9mtAi_Oo9rryOq434P3qZX8DGuUiV81TZkXN5h7TGHi7hweUL2cZcuaEkNad4mm76NMnUdG-VzWqSHzdQfY2s_9bP_M7Y7y8WPSO9QevDofj49cM_N1m1Y_KAGIn7-zlwWEw 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 21:10:57 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBASoJJA5Xp2o5UYkmSP7MvgKh1Bj3XbQc__p2f6Jt9aokteat_3LKa8-ASeBdVbeVKgGwx70H-hv7C9fD79W1ISwTbjSBUg3FBcrAwNnr4_VIFh4uNA2HpGq", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 21:10:55 GMT 59 | - request: 60 | method: post 61 | uri: https://addrssr-8612c.firebaseio.com/root.json 62 | body: 63 | encoding: UTF-8 64 | string: '{"name":"name_1","age":1,"skill":1.0,"created_at":"2017-03-26T22:10:55+01:00","updated_at":null}' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBASoJJA5Xp2o5UYkmSP7MvgKh1Bj3XbQc__p2f6Jt9aokteat_3LKa8-ASeBdVbeVKgGwx70H-hv7C9fD79W1ISwTbjSBUg3FBcrAwNnr4_VIFh4uNA2HpGq 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 21:10:58 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '31' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"name":"-KgBSHz-k-3768XjH7o0"}' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 21:10:56 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/valid_model_bootstrap_2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYyNjU2LCJleHAiOjE0OTA1NjYyNTYsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.TTKT7udll7Wz_A_YjXnZMEzpInayqEVQvXVSfZHxUKMNBSrxPj14FVlUSMfzYTs_F7v-mSMm0GM4CZ42XrZ0kZsfQXy80V6MIWknAtA23Mseiev6XzPS9bYQWIKvx6oNdpfnsKPb9RRgnac-kJvXJ4U8FwL9wr0zHUCxth9MQlaYOZZt9nE-fy1V6m6pW3Hyk3zrR7qmatF4w0P36TatAbAb_THgWg43NCRUxAVLxDZ4z2GGtUDIEJo81_PMmrAKEiZ5zfksWQ21l4xIcWbpCEK5fRI11-suW2qjW6yV3Ud1IkMNozcGvX86V-M3eBu2DIPsuxkGFYUi0uUUiYvsuw 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 21:10:58 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBAw22mUxo5viIPMSMP9Wl_A-UNRzaINdRYpDUyfAt-UgE6kVg3sBeG9Q-nnt7kZoUqmraXXWCCxZ5Risoxt9NdGehQua74NQR5aHgDOhHGmc8hYgRCyarc2B", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 21:10:57 GMT 59 | - request: 60 | method: post 61 | uri: https://addrssr-8612c.firebaseio.com/root.json 62 | body: 63 | encoding: UTF-8 64 | string: '{"name":"name_2","age":2,"skill":2.0,"created_at":"2017-03-26T22:10:56+01:00","updated_at":null}' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBAw22mUxo5viIPMSMP9Wl_A-UNRzaINdRYpDUyfAt-UgE6kVg3sBeG9Q-nnt7kZoUqmraXXWCCxZ5Risoxt9NdGehQua74NQR5aHgDOhHGmc8hYgRCyarc2B 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 21:10:59 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '31' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"name":"-KgBSIH-vwJV7BE3yEko"}' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 21:10:57 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/valid_model_cleanup_0.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYyNjY1LCJleHAiOjE0OTA1NjYyNjUsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.BE7wNYa0Dm1VgGM1zstcI8pNd2u2UonRvKLcL5T5r8d9LDZumXPjlgifD066S8MZifgFksEOIU-bvlT5AxV0WDo33PGz-ctFom3OIZZzqplJLhnqQd8b7Unr4k4pS2-G1RTDKrGBtF2tsSbzKgitp27mRxc1FbpOksW3NkWQkV28Py7IbIMR2uQnla_Zk1gBGa-pTXKNGMr2EjYbZEtJUEcOms3pAcWjj1ieJODmpKiwXMLvn81ibDNxgfyej5ELEewboVgowUuppWAJ8yfFthXvrojjH89LbdYfF9SFcbJEgjKINOqlBPHZMVeZvvCfHFdHqLU38dWOouPiaolrXw 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 21:11:07 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBPAQxxhNla7NJyQurvoC6dCbIa84dYH42CjLLi4SQ7Z0EbPVTsh148hq7P-qaBLyBdKKea-0Hthi33FyPN3o1LxZLZnloG-mnfljRR8P61WXB-r7Fqg-ah1d", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 21:11:05 GMT 59 | - request: 60 | method: delete 61 | uri: https://addrssr-8612c.firebaseio.com/root/-KgBSHdh_ildE5y8eBSc.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBPAQxxhNla7NJyQurvoC6dCbIa84dYH42CjLLi4SQ7Z0EbPVTsh148hq7P-qaBLyBdKKea-0Hthi33FyPN3o1LxZLZnloG-mnfljRR8P61WXB-r7Fqg-ah1d 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 21:11:08 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '4' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: 'null' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 21:11:06 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/valid_model_cleanup_1.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYyNjY2LCJleHAiOjE0OTA1NjYyNjYsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.FHiW2Ku7belDP39ZD1y91hNjCS11MCX7WKt6xoeDRUZErW5xfSqw0tyynkDMkFp6bgTVhgx3hrXjsYbmhD4zftdqaoPf9mjHY5vs5UUtI0yEgfY2mlSh9tSl_Y_faofIvYX-tp1qF5jX-AOxj14omMgiP49KN8fXvoKgY0MczKfOFvx3dRwZg0D7bY545-f8giX3lYk4aSPSwSklfT8TIjM6r7Fs-d8GFF-7v69dpelDPJ6QRfh8UzXG5JI00VeqW8aCqCVd-z3CeMFNIY4BM_eaiexND4GI6JJdeHqztGbp_qIgDWRh9ezAmEOJ8JgS3R-W0CDA-CmclCMzbGgcDQ 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 21:11:08 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBB3S-S2uVLAfWcztapCqn0St7-jSNbsGn5NsW8zIG8SMDn3eixOIw4x-spLaEswcntVgS7wqYFlyOczT6M3LCC3EAIndwEcREa8OE4RHORlLtIDWIYh-1feW", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 21:11:06 GMT 59 | - request: 60 | method: delete 61 | uri: https://addrssr-8612c.firebaseio.com/root/-KgBSHz-k-3768XjH7o0.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBB3S-S2uVLAfWcztapCqn0St7-jSNbsGn5NsW8zIG8SMDn3eixOIw4x-spLaEswcntVgS7wqYFlyOczT6M3LCC3EAIndwEcREa8OE4RHORlLtIDWIYh-1feW 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 21:11:09 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '4' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: 'null' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 21:11:08 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/valid_model_cleanup_2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYyNjY4LCJleHAiOjE0OTA1NjYyNjgsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.SJwsU3AopKg_c-VLFDzO7Zgq0wtRk8voGb59GAaX0p3M6IbIwNbDttyF5-tQawG6RjNJAT0VV7Cno1D5tppjExk-g4aNsCpsnESQJfGGKyV6CkUhJOCm4P10tZ2gsnOmXEdkn_vSoRUPOdVEXiNK1K-NAn6eSNtwD1m-c6Uf2YSClbeP5bpX3p3XTdaq1_-DA7krROYEPm4cQ8qHw97QTkXT5acXynAhw6j_c9i64OX42ZFULNCef8OWglCr0_qafKDLnK5bA_AMQa_2spgCVJU4C-RXsB1RcgToLVnVJQBs03bCB-Q0nay7Xz7AhP0Fxi-ZZ7og7rk-YXFeXAWeng 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 21:11:10 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBIyllc05LQ2M8K_m-v1gX1_rvQ3DndMMlTDRhGIzB21DaDBnyGdL6cvG7FSp1-jRhV83MZCBu3R_WkzMsE4z2jPUawzJU8ZCwg5XwCzb3yGOtn8Z6D1wN3xg", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 21:11:08 GMT 59 | - request: 60 | method: delete 61 | uri: https://addrssr-8612c.firebaseio.com/root/-KgBSIH-vwJV7BE3yEko.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBIyllc05LQ2M8K_m-v1gX1_rvQ3DndMMlTDRhGIzB21DaDBnyGdL6cvG7FSp1-jRhV83MZCBu3R_WkzMsE4z2jPUawzJU8ZCwg5XwCzb3yGOtn8Z6D1wN3xg 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 21:11:10 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '4' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: 'null' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 21:11:09 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/valid_model_find.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYyNjU4LCJleHAiOjE0OTA1NjYyNTgsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.gMRg8jWQAhXUYbRnNZABtcDBBw2LiOsSIrTPDQWky4td5UqpkMY_je0aD6ft5a46zo4PLqQC5zF67nm5zknCTzZPZpb7RUEcRMysD-peIki-MWASnfL1jpPZM53pR31IWbsSb6mMile-aWxmuDANCq8Af8pOn0526E0cHinLKiIhxr90c38dLhGMKvDm9j8rdry51NPSrpcWMaEqvG7NHQwVF_xopO1YtKgmU9F-DoYAfT2lztsbDxwDQvjb_kKvbEMFPcCfRUDVBLA8JFS_bUCTK8okltTuidyzTzreBrQnHI5h03h6NCFq3HeQ0XTSJ8hrhElubngSuO3EEfIRWg 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 21:11:01 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBHf2zccZkIb1L7meOkuvt3Vta5Ej7upAEqMwGfjTNiCMISadG2WiQJKzo0LtJaaOkXQ1tn0LIy95YdW6pqz3s44eXkMBrwumJL2aqXHB6A-CtDhCo7XT0vmb", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 21:10:59 GMT 59 | - request: 60 | method: get 61 | uri: https://addrssr-8612c.firebaseio.com/root/-KgBSHdh_ildE5y8eBSc.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBHf2zccZkIb1L7meOkuvt3Vta5Ej7upAEqMwGfjTNiCMISadG2WiQJKzo0LtJaaOkXQ1tn0LIy95YdW6pqz3s44eXkMBrwumJL2aqXHB6A-CtDhCo7XT0vmb 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 21:11:02 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '78' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"age":0,"created_at":"2017-03-26T22:10:53+01:00","name":"name_0","skill":0.0}' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 21:11:00 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/valid_model_where.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://accounts.google.com/o/oauth2/token 6 | body: 7 | encoding: US-ASCII 8 | string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay01c2w4eUBhZGRyc3NyLTg2MTJjLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNDkwNTYyNjYwLCJleHAiOjE0OTA1NjYyNjAsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC91c2VyaW5mby5lbWFpbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2ZpcmViYXNlLmRhdGFiYXNlIn0.Uwzq-b47nifG_2LPKWXzrkttR-yxh-lO32UBZYc1P82DjJgP9gztW7xR6zdWgtqHqbgDjyxAMAumv6a9e4FnMxxuaVIR0YybHMvMnWYABOoehXBPTy3ertY1VByBtJG-cV0L16T25DugN_kQ2YHDqjY9xgfj4xRT-60_SwWKV0pcX1WuNu73bFid1Rctme8X6ZRYfbiDoQ3zqTLNYRE44EJR7Kw-IIK8nBgOpQDrz4P7Y4VLyuD516VeLQDeaal8S4rkUfhen2lnITWSnGXWT6Zk-MroQqrcso_yewceMfNbcSKObHT15UC2y9UgIBEhrjbp7TgyG9gzeVgc6kn2SA 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | Cache-Control: 17 | - no-store 18 | Content-Type: 19 | - application/x-www-form-urlencoded 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Content-Type: 26 | - application/json; charset=utf-8 27 | X-Content-Type-Options: 28 | - nosniff 29 | Cache-Control: 30 | - no-cache, no-store, max-age=0, must-revalidate 31 | Pragma: 32 | - no-cache 33 | Expires: 34 | - Mon, 01 Jan 1990 00:00:00 GMT 35 | Date: 36 | - Sun, 26 Mar 2017 21:11:02 GMT 37 | Content-Disposition: 38 | - attachment; filename="json.txt"; filename*=UTF-8''json.txt 39 | Server: 40 | - ESF 41 | X-Xss-Protection: 42 | - 1; mode=block 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | Alt-Svc: 46 | - quic=":443"; ma=2592000; v="37,36,35" 47 | Transfer-Encoding: 48 | - chunked 49 | body: 50 | encoding: ASCII-8BIT 51 | string: |- 52 | { 53 | "access_token" : "ya29.ElsaBMAuJdLJeDyPDA9_9QFh4aixxYH6KTdS6c7HgVn8Sb9JLbdkV_Yf_cwljYRJDB5-deoI5ffekFIZfPdwtxiCJOmhsKdSTSnEUKnkcjRxfcYLtLPgHvaljSFw", 54 | "expires_in" : 3600, 55 | "token_type" : "Bearer" 56 | } 57 | http_version: 58 | recorded_at: Sun, 26 Mar 2017 21:11:00 GMT 59 | - request: 60 | method: get 61 | uri: https://addrssr-8612c.firebaseio.com/root.json 62 | body: 63 | encoding: US-ASCII 64 | string: '' 65 | headers: 66 | Authorization: 67 | - Bearer ya29.ElsaBMAuJdLJeDyPDA9_9QFh4aixxYH6KTdS6c7HgVn8Sb9JLbdkV_Yf_cwljYRJDB5-deoI5ffekFIZfPdwtxiCJOmhsKdSTSnEUKnkcjRxfcYLtLPgHvaljSFw 68 | Content-Type: 69 | - application/json 70 | User-Agent: 71 | - X-FIREBASE-CLIENT 72 | response: 73 | status: 74 | code: 200 75 | message: OK 76 | headers: 77 | Server: 78 | - nginx 79 | Date: 80 | - Sun, 26 Mar 2017 21:11:03 GMT 81 | Content-Type: 82 | - application/json; charset=utf-8 83 | Content-Length: 84 | - '307' 85 | Connection: 86 | - keep-alive 87 | Access-Control-Allow-Origin: 88 | - "*" 89 | Cache-Control: 90 | - no-cache 91 | Strict-Transport-Security: 92 | - max-age=31556926; includeSubDomains; preload 93 | body: 94 | encoding: UTF-8 95 | string: '{"-KgBSHdh_ildE5y8eBSc":{"age":0,"created_at":"2017-03-26T22:10:53+01:00","name":"name_0","skill":0.0},"-KgBSHz-k-3768XjH7o0":{"age":1,"created_at":"2017-03-26T22:10:55+01:00","name":"name_1","skill":1.0},"-KgBSIH-vwJV7BE3yEko":{"age":2,"created_at":"2017-03-26T22:10:56+01:00","name":"name_2","skill":2.0}}' 96 | http_version: 97 | recorded_at: Sun, 26 Mar 2017 21:11:02 GMT 98 | recorded_with: VCR 3.0.3 99 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | require 'firecord' 3 | require 'webmock/rspec' 4 | require 'vcr' 5 | 6 | RSpec.configure do |config| 7 | # Enable flags like --only-failures and --next-failure 8 | config.example_status_persistence_file_path = '.rspec_status' 9 | 10 | config.expect_with :rspec do |c| 11 | c.syntax = :expect 12 | end 13 | end 14 | 15 | VCR.configure do |config| 16 | config.cassette_library_dir = 'spec/fixtures/vcr_cassettes' 17 | config.hook_into :webmock 18 | config.allow_http_connections_when_no_cassette = true 19 | end 20 | --------------------------------------------------------------------------------