plain_record 0.1 → 0.2
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 +8 -0
- data/.rspec +1 -0
- data/.travis.yml +6 -0
- data/.yardopts +4 -0
- data/ChangeLog +9 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +24 -0
- data/LICENSE +3 -4
- data/README.md +124 -0
- data/Rakefile +27 -50
- data/lib/plain_record/association_proxy.rb +59 -0
- data/lib/plain_record/associations.rb +271 -0
- data/lib/plain_record/callbacks.rb +146 -0
- data/lib/plain_record/filepath.rb +141 -0
- data/lib/plain_record/model/entry.rb +17 -9
- data/lib/plain_record/model/list.rb +22 -9
- data/lib/plain_record/model.rb +119 -64
- data/lib/plain_record/resource.rb +72 -19
- data/lib/plain_record/version.rb +1 -1
- data/lib/plain_record.rb +21 -2
- data/plain_record.gemspec +30 -0
- data/spec/associations_spec.rb +142 -0
- data/spec/callbacks_spec.rb +59 -0
- data/spec/data/1/comments.yml +5 -0
- data/spec/data/1/{post.m → post.md} +0 -0
- data/spec/data/2/{post.m → post.md} +1 -1
- data/spec/data/3/post.md +4 -0
- data/spec/data/authors/extern.yml +2 -2
- data/spec/data/authors/intern.yml +4 -4
- data/spec/data/best/4/post.md +1 -0
- data/spec/filepath_spec.rb +53 -0
- data/spec/model_spec.rb +90 -42
- data/spec/resource_spec.rb +70 -27
- data/spec/spec_helper.rb +33 -14
- metadata +122 -70
- data/README.rdoc +0 -96
- data/spec/data/3/post.m +0 -1
| @@ -0,0 +1,59 @@ | |
| 1 | 
            +
            require File.join(File.dirname(__FILE__), 'spec_helper')
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe PlainRecord::Callbacks do
         | 
| 4 | 
            +
              before :all do
         | 
| 5 | 
            +
                module ::Fullname
         | 
| 6 | 
            +
                  include PlainRecord::Callbacks
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def fullname(first, second)
         | 
| 9 | 
            +
                    use_callbacks(:fullname, first, second) do
         | 
| 10 | 
            +
                      first + ' ' + second
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              it "should use methods without callbacks" do
         | 
| 17 | 
            +
                Class.new {
         | 
| 18 | 
            +
                  extend ::Fullname
         | 
| 19 | 
            +
                }.fullname('John', 'Smith').should == 'John Smith'
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              it "should use before callbacks by priority" do
         | 
| 23 | 
            +
                checker = mock()
         | 
| 24 | 
            +
                checker.should_receive(:check_first).with('John', 'Smith').once.ordered
         | 
| 25 | 
            +
                checker.should_receive(:check_last).with('John', 'Smith').once.ordered
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                Class.new {
         | 
| 28 | 
            +
                  extend ::Fullname
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  before :fullname, 2, &checker.method(:check_last)
         | 
| 31 | 
            +
                  before :fullname, 1, &checker.method(:check_first)
         | 
| 32 | 
            +
                }.fullname('John', 'Smith').should == 'John Smith'
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              it "should use after callbacks by priority" do
         | 
| 36 | 
            +
                adder = Class.new do
         | 
| 37 | 
            +
                  def self.add_first(full, first, last); full + ' ' + first.downcase end
         | 
| 38 | 
            +
                  def self.add_last(full, first, last);  full + ' ' + last.downcase  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                Class.new {
         | 
| 42 | 
            +
                  extend ::Fullname
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  after :fullname, 2, &adder.method(:add_last)
         | 
| 45 | 
            +
                  after :fullname, 1, &adder.method(:add_first)
         | 
| 46 | 
            +
                }.fullname('John', 'Smith').should == 'John Smith john smith'
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              it "should set one callback for many events" do
         | 
| 50 | 
            +
                klass = Class.new {
         | 
| 51 | 
            +
                  extend ::Fullname
         | 
| 52 | 
            +
                  before [:one, :two] do; end
         | 
| 53 | 
            +
                  before [:one, :two] do; end
         | 
| 54 | 
            +
                }
         | 
| 55 | 
            +
                klass.callbacks[:before].length.should == 2
         | 
