tush 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +86 -0
- data/LICENSE.txt +20 -0
- data/README.md +60 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/lib/tush.rb +12 -0
- data/lib/tush/exporter.rb +27 -0
- data/lib/tush/helpers/association_helpers.rb +92 -0
- data/lib/tush/importer.rb +91 -0
- data/lib/tush/model_store.rb +58 -0
- data/lib/tush/model_wrapper.rb +107 -0
- data/spec/association_helpers_spec.rb +81 -0
- data/spec/exporter_spec.rb +39 -0
- data/spec/helper.rb +40 -0
- data/spec/importer_spec.rb +177 -0
- data/spec/model_store_spec.rb +32 -0
- data/spec/model_wrapper_spec.rb +119 -0
- data/spec/support/exported_data.json +1 -0
- data/spec/support/schema.rb +88 -0
- data/tush.gemspec +102 -0
- metadata +299 -0
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            require 'tush/helpers/association_helpers'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Tush
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              # This holds the collection of models that will be exported.
         | 
| 6 | 
            +
              class ModelStore
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                attr_accessor :model_wrappers, :blacklisted_models, :copy_only_models
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def initialize(opts={})
         | 
| 11 | 
            +
                  self.blacklisted_models = opts[:blacklisted_models] || []
         | 
| 12 | 
            +
                  self.copy_only_models = opts[:copy_only_models] || []
         | 
| 13 | 
            +
                  self.model_wrappers = []
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def push_array(model_array)
         | 
| 17 | 
            +
                  model_array.each { |model_instance| self.push(model_instance) }
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def push(model_instance, parent_wrapper=nil)
         | 
| 21 | 
            +
                  return if self.object_in_stack?(model_instance)
         | 
| 22 | 
            +
                  return if self.blacklisted_models.include?(model_instance.class)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  model_wrapper = ModelWrapper.new(:model => model_instance)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  if parent_wrapper and parent_wrapper.model_trace.any?
         | 
| 27 | 
            +
                    model_wrapper.add_model_trace_list(parent_wrapper.model_trace)
         | 
| 28 | 
            +
                    model_wrapper.add_model_trace(parent_wrapper)
         | 
| 29 | 
            +
                  elsif parent_wrapper
         | 
| 30 | 
            +
                    model_wrapper.add_model_trace(parent_wrapper)
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  model_wrappers.push(model_wrapper)
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  return if self.copy_only_models.include?(model_instance.class)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  model_wrapper.association_objects.each do |object|
         | 
| 38 | 
            +
                    self.push(object, model_wrapper)
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                def object_in_stack?(model_instance)
         | 
| 43 | 
            +
                  self.model_wrappers.each do |model_wrapper|
         | 
| 44 | 
            +
                    next if model_instance.class != model_wrapper.model_class
         | 
| 45 | 
            +
                    next if model_instance.attributes != model_wrapper.model_attributes
         | 
| 46 | 
            +
                    return true
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  return false
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def export
         | 
| 53 | 
            +
                  { :model_wrappers => self.model_wrappers.map { |model_wrapper| model_wrapper.export } }
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            end
         | 
| @@ -0,0 +1,107 @@ | |
| 1 | 
            +
            require 'active_record'
         | 
| 2 | 
            +
            require 'active_support'
         | 
| 3 | 
            +
            require 'deep_clone'
         | 
| 4 | 
            +
            require 'sneaky-save'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Tush
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              # This is a class the wraps each model instance that we
         | 
| 9 | 
            +
              # plan on exporting.
         | 
| 10 | 
            +
              class ModelWrapper
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                attr_accessor(:model_attributes,
         | 
| 13 | 
            +
                              :new_model,
         | 
| 14 | 
            +
                              :new_model_attributes,
         | 
| 15 | 
            +
                              :model,
         | 
| 16 | 
            +
                              :model_class,
         | 
| 17 | 
            +
                              :model_trace,
         | 
| 18 | 
            +
                              :original_db_id)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def initialize(opts={})
         | 
| 21 | 
            +
                  model = opts[:model]
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  if model.is_a?(ActiveRecord::Base)
         | 
| 24 | 
            +
                    self.model = model
         | 
| 25 | 
            +
                    self.model_class = model.class
         | 
| 26 | 
            +
                    self.model_attributes = model.attributes || {}
         | 
| 27 | 
            +
                  else
         | 
| 28 | 
            +
                    self.model_class = opts[:model_class].constantize
         | 
