jason-orm 0.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/.gitignore +3 -0
 - data/Gemfile +3 -0
 - data/Gemfile.lock +41 -0
 - data/Readme.md +130 -0
 - data/jason.gemspec +28 -0
 - data/lib/jason/core_ext/string.rb +7 -0
 - data/lib/jason/crypt/document_id.rb +15 -0
 - data/lib/jason/encoding/deletable.rb +30 -0
 - data/lib/jason/encoding/persistable.rb +102 -0
 - data/lib/jason/encoding/persistence_handler.rb +33 -0
 - data/lib/jason/encoding/persistence_object.rb +26 -0
 - data/lib/jason/encoding/restorable.rb +83 -0
 - data/lib/jason/errors.rb +13 -0
 - data/lib/jason/operations/file.rb +41 -0
 - data/lib/jason/persistence.rb +191 -0
 - data/lib/jason/reflection/base.rb +19 -0
 - data/lib/jason/relation.rb +127 -0
 - data/lib/jason.rb +71 -0
 - data/lib/version.rb +3 -0
 - data/spec/core_ext/string_spec.rb +22 -0
 - data/spec/persistence/persistence_spec.rb +259 -0
 - data/spec/relation/relation_spec.rb +105 -0
 - data/spec/spec_helper.rb +28 -0
 - metadata +127 -0
 
    
        data/.gitignore
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/Gemfile.lock
    ADDED
    
    | 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            PATH
         
     | 
| 
      
 2 
     | 
    
         
            +
              remote: .
         
     | 
| 
      
 3 
     | 
    
         
            +
              specs:
         
     | 
| 
      
 4 
     | 
    
         
            +
                jason (0.1)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  activesupport
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            GEM
         
     | 
| 
      
 8 
     | 
    
         
            +
              remote: http://rubygems.org/
         
     | 
| 
      
 9 
     | 
    
         
            +
              specs:
         
     | 
| 
      
 10 
     | 
    
         
            +
                activesupport (3.2.6)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  i18n (~> 0.6)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  multi_json (~> 1.0)
         
     | 
| 
      
 13 
     | 
    
         
            +
                chronic (0.6.7)
         
     | 
| 
      
 14 
     | 
    
         
            +
                diff-lcs (1.1.3)
         
     | 
| 
      
 15 
     | 
    
         
            +
                fuubar (1.0.0)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  rspec (~> 2.0)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  rspec-instafail (~> 0.2.0)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  ruby-progressbar (~> 0.0.10)
         
     | 
| 
      
 19 
     | 
    
         
            +
                i18n (0.6.0)
         
     | 
| 
      
 20 
     | 
    
         
            +
                multi_json (1.3.6)
         
     | 
| 
      
 21 
     | 
    
         
            +
                rake (0.9.2.2)
         
     | 
| 
      
 22 
     | 
    
         
            +
                rspec (2.11.0)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  rspec-core (~> 2.11.0)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  rspec-expectations (~> 2.11.0)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  rspec-mocks (~> 2.11.0)
         
     | 
| 
      
 26 
     | 
    
         
            +
                rspec-core (2.11.0)
         
     | 
| 
      
 27 
     | 
    
         
            +
                rspec-expectations (2.11.1)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  diff-lcs (~> 1.1.3)
         
     | 
| 
      
 29 
     | 
    
         
            +
                rspec-instafail (0.2.4)
         
     | 
| 
      
 30 
     | 
    
         
            +
                rspec-mocks (2.11.1)
         
     | 
| 
      
 31 
     | 
    
         
            +
                ruby-progressbar (0.0.10)
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            PLATFORMS
         
     | 
| 
      
 34 
     | 
    
         
            +
              ruby
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            DEPENDENCIES
         
     | 
| 
      
 37 
     | 
    
         
            +
              chronic
         
     | 
| 
      
 38 
     | 
    
         
            +
              fuubar
         
     | 
| 
      
 39 
     | 
    
         
            +
              jason!
         
     | 
| 
      
 40 
     | 
    
         
            +
              rake
         
     | 
| 
      
 41 
     | 
    
         
            +
              rspec
         
     | 
    
        data/Readme.md
    ADDED
    
    | 
         @@ -0,0 +1,130 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ## Jason (Json Persistence Framework)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ### Introduction
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            It's only for demonstration purposes. If you want to use it in your application - feel free. 
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            It uses *.json files for persistence. One for each model (imagine as *row*).
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            ### Features
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            By now, Jason supports:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            * a persistence_layer
         
     | 