| 56 | 
            +
                klass.callbacks[:after].length.should == 2
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            end
         | 
| 
            File without changes
         | 
    
        data/spec/data/3/post.md
    ADDED
    
    
| @@ -1,3 +1,3 @@ | |
| 1 1 | 
             
            - name:  Anonymous
         | 
| 2 | 
            -
            -  | 
| 3 | 
            -
               | 
| 2 | 
            +
            - name:  SuperHacker
         | 
| 3 | 
            +
              login: super1997
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            -  | 
| 2 | 
            -
               | 
| 3 | 
            -
            -  | 
| 4 | 
            -
               | 
| 1 | 
            +
            - name:  John Smith
         | 
| 2 | 
            +
              login: john
         | 
| 3 | 
            +
            - name:  Ivan Ivanov
         | 
| 4 | 
            +
              login: ivan
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            title: Best
         | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            require File.join(File.dirname(__FILE__), 'spec_helper')
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe PlainRecord::Filepath do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              it "shouldn't create non-virtual filepath property" do
         | 
| 6 | 
            +
                lambda {
         | 
| 7 | 
            +
                  Class.new do
         | 
| 8 | 
            +
                    include PlainRecord::Resource
         | 
| 9 | 
            +
                    entry_in 'data/*/post.md'
         | 
| 10 | 
            +
                    property :category, in_filepath(1)
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                }.should raise_error(ArgumentError, /virtual creator/)
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              it "should load filepath property" do
         | 
| 16 | 
            +
                best = FilepathPost.first(:title => 'Best')
         | 
| 17 | 
            +
                best.category.should == 'best/'
         | 
| 18 | 
            +
                best.name.should == '4'
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              it "should load filepath property as nil when ** pattern is empty" do
         | 
| 22 | 
            +
                FilepathPost.first(:title => 'First').category.should be_empty
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              it "should return more accurate path by filepath properties" do
         | 
| 26 | 
            +
                FilepathPost.path(:name => 2).should == 'data/**/2/post.md'
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              it "should use filepath properties in search" do
         | 
| 30 | 
            +
                FilepathPost.loaded = { }
         | 
| 31 | 
            +
                FilepathPost.all(:category => 'best/')
         | 
| 32 | 
            +
                FilepathPost.loaded.should have(1).keys
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              it "should load properties from model constructor" do
         | 
| 36 | 
            +
                post = FilepathPost.new(:name => 5)
         | 
| 37 | 
            +
                post.name.should == 5
         | 
| 38 | 
            +
                post.category.should be_nil
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              it "should get entry path by filepath properties" do
         | 
| 42 | 
            +
                path = File.join(File.dirname(__FILE__), 'data/5/post.md')
         | 
| 43 | 
            +
                post = FilepathPost.new(:name => 5, :category => '')
         | 
| 44 | 
            +
                FilepathPost.should_receive(:move_entry).with(post, nil, path)
         | 
| 45 | 
            +
                post.save
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              it "should raise error, when can't get entry path by filepath properties" do
         | 
| 49 | 
            +
                post = FilepathPost.new
         | 