| 29 | 
            +
                    self.model_attributes = opts[:model_attributes] || {}
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  self.model_trace = []
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def original_db_key
         | 
| 36 | 
            +
                  "id"
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def create_copy
         | 
| 40 | 
            +
                  # Define the custom_create method on a model to save
         | 
| 41 | 
            +
                  # new models in a custom manner.
         | 
| 42 | 
            +
                  if model_class.respond_to?(:custom_create)
         | 
| 43 | 
            +
                    self.new_model = self.model_class.custom_create(model_attributes)
         | 
| 44 | 
            +
                    self.new_model_attributes = self.new_model.attributes
         | 
| 45 | 
            +
                  else
         | 
| 46 | 
            +
                    create_without_validation_and_callbacks
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def create_without_validation_and_callbacks
         | 
| 51 | 
            +
                  attributes = model_attributes.clone
         | 
| 52 | 
            +
                  attributes.delete(original_db_key)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  copy = model_class.new(attributes)
         | 
| 55 | 
            +
                  copy.sneaky_save
         | 
| 56 | 
            +
                  copy.reload
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  self.new_model = copy
         | 
| 59 | 
            +
                  self.new_model_attributes = copy.attributes
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def original_db_id
         | 
| 63 | 
            +
                  model_attributes[self.original_db_key]
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def add_model_trace_list(list)
         | 
| 67 | 
            +
                  model_trace.concat(list)
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                def add_model_trace(model_wrapper)
         | 
| 71 | 
            +
                  model_trace << [model_wrapper.model_class.to_s,
         | 
| 72 | 
            +
                                  model_wrapper.original_db_id]
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                def association_objects
         | 
| 76 | 
            +
                  objects = []
         | 
| 77 | 
            +
                  SUPPORTED_ASSOCIATIONS.each do |association_type|
         | 
| 78 | 
            +
                    relation_infos =
         | 
| 79 | 
            +
                      AssociationHelpers.relation_infos(association_type,
         | 
| 80 | 
            +
                                                        model_class)
         | 
| 81 | 
            +
                    next if relation_infos.empty?
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    relation_infos.each do |info|
         | 
| 84 | 
            +
                      next unless model.respond_to?(info.name)
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                      object = model.send(info.name)
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                      if object.is_a?(Array)
         | 
| 89 | 
            +
                        objects.concat(object)
         | 
| 90 | 
            +
                      elsif object
         | 
| 91 | 
            +
                        objects << object
         | 
| 92 | 
            +
                      end
         | 
| 93 | 
            +
                    end
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                  objects
         | 
| 97 | 
            +
                end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                def export
         | 
| 100 | 
            +
                  { :model_class => model_class.to_s,
         | 
| 101 | 
            +
                  	:model_attributes => model_attributes,
         | 
| 102 | 
            +
                    :model_trace => model_trace }
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            end
         | 
| @@ -0,0 +1,81 @@ | |
| 1 | 
            +
            require 'active_record'
         | 
| 2 | 
            +
            require 'helper'
         | 
| 3 | 
            +
            require 'tush'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            describe Tush::AssociationHelpers do
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              before :all do
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                class Jacob < ActiveRecord::Base
         | 
| 10 | 
            +
                  belongs_to :jesse
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                class Jesse < ActiveRecord::Base
         | 
| 14 | 
            +
                  has_one :jim
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                class Jim < ActiveRecord::Base
         | 
| 18 | 
            +
                  belongs_to :jesse
         | 
| 19 | 
            +
                  has_many :leah
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                class Leah < ActiveRecord::Base
         | 
| 23 | 
            +
                  belongs_to :jim
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              describe ".relation_infos" do
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                it "returns an info for an association" do
         | 
| 31 | 
            +
                  infos = Tush::AssociationHelpers.relation_infos(:has_one, Jesse)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  infos.count.should == 1
         | 
| 34 | 
            +
                  infos.first.name.should == :jim
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                it "works with string classes" do
         | 
| 38 | 
            +
                  infos = Tush::AssociationHelpers.relation_infos(:belongs_to, "Jacob")
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  infos.count.should == 1
         | 
| 41 | 
            +
                  infos.first.name.should == :jesse
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              describe ".model_relation_info" do
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                it "returns a mapping of association to relation info" do
         | 
| 49 | 
            +
                  info = Tush::AssociationHelpers.model_relation_info(Jim)
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  info.keys.should == Tush::SUPPORTED_ASSOCIATIONS
         | 