| 
      
 14 
     | 
    
         
            +
            * a simple relation (association) mapper
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            It's customizable:
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            Jason.setup do |config|
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              config.persistence_path = "/Users/bob/jsons"
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              config.restore_app      = MyOwn::RestoreApp
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            ```
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            <code>config.restore_app</code> allows to use an own Class which handles restoring from *.json* files.
         
     | 
| 
      
 31 
     | 
    
         
            +
            If this is set, it replaces the integrated <code>Encoding::PersistenceHandler::Restorable</code> class. 
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            **The persistence layer**
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            Usage of the persistence layer is widly known from other libraries.
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            By now, it supports the following datatypes:
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            * Integer
         
     | 
| 
      
 41 
     | 
    
         
            +
            * String
         
     | 
| 
      
 42 
     | 
    
         
            +
            * Date
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 45 
     | 
    
         
            +
            class Person
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              include Jason::Persistence
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              attribute :first_name,  String
         
     | 
| 
      
 50 
     | 
    
         
            +
              attribute :last_name,   String
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            person = Person.new(:first_name => "Michail", :last_name => "Bulgakov")
         
     | 
| 
      
 55 
     | 
    
         
            +
            person.save
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            person.update_attributes(:first_name => "Sascha")
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            person.delete
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            Person.find("1223wer43")
         
     | 
| 
      
 62 
     | 
    
         
            +
            Person.find_by_id("1223wer43")
         
     | 
| 
      
 63 
     | 
    
         
            +
            Person.find_by_last_name("Bulgakov") #=> returns Array, it's kind of 'where'
         
     | 
| 
      
 64 
     | 
    
         
            +
            Person.find_by_first_name("Michael")
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            ```
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            **The relation mapper**
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            Usage of the relation mapper is also widly known from other libraries.
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            By now it supports:
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            * belongs_to
         
     | 
| 
      
 75 
     | 
    
         
            +
            * has_many (work in progress)
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 78 
     | 
    
         
            +
            class Person
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
              include Jason::Persistence
         
     | 
| 
      
 81 
     | 
    
         
            +
              include Jason::Relation
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
              attribute :first_name,  String
         
     | 
| 
      
 84 
     | 
    
         
            +
              attribute :last_name,   String  
         
     | 
| 
      
 85 
     | 
    
         
            +
              attribute :age,         Integer
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
              belongs_to :wife
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
            end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            class Wife
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
              include Jason::Persistence
         
     | 
| 
      
 94 
     | 
    
         
            +
              include Jason::Relation
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
              attribute :name,  String
         
     | 
| 
      
 97 
     | 
    
         
            +
            end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            person = Person.new(:first_name => "Michail", :last_name => "Bulgakov")
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
            woman = Wife.new(:name => "Natascha Rutskovskaja")
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            person.wife = woman 
         
     | 
| 
      
 104 
     | 
    
         
            +
            person.save
         
     | 
| 
      
 105 
     | 
    
         
            +
            ```
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
            <code>belongs_to</code> takes also a second parameter which is a hash:
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
            belongs_to :wife, :class => "Woman"
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
            ```
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
            so different class (names) are assignable to the relation name. 
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            ### TODO
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
            | Feature                         | Status            |
         
     | 
| 
      
 120 
     | 
    
         
            +
            |:--------------------------------|:------------------|
         
     | 
| 
      
 121 
     | 
    
         
            +
            | Date                            | DONE              |
         
     | 
| 
      
 122 
     | 
    
         
            +
            | has_many                        | DONE              |
         
     | 
| 
      
 123 
     | 
    
         
            +
            | Custom data types               | TODO              |
         
     | 
| 
      
 124 
     | 
    
         
            +
            | deletable only if already saved | DONE              |
         
     | 
| 
      
 125 
     | 
    
         
            +
            | code documentation              | Partly & TODO     |
         
     | 