| 50 | 
            +
                lambda { post.save }.should raise_error(ArgumentError, /isn't file to save/)
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            end
         | 
    
        data/spec/model_spec.rb
    CHANGED
    
    | @@ -1,33 +1,56 @@ | |
| 1 1 | 
             
            require File.join(File.dirname(__FILE__), 'spec_helper')
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe PlainRecord::Model do
         | 
| 4 | 
            -
             | 
| 4 | 
            +
             | 
| 5 | 
            +
              after :each do
         | 
| 6 | 
            +
                Post.loaded   = { }
         | 
| 7 | 
            +
                Author.loaded = { }
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              it "should define virtual property" do
         | 
| 11 | 
            +
                klass = Class.new do
         | 
| 12 | 
            +
                  include PlainRecord::Resource
         | 
| 13 | 
            +
                  virtual :one, Definers.none
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                klass.virtuals.should == [:one]
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              it "shouldn't define virtual property without accessor from definers" do
         | 
| 20 | 
            +
                lambda {
         | 
| 21 | 
            +
                  Class.new do
         | 
| 22 | 
            +
                    include PlainRecord::Resource
         | 
| 23 | 
            +
                    virtual :one, Definers.reader
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                }.should raise_error(ArgumentError, /own accessors/)
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 5 28 | 
             
              it "should define property" do
         | 
| 6 29 | 
             
                klass = Class.new do
         | 
| 7 30 | 
             
                  include PlainRecord::Resource
         | 
| 8 31 | 
             
                  property :one
         | 
| 9 32 | 
             
                end
         | 
| 10 | 
            -
             | 
| 33 | 
            +
             | 
| 11 34 | 
             
                klass.properties.should == [:one]
         | 
| 12 | 
            -
                object = klass.new(nil, {'one' => 1})
         | 
| 35 | 
            +
                object = klass.new(nil, { 'one' => 1 })
         | 
| 13 36 | 
             
                object.one.should == 1
         | 
| 14 37 | 
             
                object.one = 2
         | 
| 15 38 | 
             
                object.one.should == 2
         | 
| 16 39 | 
             
              end
         | 
| 17 | 
            -
             | 
| 40 | 
            +
             | 
| 18 41 | 
             
              it "should define text" do
         | 
| 19 42 | 
             
                klass = Class.new do
         | 
| 20 43 | 
             
                  include PlainRecord::Resource
         | 
| 21 44 | 
             
                  text :content
         | 
| 22 45 | 
             
                end
         | 
| 23 | 
            -
             | 
| 46 | 
            +
             | 
| 24 47 | 
             
                klass.texts.should == [:content]
         | 
| 25 | 
            -
                object = klass.new(nil, {}, ['text'])
         | 
| 48 | 
            +
                object = klass.new(nil, { }, ['text'])
         | 
| 26 49 | 
             
                object.content.should == 'text'
         | 
| 27 50 | 
             
                object.content = 'another'
         | 
| 28 51 | 
             
                object.content.should == 'another'
         | 
| 29 52 | 
             
              end
         | 
| 30 | 
            -
             | 
| 53 | 
            +
             | 
| 31 54 | 
             
              it "should call definer" do
         | 
| 32 55 | 
             
                klass = Class.new do
         | 
| 33 56 | 
             
                  include PlainRecord::Resource
         | 
| @@ -38,7 +61,7 @@ describe PlainRecord::Model do | |
| 38 61 | 
             
                end
         | 
| 39 62 | 
             
                klass.should has_methods(:one, :'one=', :'three=', :two)
         | 
| 40 63 | 
             
              end
         | 
| 41 | 
            -
             | 
| 64 | 
            +
             | 
| 42 65 | 
             
              it "should use accessors from definers" do
         | 
| 43 66 | 
             
                klass = Class.new do
         | 
| 44 67 | 
             
                  include PlainRecord::Resource
         | 
| @@ -47,25 +70,29 @@ describe PlainRecord::Model do | |
| 47 70 | 
             
                end
         | 
| 48 71 | 
             
                klass.should has_methods(:two)
         | 
| 49 72 | 
             
              end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
              it "should send property name to definer" do
         | 
| 73 | 
            +
             | 
| 74 | 
            +
              it "should send property name and caller type to definer" do
         | 
| 52 75 | 
             
                definer = mock
         | 
| 53 | 
            -
                definer.stub!(: | 
| 76 | 
            +
                definer.stub!(:virtual).with(:one, :virtual)
         | 
| 77 | 
            +
                definer.stub!(:property).with(:two, :property)
         | 
| 78 | 
            +
                definer.stub!(:text).with(:three, :text)
         | 
| 54 79 | 
             
                klass = Class.new do
         | 
| 55 80 | 
             
                  include PlainRecord::Resource
         | 
| 56 | 
            -
                   | 
| 81 | 
            +
                  virtual  :one,   definer.method(:virtual)
         | 
| 82 | 
            +
                  property :two,   definer.method(:property)
         | 
| 83 | 
            +
                  text     :three, definer.method(:text)
         | 
| 57 84 | 
             
                end
         | 
| 58 85 | 
             
              end
         | 
| 59 | 
            -
             | 
| 86 | 
            +
             | 
| 60 87 | 
             
              it "should find all enrty files by glob pattern" do
         | 
| 61 88 | 
             
                klass = Class.new do
         | 
| 62 89 | 
             
                  include PlainRecord::Resource
         | 
| 63 | 
            -
                  entry_in 'data/*/post. | 
| 90 | 
            +
                  entry_in 'data/*/post.md'
         | 
| 64 91 | 
             
                end
         | 
| 65 92 | 
             
                klass.storage.should == :entry
         | 
| 66 93 | 
             
                klass.files.sort.should == [FIRST, SECOND, THIRD]
         | 
| 67 94 | 
             
              end
         | 
| 68 | 
            -
             | 
| 95 | 
            +
             | 
| 69 96 | 
             
              it "should find all list files by glob pattern" do
         | 
| 70 97 | 
             
                klass = Class.new do
         | 
| 71 98 | 
             
                  include PlainRecord::Resource
         | 
| @@ -74,40 +101,40 @@ describe PlainRecord::Model do | |
| 74 101 | 
             
                klass.storage.should == :list
         | 
| 75 102 | 
             
                klass.files.sort.should == [EXTERN, INTERN]
         | 
| 76 103 | 
             
              end
         | 
| 77 | 
            -
             | 
| 104 | 
            +
             | 
| 78 105 | 
             
              it "should load YAML data from entry file" do
         | 
| 79 106 | 
             
                obj = Post.load_file(FIRST)
         | 
| 80 107 | 
             
                obj.should be_a(Post)
         | 
| 81 108 | 
             
                obj.title.should == 'First'
         | 
| 82 | 
            -
             | 
| 109 | 
            +
             | 
| 83 110 | 
             
                obj = Post.load_file(SECOND)
         | 
| 84 111 | 
             
                obj.should be_a(Post)
         | 
| 85 112 | 
             
                obj.title.should be_nil
         | 
| 86 113 | 
             
              end
         | 
| 87 | 
            -
             | 
| 114 | 
            +
             | 
| 88 115 | 
             
              it "should load text data from entry file" do
         | 
| 89 116 | 
             
                post = Post.load_file(FIRST)
         | 
| 90 117 | 
             
                post.summary.should == 'first --- content'
         | 
| 91 118 | 
             
                post.content.rstrip.should == "big\n---\ncontent"
         | 
| 92 | 
            -
             | 
| 119 | 
            +
             | 
| 93 120 | 
             
                post = Post.load_file(SECOND)
         | 
| 94 121 | 
             
                post.summary.rstrip.should == " only one"
         | 
| 95 122 | 
             
                post.content.should be_nil
         | 
| 96 123 | 
             
              end
         | 
| 97 | 
            -
             | 
| 124 | 
            +
             | 
| 98 125 | 
             
              it "should load data from list file" do
         | 
| 99 126 | 
             
                authors = Author.load_file(EXTERN)
         | 
| 100 127 | 
             
                authors.length.should == 2
         | 
| 101 | 
            -
             | 
| 128 | 
            +
             | 
| 102 129 | 
             
                authors[0].should be_a(Author)
         | 
| 103 130 | 
             
                authors[0].login.should be_nil
         | 
| 104 131 | 
             
                authors[0].name.should == 'Anonymous'
         | 
| 105 | 
            -
             | 
| 132 | 
            +
             | 
| 106 133 | 
             
                authors[1].should be_a(Author)
         | 
| 107 134 | 
             
                authors[1].login.should == 'super1997'
         | 
| 108 135 | 
             
                authors[1].name.should == 'SuperHacker'
         | 
| 109 136 | 
             
              end
         | 
| 110 | 
            -
             | 
| 137 | 
            +
             | 
| 111 138 | 
             
              it "shouldn't define text data in model with list storage" do
         | 
| 112 139 | 
             
                lambda {
         | 
| 113 140 | 
             
                  klass = Class.new do
         | 
| @@ -117,58 +144,79 @@ describe PlainRecord::Model do | |
| 117 144 | 
             
                  end
         | 
| 118 145 | 
             
                }.should raise_error /entry_in/
         | 
| 119 146 | 
             
              end
         | 
| 120 | 
            -
             | 
| 147 | 
            +
             | 
| 121 148 | 
             
              it "should load all entries" do
         | 
| 122 | 
            -
                Post.all.should  | 
| 149 | 
            +
                Post.all.should =~ [SECOND_POST, THIRD_POST, FIRST_POST]
         | 
| 123 150 | 
             
              end
         | 
| 124 | 
            -
             | 
| 151 | 
            +
             | 
| 125 152 | 
             
              it "should return entries by string matcher" do
         | 
| 126 153 | 
             
                Post.all(:title => 'First').should == [FIRST_POST]
         | 
| 127 154 | 
             
              end
         | 
| 128 | 
            -
             | 
| 155 | 
            +
             | 
| 129 156 | 
             
              it "should return entries by regexp matcher" do
         | 
| 130 157 | 
             
                Post.all(:title => /First/, :title => /Second/).should be_empty
         | 
| 131 158 | 
             
              end
         | 
| 132 | 
            -
             | 
| 159 | 
            +
             | 
| 133 160 | 
             
              it "should return entries by search proc" do
         | 
| 134 | 
            -
                Post.all { |i| not i.title.nil? }.should  | 
| 161 | 
            +
                Post.all { |i| not i.title.nil? }.should =~ [THIRD_POST, FIRST_POST]
         | 
| 135 162 | 
             
              end
         | 
| 136 | 
            -
             | 
| 163 | 
            +
             | 
| 137 164 | 
             
              it "should return all list entries" do
         | 
| 138 | 
            -
                Author.all.map { |i| i.login }.should  | 
| 165 | 
            +
                Author.all.map { |i| i.login }.should =~ [nil, 'super1997', 'john', 'ivan']
         | 
| 139 166 | 
             
              end
         | 
| 140 | 
            -
             | 
| 167 | 
            +
             | 
| 141 168 | 
             
              it "should return first entry" do
         | 
| 142 169 | 
             
                Post.first.should be_a(Post)
         | 
| 143 170 | 
             
              end
         | 
| 144 | 
            -
             | 
| 171 | 
            +
             | 
| 145 172 | 
             
              it "should return entry by string matcher" do
         | 
| 146 173 | 
             
                Post.first(:title => 'Third').should == THIRD_POST
         | 
| 147 174 | 
             
              end
         | 
| 148 | 
            -
             | 
| 175 | 
            +
             | 
| 149 176 | 
             
              it "should return entry by regexp matcher" do
         | 
| 150 | 
            -
                Post.first(:title => /First | 
| 177 | 
            +
                Post.first(:title => /First/).should == FIRST_POST
         | 
| 151 178 | 
             
              end
         | 
| 152 | 
            -
             | 
| 179 | 
            +
             | 
| 153 180 | 
             
              it "should return entry by search proc" do
         | 
| 154 181 | 
             
                Post.first { |i| false }.should be_nil
         | 
| 155 182 | 
             
              end
         | 
| 156 | 
            -
             | 
| 183 | 
            +
             | 
| 157 184 | 
             
              it "should return first list entry" do
         | 
| 158 | 
            -
                Author.first { |i| not i.login.nil?  | 
| 185 | 
            +
                Author.first { |i| not i.login.nil? and i.type == 'extern' }.
         | 
| 186 | 
            +
                  name.should == 'SuperHacker'
         | 
| 159 187 | 
             
              end
         | 
| 160 | 
            -
             | 
| 188 | 
            +
             | 
| 161 189 | 
             
              it "should delete file, cache and empty dirs" do
         | 
| 162 190 | 
             
                File.should_receive(:delete).with(FIRST)
         | 
| 163 | 
            -
             | 
| 191 | 
            +
             | 
| 164 192 | 
             
                first_dir = File.dirname(FIRST)
         | 
| 165 193 | 
             
                Dir.should_receive(:entries).with(first_dir).and_return(['.', '..'])
         | 
| 166 194 | 
             
                Dir.should_receive(:rmdir).with(first_dir)
         | 
| 167 195 | 
             
                Dir.should_receive(:entries).with(File.dirname(first_dir)).and_return(
         | 
| 168 196 | 
             
                    ['.', '..', '2', '3'])
         | 
| 169 | 
            -
             | 
| 197 | 
            +
             | 
| 170 198 | 
             
                Post.instance_eval { delete_file(FIRST) }
         | 
| 171 199 | 
             
                Post.loaded.should_not have_key(FIRST)
         | 
| 172 200 | 
             
              end
         | 
| 173 | 
            -
             | 
| 201 | 
            +
             | 
| 202 | 
            +
              it "should move entry from one file to another" do
         | 
| 203 | 
            +
                first = Post.first(:title => 'First')
         | 
| 204 | 
            +
                Post.should_receive(:delete_file).with(FIRST)
         | 
| 205 | 
            +
                Post.should_receive(:save_file).with(PlainRecord.root('file'))
         | 
| 206 | 
            +
                first.file = 'file'
         | 
| 207 | 
            +
                first.save
         | 
| 208 | 
            +
              end
         | 
| 209 | 
            +
             | 
| 210 | 
            +
              it "should move list entry from one file to another" do
         | 
| 211 | 
            +
                Author.should_receive(:save_file).with(INTERN).once
         | 
| 212 | 
            +
                Author.should_receive(:save_file).with(PlainRecord.root('file')).twice
         | 
| 213 | 
            +
                Author.should_receive(:delete_file).with(INTERN).once
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                authors = Author.all(:login => /john|ivan/)
         | 
| 216 | 
            +
                authors.each do |author|
         | 
| 217 | 
            +
                  author.file = 'file'
         | 
| 218 | 
            +
                  author.save
         | 
| 219 | 
            +
                end
         | 
| 220 | 
            +
              end
         | 
| 221 | 
            +
             | 
| 174 222 | 
             
            end
         | 
    
        data/spec/resource_spec.rb
    CHANGED
    
    | @@ -1,27 +1,33 @@ | |
| 1 1 | 
             
            require File.join(File.dirname(__FILE__), 'spec_helper')
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe PlainRecord::Resource do
         | 
| 4 | 
            -
             | 
| 4 | 
            +
             | 
| 5 | 
            +
              after :each do
         | 
| 6 | 
            +
                Post.loaded   = { }
         | 
| 7 | 
            +
                Author.loaded = { }
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 5 10 | 
             
              it "should compare two object" do
         | 
| 6 | 
            -
                first | 
| 7 | 
            -
                 | 
| 8 | 
            -
                second | 
| 9 | 
            -
             | 
| 10 | 
            -
                first.should ==  | 
| 11 | 
            +
                first   = Post.load_file(FIRST)
         | 
| 12 | 
            +
                another = Post.load_file(FIRST)
         | 
| 13 | 
            +
                second  = Post.load_file(SECOND)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                first.should == another
         | 
| 11 16 | 
             
                first.should_not == second
         | 
| 12 17 | 
             
              end
         | 
| 13 | 
            -
             | 
| 18 | 
            +
             | 
| 14 19 | 
             
              it "should remeber it file" do
         | 
| 15 20 | 
             
                Post.load_file(FIRST).file.should == FIRST
         | 
| 21 | 
            +
                Post.load_file(FIRST).path.should == 'data/1/post.md'
         | 
| 16 22 | 
             
              end
         | 
| 17 | 
            -
             | 
| 23 | 
            +
             | 
| 18 24 | 
             
              it "should save entry" do
         | 
| 19 25 | 
             
                file = StringIO.new
         | 
| 20 26 | 
             
                File.should_receive(:open).with(FIRST, 'w').and_yield(file)
         | 
| 21 | 
            -
             | 
| 27 | 
            +
             | 
| 22 28 | 
             
                first = Post.first(:title => 'First')
         | 
| 23 29 | 
             
                first.save
         | 
| 24 | 
            -
             | 
| 30 | 
            +
             | 
| 25 31 | 
             
                file.rewind
         | 
| 26 32 | 
             
                file.read.should == "title: First\n" +
         | 
| 27 33 | 
             
                                    "---\n" +
         | 
| @@ -31,39 +37,76 @@ describe PlainRecord::Resource do | |
| 31 37 | 
             
                                    "---\n" +
         | 
| 32 38 | 
             
                                    "content\n"
         | 
| 33 39 | 
             
              end
         | 
| 34 | 
            -
             | 
| 40 | 
            +
             | 
| 35 41 | 
             
              it "should save list entry" do
         | 
| 36 42 | 
             
                file = StringIO.new
         | 
| 43 | 
            +
                Author.all
         | 
| 37 44 | 
             
                File.should_receive(:open).with(INTERN, 'w').and_yield(file)
         | 
| 38 | 
            -
             | 
| 45 | 
            +
             | 
| 39 46 | 
             
                john = Author.first(:login => 'john')
         | 
| 40 47 | 
             
                john.save
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                file. | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
                                    "  name: Ivan Ivanov\n"
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                file.should has_yaml([
         | 
| 50 | 
            +
                  { 'name' => 'John Smith',  'login' => 'john' },
         | 
| 51 | 
            +
                  { 'name' => 'Ivan Ivanov', 'login' => 'ivan' }
         | 
| 52 | 
            +
                ])
         | 
| 47 53 | 
             
              end
         | 
| 48 | 
            -
             | 
| 54 | 
            +
             | 
| 49 55 | 
             
              it "should delete entry" do
         | 
| 50 56 | 
             
                Post.should_receive(:delete_file).with(FIRST)
         | 
| 51 57 | 
             
                Post.first(:title => 'First').destroy
         | 
| 52 58 | 
             
              end
         | 
| 53 | 
            -
             | 
| 59 | 
            +
             | 
| 60 | 
            +
              it "should save entry without file if model use only one file" do
         | 
| 61 | 
            +
                class Model
         | 
| 62 | 
            +
                  include PlainRecord::Resource
         | 
| 63 | 
            +
                  list_in 'file.yml'
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                path = PlainRecord.root('file.yml')
         | 
| 67 | 
            +
                File.should_receive(:open).with(path, 'w').and_yield(StringIO.new)
         | 
| 68 | 
            +
                Model.new.save
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 54 71 | 
             
              it "should delete list entry" do
         | 
| 55 72 | 
             
                file = StringIO.new
         | 
| 73 | 
            +
                Author.all
         | 
| 56 74 | 
             
                File.should_receive(:open).with(INTERN, 'w').and_yield(file)
         | 
| 57 | 
            -
             | 
| 75 | 
            +
             | 
| 58 76 | 
             
                Author.first(:login => 'john').destroy
         | 
| 59 | 
            -
             | 
| 77 | 
            +
             | 
| 60 78 | 
             
                Author.first(:login => 'john').should be_nil
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                file. | 
| 63 | 
            -
             | 
| 64 | 
            -
                
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                file.should has_yaml([{ 'name' => 'Ivan Ivanov', 'login' => 'ivan' }])
         | 
| 81 | 
            +
             | 
| 65 82 | 
             
                Author.should_receive(:delete_file).with(INTERN)
         | 
| 66 83 | 
             
                Author.first(:login => 'ivan').destroy
         | 
| 67 84 | 
             
              end
         | 
| 68 | 
            -
             | 
| 85 | 
            +
             | 
| 86 | 
            +
              it "should call callbacks" do
         | 
| 87 | 
            +
                class Callbacked
         | 
| 88 | 
            +
                  include PlainRecord::Resource
         | 
| 89 | 
            +
                  entry_in 'data/*/post.md'
         | 
| 90 | 
            +
                  property :title
         | 
| 91 | 
            +
                  text :summary
         | 
| 92 | 
            +
                  text :content
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                callbacks  = mock()
         | 
| 96 | 
            +
                callbacks.should_receive(:path).
         | 
| 97 | 
            +
                  with(Callbacked.path, { :title => 'First' }).and_return('data/1/post.md')
         | 
| 98 | 
            +
                callbacks.should_receive(:load).with(an_instance_of Callbacked)
         | 
| 99 | 
            +
                callbacks.should_receive(:save).with(an_instance_of Callbacked).and_raise
         | 
| 100 | 
            +
                callbacks.should_receive(:destroy).with(an_instance_of Callbacked).and_raise
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                Callbacked.after  :path,    &callbacks.method(:path)
         | 
| 103 | 
            +
                Callbacked.before :load,    &callbacks.method(:load)
         | 
| 104 | 
            +
                Callbacked.before :save,    &callbacks.method(:save)
         | 
| 105 | 
            +
                Callbacked.before :destroy, &callbacks.method(:destroy)
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                first = Callbacked.first({ :title => 'First' })
         | 
| 108 | 
            +
                lambda { first.save }.should raise_error
         | 
| 109 | 
            +
                lambda { first.destroy }.should raise_error
         | 
| 110 | 
            +
              end
         | 
| 111 | 
            +
             | 
| 69 112 | 
             
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | @@ -2,43 +2,62 @@ require File.join(File.dirname(__FILE__), '../lib/plain_record') | |
| 2 2 |  | 
| 3 3 | 
             
            class Post
         | 
| 4 4 | 
             
              include PlainRecord::Resource
         | 
| 5 | 
            -
             | 
| 6 | 
            -
              entry_in 'data/*/post. | 
| 7 | 
            -
             | 
| 5 | 
            +
             | 
| 6 | 
            +
              entry_in 'data/*/post.md'
         | 
| 7 | 
            +
             | 
| 8 8 | 
             
              property :title
         | 
| 9 9 | 
             
              text :summary
         | 
| 10 10 | 
             
              text :content
         | 
| 11 11 | 
             
            end
         | 
| 12 12 |  | 
| 13 | 
            +
            class FilepathPost
         | 
| 14 | 
            +
              include PlainRecord::Resource
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              entry_in 'data/**/*/post.md'
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              virtual :category, in_filepath(1)
         | 
| 19 | 
            +
              virtual :name,     in_filepath(2)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              property :title
         | 
| 22 | 
            +
            end
         | 
| 23 | 
            +
             | 
| 13 24 | 
             
            class Author
         | 
| 14 25 | 
             
              include PlainRecord::Resource
         | 
| 15 | 
            -
             | 
| 26 | 
            +
             | 
| 16 27 | 
             
              list_in 'data/authors/*.yml'
         | 
| 17 | 
            -
             | 
| 28 | 
            +
             | 
| 29 | 
            +
              virtual  :type, in_filepath(1)
         | 
| 18 30 | 
             
              property :login
         | 
| 19 31 | 
             
              property :name
         | 
| 20 32 | 
             
            end
         | 
| 21 33 |  | 
| 22 34 | 
             
            PlainRecord.root = File.dirname(__FILE__)
         | 
| 23 35 |  | 
| 24 | 
            -
            FIRST  = File.join(File.dirname(__FILE__), 'data/1/post. | 
| 25 | 
            -
            SECOND = File.join(File.dirname(__FILE__), 'data/2/post. | 
| 26 | 
            -
            THIRD  = File.join(File.dirname(__FILE__), 'data/3/post. | 
| 27 | 
            -
            FIRST_POST | 
| 36 | 
            +
            FIRST  = File.join(File.dirname(__FILE__), 'data/1/post.md')
         | 
| 37 | 
            +
            SECOND = File.join(File.dirname(__FILE__), 'data/2/post.md')
         | 
| 38 | 
            +
            THIRD  = File.join(File.dirname(__FILE__), 'data/3/post.md')
         | 
| 39 | 
            +
            FIRST_POST  = Post.load_file(FIRST)
         | 
| 28 40 | 
             
            SECOND_POST = Post.load_file(SECOND)
         | 
| 29 | 
            -
            THIRD_POST | 
| 41 | 
            +
            THIRD_POST  = Post.load_file(THIRD)
         | 
| 30 42 |  | 
| 31 43 | 
             
            INTERN = File.join(File.dirname(__FILE__), 'data/authors/intern.yml')
         | 
| 32 44 | 
             
            EXTERN = File.join(File.dirname(__FILE__), 'data/authors/extern.yml')
         | 
| 33 45 |  | 
| 34 46 | 
             
            def model_methods(model)
         | 
| 35 | 
            -
                model.instance_methods - Object.instance_methods -
         | 
| 36 | 
            -
                    PlainRecord::Resource.instance_methods
         | 
| 47 | 
            +
                (model.instance_methods - Object.instance_methods -
         | 
| 48 | 
            +
                    PlainRecord::Resource.instance_methods).map { |i| i.to_s }
         | 
| 37 49 | 
             
            end
         | 
| 38 50 |  | 
| 39 | 
            -
             | 
| 51 | 
            +
            RSpec::Matchers.define :has_methods do |*methods|
         | 
| 40 52 | 
             
              match do |model|
         | 
| 41 | 
            -
                model_methods(model).sort == methods.sort
         | 
| 53 | 
            +
                model_methods(model).sort == methods.map! { |i| i.to_s }.sort
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
            end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            RSpec::Matchers.define :has_yaml do |data|
         | 
| 58 | 
            +
              match do |file|
         | 
| 59 | 
            +
                file.rewind
         | 
| 60 | 
            +
                YAML.load(file.read).should == data
         | 
| 42 61 | 
             
              end
         | 
| 43 62 | 
             
            end
         | 
| 44 63 |  |