| 52 | 
            +
                  info[:has_many].count.should == 1
         | 
| 53 | 
            +
                  info[:has_many].first.name.should == :leah
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              describe ".create_foreign_key_mapping" do
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                it "it finds the appropriate foreign keys for the passed in classes" do
         | 
| 61 | 
            +
                  mapping = Tush::AssociationHelpers.create_foreign_key_mapping([Jacob, Jesse, Jim, Leah])
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  mapping.should == { Jacob => [{ :foreign_key=>"jesse_id", :class=> Jesse }],
         | 
| 64 | 
            +
                                      Jesse => [],
         | 
| 65 | 
            +
                                      Jim => [{ :foreign_key=>"jesse_id", :class=> Jesse }],
         | 
| 66 | 
            +
                                      Leah => [{ :foreign_key=>"jim_id", :class=> Jim }] }
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                it "it returns newly discovered classes in the mapping if an input class has \
         | 
| 70 | 
            +
                    a has_many or a has_one" do
         | 
| 71 | 
            +
                  mapping = Tush::AssociationHelpers.create_foreign_key_mapping([Jacob, Jesse])
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  mapping.should == { Jacob => [{ :foreign_key=>"jesse_id", :class=> Jesse }],
         | 
| 74 | 
            +
                                      Jesse => [],
         | 
| 75 | 
            +
                                      Jim => [{ :foreign_key=>"jesse_id", :class=> Jesse }] }
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
             | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            end
         | 
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            require 'helper'
         | 
| 2 | 
            +
            require 'tempfile'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe Tush::Exporter do
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              before :all do
         | 
| 7 | 
            +
                class Jason < ActiveRecord::Base
         | 
| 8 | 
            +
                  has_one :kumie
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                class Kumie < ActiveRecord::Base; end
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              let!(:jason1) { Jason.create }
         | 
| 15 | 
            +
              let!(:jason2) { Jason.create }
         | 
| 16 | 
            +
              let!(:kumie1) { Kumie.create :jason_id => jason1.id }
         | 
| 17 | 
            +
              let!(:kumie2) { Kumie.create :jason_id => jason2.id }
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              let!(:exporter) { Tush::Exporter.new([jason1, jason2]) }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              describe "#data" do
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                it "should store data correctly" do
         | 
| 24 | 
            +
                  exporter.data.should ==
         | 
| 25 | 
            +
                    {:model_wrappers=>[{:model_class=>"Jason", :model_attributes=>{"id"=>1}, :model_trace=>[]}, {:model_class=>"Kumie", :model_attributes=>{"id"=>1, "jason_id"=>1}, :model_trace=>[["Jason", 1]]}, {:model_class=>"Jason", :model_attributes=>{"id"=>2}, :model_trace=>[]}, {:model_class=>"Kumie", :model_attributes=>{"id"=>2, "jason_id"=>2}, :model_trace=>[["Jason", 2]]}]}
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              describe "#export_json" do
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                it "should export its data in json" do
         | 
| 33 | 
            +
                  exporter.export_json.should ==
         | 
| 34 | 
            +
                    "{\"model_wrappers\":[{\"model_class\":\"Jason\",\"model_attributes\":{\"id\":1},\"model_trace\":[]},{\"model_class\":\"Kumie\",\"model_attributes\":{\"id\":1,\"jason_id\":1},\"model_trace\":[[\"Jason\",1]]},{\"model_class\":\"Jason\",\"model_attributes\":{\"id\":2},\"model_trace\":[]},{\"model_class\":\"Kumie\",\"model_attributes\":{\"id\":2,\"jason_id\":2},\"model_trace\":[[\"Jason\",2]]}]}"
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            end
         | 
    
        data/spec/helper.rb
    ADDED
    
    | @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            require 'simplecov'
         | 
| 2 | 
            +
            SimpleCov.start
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'rubygems'
         | 
| 5 | 
            +
            require 'bundler'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            begin
         | 
| 8 | 
            +
              Bundler.setup(:default, :development)
         | 
| 9 | 
            +
            rescue Bundler::BundlerError => e
         | 
| 10 | 
            +
              $stderr.puts e.message
         | 
| 11 | 
            +
              $stderr.puts "Run `bundle install` to install missing gems"
         | 
| 12 | 
            +
              exit e.status_code
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            require 'rspec'
         | 
| 16 | 
            +
            require 'shoulda'
         | 
| 17 | 
            +
            require 'pry'
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
         | 