| 
      
 126 
     | 
    
         
            +
            | Gemspec                         | DONE              |
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
            ### Last words
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
            Author: Daniel Schmidt, 15/16/17. July 2012
         
     | 
    
        data/jason.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            $:.push File.expand_path("../lib", __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "version"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 6 
     | 
    
         
            +
              s.name        = "jason-orm"
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.version     = Jason::VERSION
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.authors     = ["Daniel Schmidt"]
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.email       = ["dsci@code79.net"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.homepage    = ""
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.summary     = %q{JSON persistence framework}
         
     | 
| 
      
 12 
     | 
    
         
            +
              s.description = %q{A persistence framework based on json files.}
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              
         
     | 
| 
      
 15 
     | 
    
         
            +
              s.files         = `git ls-files`.split("\n")
         
     | 
| 
      
 16 
     | 
    
         
            +
              s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
         
     | 
| 
      
 17 
     | 
    
         
            +
              s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         
     | 
| 
      
 18 
     | 
    
         
            +
              s.require_paths = ["lib"]
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              # specify any dependencies here; for example:
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              s.add_dependency "activesupport"
         
     | 
| 
      
 23 
     | 
    
         
            +
              
         
     | 
| 
      
 24 
     | 
    
         
            +
              s.add_development_dependency "rake"
         
     | 
| 
      
 25 
     | 
    
         
            +
              s.add_development_dependency "rspec"
         
     | 
| 
      
 26 
     | 
    
         
            +
              s.add_development_dependency "fuubar"
         
     | 
| 
      
 27 
     | 
    
         
            +
              s.add_development_dependency "chronic"
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Jason
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              module Encoding
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                module PersistenceHandler
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  class Deletable < PersistenceObject
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    include Jason::Operations::File
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    def delete
         
     | 
| 
      
 12 
     | 
    
         
            +
                      deleted = true
         
     | 
| 
      
 13 
     | 
    
         
            +
                      persisted_file_content  = load_from_file(where_to_persist)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      r_objects       =  ActiveSupport::JSON.decode(persisted_file_content)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      r_objects.delete_if{|obj| obj[@root]["id"] == @persistable_obj.send(:id)}
         
     | 
| 
      
 16 
     | 
    
         
            +
                      save_to_file(ActiveSupport::JSON.encode(r_objects))
         
     | 
| 
      
 17 
     | 
    
         
            +
                    rescue 
         
     | 
| 
      
 18 
     | 
    
         
            +
                      deleted = false
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    ensure
         
     | 
| 
      
 21 
     | 
    
         
            +
                      return deleted
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,102 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Jason
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Encoding
         
     | 
| 
      
 3 
     | 
    
         
            +
                module PersistenceHandler
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  class Persistable < PersistenceObject
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    include Jason::Operations::File
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    def initialize(obj,options={})
         
     | 
| 
      
 10 
     | 
    
         
            +
                      @update           = options.fetch(:update, false)
         
     | 
| 
      
 11 
     | 
    
         
            +
                      super(obj)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
                   
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    def process_persistence
         
     | 
| 
      
 16 
     | 
    
         
            +
                      persisted = true
         
     | 
| 
      
 17 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 18 
     | 
    
         
            +
                        persisted_file_content  = load_from_file(where_to_persist)
         
     | 
| 
      
 19 
     | 
    
         
            +
                        r_objects       =  ActiveSupport::JSON.decode(persisted_file_content)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      rescue MultiJson::DecodeError => de
         
     | 
| 
      
 21 
     | 
    
         
            +
                        r_objects = []
         
     | 
| 
      
 22 
     | 
    
         
            +
                      ensure
         
     | 
| 
      
 23 
     | 
    
         
            +
                        # There was something persisted before. Search for id and replace.
         
     | 
| 
      
 24 
     | 
    
         
            +
                        # (Only if update is true)
         
     | 
| 
      
 25 
     | 
    
         
            +
                        # If not updated, append to objects array.
         
     | 
| 
      
 26 
     | 
    
         
            +
                        unless @update
         
     | 
| 
      
 27 
     | 
    
         
            +
                          as_json = @persistable_obj.send(:as_json)
         
     | 
| 
      
 28 
     | 
    
         
            +
                            
         
     | 
| 
      
 29 
     | 
    
         
            +
                          # persist with relations if given.
         
     | 
| 
      
 30 
     | 
    
         
            +
                          # persist belongs_to
         
     | 
| 
      
 31 
     | 
    
         
            +
                          
         
     | 
| 
      
 32 
     | 
    
         
            +
                          if @persistable_obj.class.ancestors.map(&:to_s).include?("Jason::Relation")
         
     | 
| 
      
 33 
     | 
    
         
            +
                            as_json[@root].each_pair do |key,value|
         
     | 
| 
      
 34 
     | 
    
         
            +
                              next unless key.to_s.include?("_id")
         
     | 
| 
      
 35 
     | 
    
         
            +
                              relation = key.to_s.split("_id").first.to_sym
         
     | 
| 
      
 36 
     | 
    
         
            +
                              reflection = @persistable_obj.class.reflect_on_relation(relation)
         
     | 
| 
      
 37 
     | 
    
         
            +
                              if reflection
         
     | 
| 
      
 38 
     | 
    
         
            +
                                process_method = instance_method("process_#{reflection.type}")
         
     | 
| 
      
 39 
     | 
    
         
            +
                                process_method.bind(self).call(reflection,value)
         
     | 
| 
      
 40 
     | 
    
         
            +
                              end
         
     | 
| 
      
 41 
     | 
    
         
            +
                            end
         
     | 
| 
      
 42 
     | 
    
         
            +
                          end
         
     | 
| 
      
 43 
     | 
    
         
            +
                          r_objects << as_json
         
     | 
| 
      
 44 
     | 
    
         
            +
                        else 
         
     | 
| 
      
 45 
     | 
    
         
            +
                          r_objects.each do |object|
         
     | 
| 
      
 46 
     | 
    
         
            +
                            if object[@root]["id"] == @persistable_obj.send(:id)
         
     | 
| 
      
 47 
     | 
    
         
            +
                              # persist with relations if given.
         
     | 
| 
      
 48 
     | 
    
         
            +
                              object[@root] = @persistable_obj.send(:as_json)[@root]
         
     | 
| 
      
 49 
     | 
    
         
            +
                              break
         
     | 
| 
      
 50 
     | 
    
         
            +
                            end
         
     | 
| 
      
 51 
     | 
    
         
            +
                          end
         
     | 
| 
      
 52 
     | 
    
         
            +
                        end
         
     | 
| 
      
 53 
     | 
    
         
            +
                        persisted = save_to_file(ActiveSupport::JSON.encode(r_objects))
         
     | 
| 
      
 54 
     | 
    
         
            +
                      end
         
     | 
| 
      
 55 
     | 
    
         
            +
                      return persisted
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    private 
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    def process_belongs_to(reflection,value)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      persist = instance_method(:run_relation_persistence)
         
     | 
| 
      
 62 
     | 
    
         
            +
                      action = lambda do |relation_name,relation_class,value|
         
     | 
| 
      
 63 
     | 
    
         
            +
                        begin
         
     | 
| 
      
 64 
     | 
    
         
            +
                          already_persisted = relation_class.find(value)
         
     | 
| 
      
 65 
     | 
    
         
            +
                        rescue Jason::Errors::DocumentNotFoundError
         
     | 
| 
      
 66 
     | 
    
         
            +
                          relation_obj = @persistable_obj.send(relation_name)
         
     | 
| 
      
 67 
     | 
    
         
            +
                          relation_obj.save
         
     | 
| 
      
 68 
     | 
    
         
            +
                        end
         
     | 
| 
      
 69 
     | 
    
         
            +
                      end
         
     | 
| 
      
 70 
     | 
    
         
            +
                      persist.bind(self).call(reflection,value,action)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                    def process_has_many(reflection,value)
         
     | 
| 
      
 74 
     | 
    
         
            +
                      persist = instance_method(:run_relation_persistence)
         
     | 
| 
      
 75 
     | 
    
         
            +
                      action = lambda do |relation_name,relation_class,value|
         
     | 
| 
      
 76 
     | 
    
         
            +
                        ids = value.split(Jason::has_many_separator)
         
     | 
| 
      
 77 
     | 
    
         
            +
                        ids.each do |id|
         
     | 
| 
      
 78 
     | 
    
         
            +
                          begin
         
     | 
| 
      
 79 
     | 
    
         
            +
                            relation_class.find(id)
         
     | 
| 
      
 80 
     | 
    
         
            +
                          rescue Jason::Errors::DocumentNotFoundError
         
     | 
| 
      
 81 
     | 
    
         
            +
                            relation_obj = @persistable_obj.send(relation_name).detect{|obj| obj.id == id}
         
     | 
| 
      
 82 
     | 
    
         
            +
                            relation_obj.save unless relation_obj.nil?
         
     | 
| 
      
 83 
     | 
    
         
            +
                          end
         
     | 
| 
      
 84 
     | 
    
         
            +
                        end
         
     | 
| 
      
 85 
     | 
    
         
            +
                      end
         
     | 
| 
      
 86 
     | 
    
         
            +
                      persist.bind(self).call(reflection,value,action)
         
     | 
| 
      
 87 
     | 
    
         
            +
                    end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                    def run_relation_persistence(reflection,value,block)
         
     | 
| 
      
 90 
     | 
    
         
            +
                      relation_name   = reflection.name
         
     | 
| 
      
 91 
     | 
    
         
            +
                      relation_class  = Module.const_get(reflection.class_name.to_sym)
         
     | 
| 
      
 92 
     | 
    
         
            +
                      block.call(relation_name,relation_class,value)
         
     | 
| 
      
 93 
     | 
    
         
            +
                    end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                    def r_objects
         
     | 
| 
      
 96 
     | 
    
         
            +
                      @r_objects ||= []
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
              end
         
     | 
| 
      
 102 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'active_support/hash_with_indifferent_access'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative 'persistence_object'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'deletable'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'persistable'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative 'restorable'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module Jason
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              module Encoding
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                module PersistenceHandler
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  extend self
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def persist(obj, options={})
         
     | 
| 
      
 17 
     | 
    
         
            +
                    return Persistable.new(obj,options).process_persistence
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def delete(obj)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    return Deletable.new(obj).delete
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def restore(*args)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    action = args.shift
         
     | 
| 
      
 26 
     | 
    
         
            +
                    Jason.restore_app.new.send(action,*args)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end      
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Jason
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Encoding
         
     | 
| 
      
 3 
     | 
    
         
            +
                module PersistenceHandler
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  class PersistenceObject 
         
     | 
| 
      
 6 
     | 
    
         
            +
                    attr_accessor :persistable_obj
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                    def eigenclass
         
     | 
| 
      
 9 
     | 
    
         
            +
                      class << self;
         
     | 
| 
      
 10 
     | 
    
         
            +
                        self;
         
     | 
| 
      
 11 
     | 
    
         
            +
                      end
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    def initialize(obj)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      @persistable_obj  = obj
         
     | 
| 
      
 16 
     | 
    
         
            +
                      @root             = Jason.singularize_key(obj.class)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    def instance_method(method_name)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      eigenclass.instance_method(method_name)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,83 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Jason
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Encoding
         
     | 
| 
      
 3 
     | 
    
         
            +
                module PersistenceHandler
         
     | 
| 
      
 4 
     | 
    
         
            +
                
         
     | 
| 
      
 5 
     | 
    
         
            +
                  class Restorable
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    include Jason::Operations::File
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    def by_id(*args)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      options = args.shift
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                      @id = options[:id]
         
     | 
| 
      
 13 
     | 
    
         
            +
                      @klass = options[:klass]
         
     | 
| 
      
 14 
     | 
    
         
            +
                      key = Jason::singularize_key(@klass)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      persisted_file_content = load_from_file(where_to_persist(@klass.name))
         
     | 
| 
      
 16 
     | 
    
         
            +
                      r_objects = ActiveSupport::JSON.decode(persisted_file_content)
         
     | 
| 
      
 17 
     | 
    
         
            +
                      obj = r_objects.detect{|obj| obj[key]["id"] == @id}
         
     | 
| 
      
 18 
     | 
    
         
            +
                      raise Jason::Errors::DocumentNotFoundError, "Document not found with id #{@id}." if obj.nil?
         
     | 
| 
      
 19 
     | 
    
         
            +
                      
         
     | 
| 
      
 20 
     | 
    
         
            +
                      return restore_with_cast(obj[key])
         
     | 
| 
      
 21 
     | 
    
         
            +
                    rescue MultiJson::DecodeError => de
         
     | 
| 
      
 22 
     | 
    
         
            +
                      raise Jason::Errors::DocumentNotFoundError, "Document not found with id #{@id}."
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    def all(*args)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      options = args.shift
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                      @klass = options[:klass]
         
     | 
| 
      
 29 
     | 
    
         
            +
                      key = Jason::singularize_key(@klass)
         
     | 
| 
      
 30 
     | 
    
         
            +
                      persisted_file_content = load_from_file(where_to_persist(@klass.name))
         
     | 
| 
      
 31 
     | 
    
         
            +
                      r_objects = ActiveSupport::JSON.decode(persisted_file_content)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      r_objects.map do |obj|
         
     | 
| 
      
 33 
     | 
    
         
            +
                        restore_with_cast(obj[key])
         
     | 
| 
      
 34 
     | 
    
         
            +
                      end
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    def with_conditions(*args)
         
     | 
| 
      
 38 
     | 
    
         
            +
                      options = args.pop
         
     | 
| 
      
 39 
     | 
    
         
            +
                      
         
     | 
| 
      
 40 
     | 
    
         
            +
                      @klass = options[:klass]
         
     | 
| 
      
 41 
     | 
    
         
            +
                      options.delete(:klass)
         
     | 
| 
      
 42 
     | 
    
         
            +
                      key = Jason::singularize_key(@klass)
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                      persisted_file_content = load_from_file(where_to_persist(@klass.name))
         
     | 
| 
      
 45 
     | 
    
         
            +
                      r_objects = ActiveSupport::JSON.decode(persisted_file_content)
         
     | 
| 
      
 46 
     | 
    
         
            +
                      found_objects = []
         
     | 
| 
      
 47 
     | 
    
         
            +
                      
         
     | 
| 
      
 48 
     | 
    
         
            +
                      r_objects.each do |obj|
         
     | 
| 
      
 49 
     | 
    
         
            +
                        if obj[key][options.keys.join.to_s] == options.values.join
         
     | 
| 
      
 50 
     | 
    
         
            +
                          found_objects << restore_with_cast(obj[key])
         
     | 
| 
      
 51 
     | 
    
         
            +
                        end
         
     | 
| 
      
 52 
     | 
    
         
            +
                      end
         
     | 
| 
      
 53 
     | 
    
         
            +
                      found_objects
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    private 
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    def restore_with_cast(attributes)
         
     | 
| 
      
 59 
     | 
    
         
            +
                      instance = @klass.new(HashWithIndifferentAccess.new(attributes))
         
     | 
| 
      
 60 
     | 
    
         
            +
                      
         
     | 
| 
      
 61 
     | 
    
         
            +
                      instance.instance_eval do
         
     | 
| 
      
 62 
     | 
    
         
            +
                        @new_record = false 
         
     | 
| 
      
 63 
     | 
    
         
            +
                        # parse in given datatypes
         
     | 
| 
      
 64 
     | 
    
         
            +
                        @attributes.each_pair do |key,value|
         
     | 
| 
      
 65 
     | 
    
         
            +
                          begin
         
     | 
| 
      
 66 
     | 
    
         
            +
                            attribute_definition = self.class.defined_attributes.detect do |item| 
         
     | 
| 
      
 67 
     | 
    
         
            +
                              item[:name] == key.to_sym
         
     | 
| 
      
 68 
     | 
    
         
            +
                            end[:type]
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                            cast_to = Jason::DATA_TYPES["#{attribute_definition.to_sym}"]
         
     | 
| 
      
 71 
     | 
    
         
            +
                            instance_variable_set("@#{key}",value.send(cast_to))
         
     | 
| 
      
 72 
     | 
    
         
            +
                          rescue 
         
     | 
| 
      
 73 
     | 
    
         
            +
                            next
         
     | 
| 
      
 74 
     | 
    
         
            +
                          end
         
     | 
| 
      
 75 
     | 
    
         
            +
                        end
         
     | 
| 
      
 76 
     | 
    
         
            +
                      end
         
     | 
| 
      
 77 
     | 
    
         
            +
                      return instance
         
     | 
| 
      
 78 
     | 
    
         
            +
                    end
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
                  
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
              end
         
     | 
| 
      
 83 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/jason/errors.rb
    ADDED
    
    
| 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Jason 
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              module Operations
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                module File
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  private
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def where_to_persist(obj_name=nil)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    if obj_name.nil? and self.respond_to?(:persistable_obj)
         
     | 
| 
      
 11 
     | 
    
         
            +
                      file_prefix = persistable_obj.class.name.tableize 
         
     | 
| 
      
 12 
     | 
    
         
            +
                    else
         
     | 
| 
      
 13 
     | 
    
         
            +
                      file_prefix = obj_name.tableize
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
                    ::File.join(Jason.persistence_path,"#{file_prefix}.json")
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def save_to_file(json)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    persisted = true
         
     | 
| 
      
 20 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 21 
     | 
    
         
            +
                      open(where_to_persist, 'w') do |file|
         
     | 
| 
      
 22 
     | 
    
         
            +
                        file.puts json
         
     | 
| 
      
 23 
     | 
    
         
            +
                      end
         
     | 
| 
      
 24 
     | 
    
         
            +
                    rescue => e
         
     | 
| 
      
 25 
     | 
    
         
            +
                      puts e.message
         
     | 
| 
      
 26 
     | 
    
         
            +
                      persisted = false
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                    return persisted
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def load_from_file(file_name)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    ::File.open(file_name).read rescue ""
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                 
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     |