Module: PlainRecord::Filepath

Included in:
Model
Defined in:
lib/plain_record/filepath.rb

Overview

Extention to get properties from enrty file path. For example, your blog post may stored in name/post.md, and post model will have name property. Also if you set name property to Model#first or Model#all method, they will load entry directly only by it file.

To define filepath property:

  1. Use * or ** pattern in model path in enrty_in or list_in.

  2. In virtual method use in_filepath(i) definer after name with * or ** number (start from 1).

Define filepath property only after entry_in or list_in call.

class Post
  include PlainRecord::Resource

  entry_in '*/*/post.md'

  virtual :category, in_filepath(1)
  virtual :name,     in_filepath(1)
  
end

superpost = Post.new
superpost.name = 'superpost'
superpost.category = 'best/'
superpost.save               # Save to best/superpost/post.md

bests = Post.all(category: 'best') # Look up only in best/ dir

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Attribute Details

#filepath_propertiesObject

Returns the value of attribute filepath_properties.



51
52
53
# File 'lib/plain_record/filepath.rb', line 51

def filepath_properties
  @filepath_properties
end

#filepath_regexpObject

Returns the value of attribute filepath_regexp.



52
53
54
# File 'lib/plain_record/filepath.rb', line 52

def filepath_regexp
  @filepath_regexp
end

Class Method Details

.define_property(klass, name, number) ⇒ Object

Define in klass filepath property with name for number * or ** pattern in path.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/plain_record/filepath.rb', line 123

def define_property(klass, name, number)
  unless klass.filepath_properties
    install(klass)
  end

  klass.filepath_properties[number] = name

  klass.class_eval <<-EOS, __FILE__, __LINE__
    def #{name}
      @filepath_data[:#{name}]
    end
    def #{name}=(value)
      @filepath_data[:#{name}] = value
    end
  EOS
end

.install(klass) ⇒ Object

Define class variables and events in klass. It should be call once on same class after entry_in or list_in call.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/plain_record/filepath.rb', line 72

def install(klass)
  klass.filepath_properties = { }

  path = Regexp.escape(klass.path).gsub(/\\\*\\\*(\/|$)/, '(.*)').
                                   gsub('\\*', '([^/]+)')
  klass.filepath_regexp = Regexp.new(path)

  klass.class_eval do
    attr_accessor :filepath_data
  end

  klass.after :load do |result, entry|
    if entry.path
      data = klass.filepath_regexp.match(entry.path)
      entry.filepath_data = { }
      klass.filepath_properties.each_pair do |number, name|
        entry.filepath_data[name] = data[number]
      end
    else
      entry.filepath_data = { }
      klass.filepath_properties.each_value do |name|
        entry.filepath_data[name] = entry.data[name]
        entry.data.delete(name)
      end
    end
    result
  end

  klass.after :path do |path, matchers|
    i = 0
    path.gsub /(\*\*(\/|$)|\*)/ do |pattern|
      i += 1
      property = klass.filepath_properties[i]
      unless matchers[property].is_a? Regexp or matchers[property].nil?
        matchers[property]
      else
        pattern
      end
    end
  end

  klass.before :save do |entry|
    unless entry.file
      path = klass.path(entry.filepath_data)
      entry.file = path unless path =~ /[\*\[\?\{]/
    end
  end
end