| 20 | 
            +
            $LOAD_PATH.unshift(File.dirname(__FILE__))
         | 
| 21 | 
            +
            require 'tush'
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            require 'active_record'
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            require 'support/schema'
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            RSpec.configure do |config|
         | 
| 30 | 
            +
              config.around do |example|
         | 
| 31 | 
            +
                ActiveRecord::Base.transaction do
         | 
| 32 | 
            +
                  example.run
         | 
| 33 | 
            +
                  raise ActiveRecord::Rollback
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            def test_root
         | 
| 39 | 
            +
              File.expand_path '../..', __FILE__
         | 
| 40 | 
            +
            end
         | 
| @@ -0,0 +1,177 @@ | |
| 1 | 
            +
            require 'helper'
         | 
| 2 | 
            +
            require 'tempfile'
         | 
| 3 | 
            +
            require 'json'
         | 
| 4 | 
            +
            require 'sneaky-save'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            describe Tush::Importer do
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              before :all do
         | 
| 9 | 
            +
                class Kai < ActiveRecord::Base
         | 
| 10 | 
            +
                  has_one :brett
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                class Brett < ActiveRecord::Base; end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                class Byron < ActiveRecord::Base
         | 
| 16 | 
            +
                  belongs_to :kai
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              let!(:exported_data_path) { "#{test_root}/spec/support/exported_data.json" }
         | 
| 22 | 
            +
              let(:file) { File.read(exported_data_path) }
         | 
| 23 | 
            +
              let(:importer) { Tush::Importer.new_from_json_file(exported_data_path) }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              describe "#create_models!" do
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                it "imports data" do
         | 
| 28 | 
            +
                  importer.create_models!
         | 
| 29 | 
            +
                  importer.data.should ==
         | 
| 30 | 
            +
                    {"model_wrappers"=>
         | 
| 31 | 
            +
                    [{"model_class"=>"Kai",
         | 
| 32 | 
            +
                       "model_attributes"=>{"id"=>10, "sample_data"=>"data string"},
         | 
| 33 | 
            +
                       "original_db_key"=>"id",
         | 
| 34 | 
            +
                       "new_db_key"=>nil,
         | 
| 35 | 
            +
                       "original_db_id"=>1},
         | 
| 36 | 
            +
                     {"model_class"=>"Brett",
         | 
| 37 | 
            +
                       "model_attributes"=>{"id"=>1, "kai_id"=>10, "sample_data"=>"data string"},
         | 
| 38 | 
            +
                       "original_db_key"=>"id",
         | 
| 39 | 
            +
                       "new_db_key"=>nil,
         | 
| 40 | 
            +
                       "original_db_id"=>1},
         | 
| 41 | 
            +
                     {"model_class"=>"Kai",
         | 
| 42 | 
            +
                       "model_attributes"=>{"id"=>2, "sample_data"=>"data string"},
         | 
| 43 | 
            +
                       "original_db_key"=>"id",
         | 
| 44 | 
            +
                       "new_db_key"=>nil,
         | 
| 45 | 
            +
                       "original_db_id"=>2},
         | 
| 46 | 
            +
                     {"model_class"=>"Brett",
         | 
| 47 | 
            +
                       "model_attributes"=>{"id"=>2, "kai_id"=>2, "sample_data"=>"data string"},
         | 
| 48 | 
            +
                       "original_db_key"=>"id",
         | 
| 49 | 
            +
                       "new_db_key"=>nil,
         | 
| 50 | 
            +
                       "original_db_id"=>2}]}
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              describe "#find_wrapper_by_class_and_old_id" do
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                it "returns a matching wrapper" do
         | 
| 58 | 
            +
                  importer.create_models!
         | 
| 59 | 
            +
                  match = importer.find_wrapper_by_class_and_old_id(Kai, 10)
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  match.model_class.should == Kai
         | 
| 62 | 
            +
                  match.original_db_id.should == 10
         | 
| 63 | 
            +
                  match.original_db_key.should == "id"
         | 
| 64 | 
            +
                  match.new_model.should == Kai.first
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              describe "#update_foreign_keys!" do
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                PREFILLED_ROWS = 11
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                before :all do
         | 
| 74 | 
            +
                  class Lauren < ActiveRecord::Base
         | 
| 75 | 
            +
                    has_one :david
         | 
| 76 | 
            +
                    def self.custom_create(attributes)
         | 
| 77 | 
            +
                      Lauren.find_or_create_by_sample_data(attributes["sample_data"])
         | 
