knish 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9cebed317cbe29913edc52b2b410aac9b62033a3
4
+ data.tar.gz: bf914734271075a48d16cd03c9be1342418fd8d6
5
+ SHA512:
6
+ metadata.gz: 644bd7a99649f92ceed6d6cd12dbfe97f60583454ceb947650bf3d5ee736fe219c15cdaac30956109879d08ad0bbd22a54f953d6ecccde60ff6ec8bd6908cf34
7
+ data.tar.gz: 3be97cd34a43e957c176c3faac8670919791ea0a9378e11de2961851a90c0adc18d31602e2b400d3ac09a538e38a045bfddf094591ab7a42b94edbac006ec937
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in knish.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Kane Baccigalupi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Knish
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'knish'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install knish
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( https://github.com/[my-github-username]/knish/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'knish/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "knish"
8
+ spec.version = Knish::VERSION
9
+ spec.authors = ["Kane Baccigalupi"]
10
+ spec.email = ["baccigalupi@gmail.com"]
11
+ spec.summary = %q{File backed data models, excellent for CMS apps!}
12
+ spec.description = %q{The problem with CMSs is that you really want your application content in source control,
13
+ not a database. Knish provides a structured data model for saving data to json, and formatted html to markdown}
14
+ spec.homepage = "http://github.com/baccigalupi/knish"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.6"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "rspec"
25
+ end
@@ -0,0 +1,36 @@
1
+ require 'json'
2
+ require 'forwardable'
3
+ require 'delegate'
4
+ require 'fileutils'
5
+
6
+ require "knish/version"
7
+ require "knish/delegate_inspector"
8
+ require "knish/existing_models"
9
+ require "knish/db_config"
10
+ require "knish/model_config"
11
+ require "knish/writer"
12
+ require "knish/reader"
13
+ require "knish/builder"
14
+ require "knish/model"
15
+ require "knish/collection"
16
+ require "knish/collection_config"
17
+ require "knish/member"
18
+
19
+ module Knish
20
+ def self.clear_config
21
+ @config = nil
22
+ end
23
+
24
+ def self.config
25
+ @config ||= DbConfig.new
26
+ end
27
+
28
+ def self.configure(&block)
29
+ block.call(config)
30
+ end
31
+
32
+ def self.build(path, &block)
33
+ builder = Builder.new(path, &block)
34
+ builder.make_model
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ module Knish
2
+ class Builder
3
+ attr_reader :collection_name, :block
4
+
5
+ def initialize(collection_name, &block)
6
+ @collection_name = collection_name
7
+ @block = block
8
+ end
9
+
10
+ def make_model
11
+ klass = Class.new(Model)
12
+ klass.config = config
13
+ klass.send(:attr_accessor, *config.all_attributes)
14
+ klass.send(:attr_writer, *config.collections)
15
+ add_collections(klass, config.collections)
16
+ klass
17
+ end
18
+
19
+ def add_collections(klass, collections)
20
+ collections.each do |collection|
21
+ klass.class_eval <<-RUBY, __FILE__, __LINE__
22
+ def #{collection}
23
+ @#{collection} ||= Collection.new('#{collection}', config)
24
+ end
25
+ RUBY
26
+ end
27
+ end
28
+
29
+ def config
30
+ model_config = ModelConfig.new(Knish.config.clone, collection_name)
31
+ block.call(model_config)
32
+ model_config
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,41 @@
1
+ module Knish
2
+ class Collection < SimpleDelegator
3
+ attr_reader :name, :config
4
+
5
+ def initialize(name, parent_config)
6
+ super([])
7
+ @name = name
8
+ @config = CollectionConfig.new(parent_config, name)
9
+ end
10
+
11
+ def add(model)
12
+ configure(model)
13
+ push(model)
14
+ end
15
+
16
+ alias :<< :add
17
+
18
+ def save
19
+ each(&:save)
20
+ end
21
+
22
+ def load
23
+ clear
24
+ config.generic_model_configs.each do |c|
25
+ push(
26
+ Member.new(config, c).loaded_model
27
+ )
28
+ end
29
+ self
30
+ end
31
+
32
+ def next_id
33
+ config.next_id + select{|m| !m.persisted? }.size
34
+ end
35
+
36
+ def configure(model)
37
+ model.config = config.member_config(model.config)
38
+ model
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,53 @@
1
+ module Knish
2
+ class CollectionConfig < SimpleDelegator
3
+ attr_accessor :db_config, :path, :model_config, :unpersisted_count
4
+
5
+ def initialize(model_config, path)
6
+ super(model_config.db_config)
7
+ @path = path
8
+ @db_config = model_config.db_config
9
+ @model_config = model_config
10
+ @unpersisted_count = 0
11
+ end
12
+
13
+ def collection_root
14
+ "#{model_config.model_root}/#{path}"
15
+ end
16
+
17
+ def next_id
18
+ ExistingModels.new(collection_root).next_id + unpersisted_count
19
+ end
20
+
21
+ def generic_model_configs
22
+ ExistingModels.new(collection_root).ids.map { |id| member_config(generic_config, id) }
23
+ end
24
+
25
+ def generic_config
26
+ ModelConfig.new(Knish.config, '')
27
+ end
28
+
29
+ def inspect
30
+ DelegateInspector.new(self,
31
+ [:db_config, :model_config, :path]
32
+ ).to_inspect
33
+ end
34
+
35
+ def member_config(original_config, id=nil)
36
+ config = original_config.clone
37
+ config.id = member_id(id)
38
+ config.path = "#{model_config.path}/#{model_config.id}/#{path}"
39
+ config
40
+ end
41
+
42
+ private
43
+
44
+ def member_id(id)
45
+ return id if id
46
+ id = next_id
47
+ self.unpersisted_count += 1
48
+ id
49
+ end
50
+
51
+ end
52
+ end
53
+
@@ -0,0 +1,29 @@
1
+ module Knish
2
+ class DbConfig
3
+ attr_writer :db_directory, :view_to_db_path, :data_filename, :db_name
4
+
5
+ def db_directory
6
+ @db_directory ||= `pwd`.chomp
7
+ end
8
+
9
+ def db_root
10
+ "#{db_directory}/#{db_name}"
11
+ end
12
+
13
+ def db_name
14
+ @db_name ||= 'knish'
15
+ end
16
+
17
+ def view_to_db_path
18
+ @view_to_db_path ||= '/../..'
19
+ end
20
+
21
+ def data_filename
22
+ @data_filename ||= 'data.json'
23
+ end
24
+
25
+ def type_key
26
+ '___type'
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ module Knish
2
+ class DelegateInspector < Struct.new(:object, :attributes)
3
+ def to_inspect
4
+ "#<#{object.class.name}:#{memory_location} #{mapped_attributes.join(' ')}>"
5
+ end
6
+
7
+ def memory_location
8
+ '0x00%x' % (object.object_id << 1)
9
+ end
10
+
11
+ def mapped_attributes
12
+ attributes.map do |attr|
13
+ "@#{attr}=#{object.send(attr).inspect}"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ module Knish
2
+ class ExistingModels < Struct.new(:path)
3
+ def next_id
4
+ (ids.max || 0) + 1
5
+ end
6
+
7
+ def ids
8
+ paths.map{|path| id(path) }.compact
9
+ end
10
+
11
+ def paths
12
+ Dir.glob("#{path}/*")
13
+ end
14
+
15
+ def data
16
+ paths.map { |path|
17
+ Data.new(id(path), path) if id(path)
18
+ }.compact
19
+ end
20
+
21
+ def id(path)
22
+ last = path.split('/').last
23
+ last && last.to_i
24
+ end
25
+
26
+ Data = Struct.new(:id, :path)
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ module Knish
2
+ class Member < Struct.new(:collection_config, :config)
3
+ def model
4
+ return @model if @model
5
+ @model = model_class.new(id: config.id)
6
+ @model.config = collection_config.member_config(@model.config, config.id)
7
+ @model
8
+ end
9
+
10
+ def loaded_model
11
+ model.load
12
+ model
13
+ end
14
+
15
+ def class_name
16
+ data[config.type_key]
17
+ end
18
+
19
+ def model_class
20
+ class_name && eval(class_name)
21
+ end
22
+
23
+ def data
24
+ @data ||= reader.get_json
25
+ end
26
+
27
+ def reader
28
+ Reader.new(config)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,87 @@
1
+ module Knish
2
+ class Model
3
+ if defined?(ActiveModel::Model)
4
+ include ActiveModel::Model
5
+
6
+ def self.model_name
7
+ ActiveModel::Name.new(self, omitted_namespace)
8
+ end
9
+ end
10
+
11
+ attr_writer :config
12
+
13
+ def initialize(attrs=nil)
14
+ attrs ||= {}
15
+ set(attrs)
16
+ end
17
+
18
+ extend Forwardable
19
+
20
+ def_delegators :config, :id, :id=
21
+ def_delegators :reader, :persisted?
22
+
23
+ def save
24
+ writer.save_json(data_attributes)
25
+ writer.save_markdown(markdown_attributes)
26
+ true
27
+ end
28
+
29
+ def load
30
+ set(reader.get_json)
31
+ set(reader.get_markdown)
32
+ true
33
+ end
34
+
35
+ def set(attrs)
36
+ attrs.each do |key, value|
37
+ next if key.to_sym == config.type_key.to_sym
38
+ public_send("#{key}=", value)
39
+ end
40
+ end
41
+
42
+ def template(key)
43
+ reader.template(key)
44
+ end
45
+
46
+ def config
47
+ @config ||= self.class.config.clone
48
+ end
49
+
50
+ class << self
51
+ attr_accessor :config
52
+ end
53
+
54
+ def self.omitted_namespace
55
+ config && config.omitted_namespace
56
+ end
57
+
58
+ private
59
+
60
+ def collections
61
+ config.collections.map {|collection| send(collection) }
62
+ end
63
+
64
+ def data_attributes
65
+ extract_local_attributes(config.data_attributes).merge(___type: self.class.to_s)
66
+ end
67
+
68
+ def markdown_attributes
69
+ extract_local_attributes(config.markdown_attributes)
70
+ end
71
+
72
+ def extract_local_attributes(keys)
73
+ keys.inject({}) do |hash, key|
74
+ hash[key] = public_send(key)
75
+ hash
76
+ end
77
+ end
78
+
79
+ def writer
80
+ @writer ||= Writer.new(config)
81
+ end
82
+
83
+ def reader
84
+ @reader ||= Reader.new(config)
85
+ end
86
+ end
87
+ end