| 78 | 
            +
                    end
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  class David < ActiveRecord::Base
         | 
| 82 | 
            +
                    belongs_to :charlie
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  class Charlie < ActiveRecord::Base
         | 
| 86 | 
            +
                    belongs_to :lauren
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  class Miguel < ActiveRecord::Base
         | 
| 90 | 
            +
                    belongs_to :lauren
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  class Dan < ActiveRecord::Base
         | 
| 94 | 
            +
                    has_many :lauren
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  PREFILLED_ROWS.times do
         | 
| 98 | 
            +
                    Lauren.create
         | 
| 99 | 
            +
                    Charlie.create
         | 
| 100 | 
            +
                    David.create
         | 
| 101 | 
            +
                    Dan.create
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                let!(:dan) { Dan.create }
         | 
| 107 | 
            +
                let!(:lauren1) { Lauren.create :dan_id => dan.id, :sample_data => "sample data" }
         | 
| 108 | 
            +
                let!(:lauren2) { Lauren.create :dan_id => dan.id, :sample_data => "a;sdlfad" }
         | 
| 109 | 
            +
                let!(:charlie) { Charlie.create :lauren_id => lauren2.id }
         | 
| 110 | 
            +
                let!(:david) { David.create :lauren_id => lauren1.id, :charlie_id => charlie.id }
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                let!(:exported) { Tush::Exporter.new([lauren1, lauren2, david, charlie, dan]).export_json }
         | 
| 113 | 
            +
                let!(:importer) { Tush::Importer.new(JSON.parse(exported)) }
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                it "imports a few database rows into the same database correctly" do
         | 
| 116 | 
            +
                  importer.create_models!
         | 
| 117 | 
            +
                  importer.update_foreign_keys!
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                  existing_rows = PREFILLED_ROWS + 1
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                  Dan.count.should == existing_rows + 1
         | 
| 122 | 
            +
                  Lauren.count.should == existing_rows + 1
         | 
| 123 | 
            +
                  Charlie.count.should == existing_rows + 1
         | 
| 124 | 
            +
                  David.count.should == existing_rows + 1
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                  Dan.last.lauren.map { |lauren| lauren.id }.should == [12, 13]
         | 
| 127 | 
            +
                  David.last.charlie.id.should == 13
         | 
| 128 | 
            +
                  David.last.lauren_id.should == 12
         | 
| 129 | 
            +
                  Charlie.last.lauren.id.should == 13
         | 
| 130 | 
            +
                end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                describe "when a model wrapper doesn't exist" do
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                  it "removes foreign keys if a model wrapper doesn't exist for an association" do
         | 
| 135 | 
            +
                    lauren = Lauren.create
         | 
| 136 | 
            +
                    charlie = Charlie.create :lauren => lauren
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                    exported = Tush::Exporter.new([charlie], :blacklisted_models => [Lauren]).export_json
         | 
| 139 | 
            +
                    importer = Tush::Importer.new(JSON.parse(exported))
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                    importer.create_models!
         | 
| 142 | 
            +
                    importer.update_foreign_keys!
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                    importer.imported_model_wrappers.count.should == 1
         | 
| 145 | 
            +
                    importer.imported_model_wrappers[0].new_model.lauren_id.should == nil
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                  it "Doesn't remove foreign keys if the column has a not null restraint" do
         | 
| 149 | 
            +
                    lauren = Lauren.create
         | 
| 150 | 
            +
                    miguel = Miguel.create :lauren => lauren
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                    exported = Tush::Exporter.new([miguel], :blacklisted_models => [Lauren]).export_json
         | 
| 153 | 
            +
                    importer = Tush::Importer.new(JSON.parse(exported))
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                    importer.create_models!
         | 
| 156 | 
            +
                    importer.update_foreign_keys!
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                    importer.imported_model_wrappers.count.should == 1
         | 
| 159 | 
            +
                    importer.imported_model_wrappers[0].new_model.lauren_id.should == lauren.id
         | 
| 160 | 
            +
                  end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
              end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
              describe ".new_from_json" do
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                it "parses json and stores it in the data attribute" do
         | 
| 169 | 
            +
                  test_hash = { 'data' => 'data' }
         | 
| 170 | 
            +
                  importer = Tush::Importer.new_from_json(test_hash.to_json)
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                  importer.data.should == test_hash
         | 
| 173 | 
            +
                end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
              end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
            end
         |