stone 0.1.0

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.
Files changed (51) hide show
  1. data/History.txt +3 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +50 -0
  4. data/README.txt +52 -0
  5. data/Rakefile +22 -0
  6. data/bin/stone-gen +70 -0
  7. data/config/hoe.rb +70 -0
  8. data/config/requirements.rb +15 -0
  9. data/lib/stone/callbacks.rb +50 -0
  10. data/lib/stone/core_ext/string.rb +9 -0
  11. data/lib/stone/core_ext/symbol.rb +22 -0
  12. data/lib/stone/data_store.rb +80 -0
  13. data/lib/stone/query.rb +44 -0
  14. data/lib/stone/resource.rb +424 -0
  15. data/lib/stone/version.rb +9 -0
  16. data/lib/stone.rb +55 -0
  17. data/log/debug.log +0 -0
  18. data/sandbox_for_specs/datastore/.stone_metadata +2 -0
  19. data/sandbox_for_specs/datastore/authors/1.yml +12 -0
  20. data/sandbox_for_specs/datastore/authors/2.yml +12 -0
  21. data/sandbox_for_specs/datastore/authors/3.yml +12 -0
  22. data/sandbox_for_specs/datastore/authors/4.yml +12 -0
  23. data/sandbox_for_specs/datastore/authors/5.yml +12 -0
  24. data/sandbox_for_specs/datastore/posts/1.yml +8 -0
  25. data/sandbox_for_specs/datastore/posts/2.yml +8 -0
  26. data/sandbox_for_specs/sample_resources/author.rb +24 -0
  27. data/sandbox_for_specs/sample_resources/comment.rb +9 -0
  28. data/sandbox_for_specs/sample_resources/person.rb +6 -0
  29. data/sandbox_for_specs/sample_resources/post.rb +9 -0
  30. data/script/console +10 -0
  31. data/script/destroy +14 -0
  32. data/script/generate +14 -0
  33. data/script/txt2html +74 -0
  34. data/setup.rb +0 -0
  35. data/spec/callbacks_spec.rb +43 -0
  36. data/spec/query_spec.rb +19 -0
  37. data/spec/resource_spec.rb +190 -0
  38. data/spec/spec_helper.rb +7 -0
  39. data/spec/stone_spec.rb +12 -0
  40. data/spec/string_spec.rb +16 -0
  41. data/spec/symbol_spec.rb +16 -0
  42. data/tasks/deployment.rake +34 -0
  43. data/tasks/environment.rake +7 -0
  44. data/tasks/website.rake +17 -0
  45. data/website/images/stone.png +0 -0
  46. data/website/index.html +392 -0
  47. data/website/index.txt +245 -0
  48. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  49. data/website/stylesheets/screen.css +150 -0
  50. data/website/template.html.erb +48 -0
  51. metadata +143 -0
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ == 0.1.0 2008-04-15
2
+
3
+ * Initial release
data/License.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Nick DeMonner
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,50 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ bin/stone-gen
7
+ config/hoe.rb
8
+ config/requirements.rb
9
+ lib/stone.rb
10
+ lib/stone/callbacks.rb
11
+ lib/stone/core_ext/string.rb
12
+ lib/stone/core_ext/symbol.rb
13
+ lib/stone/data_store.rb
14
+ lib/stone/query.rb
15
+ lib/stone/resource.rb
16
+ lib/stone/version.rb
17
+ log/debug.log
18
+ sandbox_for_specs/datastore/.stone_metadata
19
+ sandbox_for_specs/datastore/authors/1.yml
20
+ sandbox_for_specs/datastore/authors/2.yml
21
+ sandbox_for_specs/datastore/authors/3.yml
22
+ sandbox_for_specs/datastore/authors/4.yml
23
+ sandbox_for_specs/datastore/authors/5.yml
24
+ sandbox_for_specs/datastore/posts/1.yml
25
+ sandbox_for_specs/datastore/posts/2.yml
26
+ sandbox_for_specs/sample_resources/author.rb
27
+ sandbox_for_specs/sample_resources/comment.rb
28
+ sandbox_for_specs/sample_resources/person.rb
29
+ sandbox_for_specs/sample_resources/post.rb
30
+ script/console
31
+ script/destroy
32
+ script/generate
33
+ script/txt2html
34
+ setup.rb
35
+ spec/callbacks_spec.rb
36
+ spec/query_spec.rb
37
+ spec/resource_spec.rb
38
+ spec/spec_helper.rb
39
+ spec/stone_spec.rb
40
+ spec/string_spec.rb
41
+ spec/symbol_spec.rb
42
+ tasks/deployment.rake
43
+ tasks/environment.rake
44
+ tasks/website.rake
45
+ website/images/stone.png
46
+ website/index.html
47
+ website/index.txt
48
+ website/javascripts/rounded_corners_lite.inc.js
49
+ website/stylesheets/screen.css
50
+ website/template.html.erb
data/README.txt ADDED
@@ -0,0 +1,52 @@
1
+ = Stone
2
+
3
+ * stone.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ For small applications, a database can be overkill for storing your data in a consistent and
8
+ organized manner. Therefore, Stone was built to provide plug-and-play data persistence for
9
+ any application or framework. It is fast, and it is easy... it is good.
10
+
11
+ == PROBLEMS:
12
+
13
+ * This is the 0.1.0 release so lots and lots of stuff to do.
14
+
15
+ == SYNOPSIS:
16
+
17
+ include Stone::Resource for persistence of any object
18
+
19
+ == REQUIREMENTS:
20
+
21
+ * English
22
+ * Facets
23
+ * Validatable
24
+
25
+ == INSTALL:
26
+
27
+ * sudo gem install stone
28
+
29
+ == LICENSE:
30
+
31
+ (The MIT License)
32
+
33
+ Copyright (c) 2008 Nick DeMonner
34
+
35
+ Permission is hereby granted, free of charge, to any person obtaining
36
+ a copy of this software and associated documentation files (the
37
+ 'Software'), to deal in the Software without restriction, including
38
+ without limitation the rights to use, copy, modify, merge, publish,
39
+ distribute, sublicense, and/or sell copies of the Software, and to
40
+ permit persons to whom the Software is furnished to do so, subject to
41
+ the following conditions:
42
+
43
+ The above copyright notice and this permission notice shall be
44
+ included in all copies or substantial portions of the Software.
45
+
46
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
47
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
49
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
50
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
51
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
52
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+ require "rake"
4
+ require 'fileutils'
5
+ require "rake/clean"
6
+ require "spec/rake/spectask"
7
+ require 'lib/stone'
8
+
9
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
10
+
11
+ Spec::Rake::SpecTask.new('specs') do |t|
12
+ t.spec_opts = ["--format", "specdoc", "--colour"]
13
+ t.spec_files = Dir['spec/**/*_spec.rb'].sort
14
+ end
15
+
16
+ desc "Run specs"
17
+ task :ok do
18
+ Stone.empty_datastore
19
+ FileUtils.rm(Dir.pwd/"sandbox_for_specs"/"stone.sql") \
20
+ if File.exists? Dir.pwd/"sandbox_for_specs"/"stone.sql"
21
+ sh "rake specs"
22
+ end
data/bin/stone-gen ADDED
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fileutils'
4
+ require 'rubygems'
5
+ require 'facets'
6
+
7
+ def usage
8
+ puts <<-EOS
9
+
10
+
11
+ stone-gen model
12
+
13
+
14
+ EOS
15
+ end
16
+
17
+ def model_usage
18
+ puts <<-EOS
19
+
20
+
21
+ stone-gen model ModelName field:type field:type ...
22
+
23
+ e.g. stone-gen model Author name:string street_number:fixnum
24
+
25
+ Works just like all the other model generators out there,
26
+ just remember that Stone only accepts Ruby primitives for
27
+ field types (String, Fixnum, etc).
28
+
29
+
30
+ EOS
31
+ end
32
+
33
+ def gen_model(args)
34
+ model_name = args.first.camelcase
35
+ file_name = model_name.snakecase
36
+ args.shift
37
+ fields = Hash[*(args.map{|a| a.split(":") }.flatten)]
38
+ model_str = "class #{model_name}\n include Stone::Resource\n\n"
39
+ for field in fields
40
+ unless field.last == "datetime"
41
+ model_str << " field :#{field.first}, #{field.last.capitalize}\n"
42
+ else
43
+ model_str << " field :#{field.first}, DateTime\n"
44
+ end
45
+ end
46
+ model_str << "end"
47
+ FileUtils.mkdir(File.join(Dir.pwd, "app/models")) \
48
+ unless File.exists?(File.join(Dir.pwd, "app/models"))
49
+ File.open(File.join(Dir.pwd, "app/models/#{file_name}.rb"), "w") do |file|
50
+ file << model_str
51
+ end
52
+ puts "Model: #{model_name} created."
53
+ end
54
+
55
+ if ARGV.empty?
56
+ usage
57
+ else
58
+ args = ARGV
59
+ case args.first
60
+ when "model"
61
+ args.shift
62
+ if args.empty?
63
+ model_usage
64
+ else
65
+ gen_model(args)
66
+ end
67
+ else
68
+ usage
69
+ end
70
+ end
data/config/hoe.rb ADDED
@@ -0,0 +1,70 @@
1
+ require 'stone/version'
2
+
3
+ AUTHOR = 'Nick DeMonner' # can also be an array of Authors
4
+ EMAIL = "nick@cladby.com"
5
+ DESCRIPTION = "Super-simple data persistence layer created for small applications."
6
+ GEM_NAME = 'stone' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'stone' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+
11
+ @config_file = "~/.rubyforge/user-config.yml"
12
+ @config = nil
13
+ RUBYFORGE_USERNAME = "unknown"
14
+ def rubyforge_username
15
+ unless @config
16
+ begin
17
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
18
+ rescue
19
+ puts <<-EOS
20
+ ERROR: No rubyforge config file found: #{@config_file}
21
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
22
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
23
+ EOS
24
+ exit
25
+ end
26
+ end
27
+ RUBYFORGE_USERNAME.replace @config["username"]
28
+ end
29
+
30
+
31
+ REV = nil
32
+ # UNCOMMENT IF REQUIRED:
33
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
34
+ VERS = Stone::VERSION::STRING + (REV ? ".#{REV}" : "")
35
+ RDOC_OPTS = ['--quiet', '--title', 'stone documentation',
36
+ "--opname", "index.html",
37
+ "--line-numbers",
38
+ "--main", "README",
39
+ "--inline-source"]
40
+
41
+ class Hoe # :nodoc:[all]
42
+ def extra_deps
43
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
44
+ @extra_deps
45
+ end
46
+ end
47
+
48
+ # Generate all the Rake tasks
49
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
50
+ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
51
+ p.developer(AUTHOR, EMAIL)
52
+ p.description = DESCRIPTION
53
+ p.summary = DESCRIPTION
54
+ p.url = HOMEPATH
55
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
56
+ p.test_globs = ["test/**/test_*.rb"]
57
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
58
+
59
+ # == Optional
60
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
61
+ p.extra_deps = [['english', '>= 0.2.0'], ['validatable', '>= 1.6.7'], ['facets', '>= 2.4.1'], ['fastercsv', '>= 1.2.3']]
62
+
63
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
64
+
65
+ end
66
+
67
+ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
68
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
69
+ $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
70
+ $hoe.rsync_args = '-av --delete --ignore-errors'
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
@@ -0,0 +1,50 @@
1
+ module Stone
2
+ class Callbacks < Hash
3
+
4
+ CALLBACKS = [
5
+ :before_save,
6
+ :after_save,
7
+ :before_create,
8
+ :after_create,
9
+ :before_destroy,
10
+ :after_destroy
11
+ ]
12
+
13
+ class << self
14
+
15
+ end # self
16
+
17
+ # Registers the +klass+ with the current instance of Callbacks in Resource
18
+ # === Parameters
19
+ # +klass+:: The class to be registered
20
+ def register_klass(klass)
21
+ self[klass.to_s.make_key] = {}
22
+ CALLBACKS.each do |cb_sym|
23
+ self[klass.to_s.make_key][cb_sym] = []
24
+ end
25
+ end
26
+
27
+ # Adds a given +meth+ to the +cb_sym+ array in the current Callbacks
28
+ # hash based on +klass+
29
+ # === Parameters
30
+ # +cb_sym+:: where +meth+ will be added
31
+ # +meth+:: method to be added
32
+ # +klass+:: determines which +cb_sym+ array will be used
33
+ def register(cb_sym, meth, klass)
34
+ self[klass.to_s.make_key][cb_sym] << meth
35
+ end
36
+
37
+ # Sends any methods registered under +cb_sym+ to +obj+
38
+ # === Parameters
39
+ # +cb_sym+:: Used to retrieve the methods to send
40
+ # +obj+:: The object to which the retrieved methods are sent
41
+ def fire(cb_sym, obj)
42
+ unless obj.class.to_s.make_key == :class
43
+ self[obj.class.to_s.make_key][cb_sym].each do |meth|
44
+ obj.send(meth) unless meth.blank?
45
+ end
46
+ end
47
+ true
48
+ end
49
+ end # Callbacks
50
+ end # Stone
@@ -0,0 +1,9 @@
1
+ class String #:nodoc:
2
+ def /(o)
3
+ File.join(self, o.to_s)
4
+ end
5
+
6
+ def make_key
7
+ self.downcase.to_sym
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ class Symbol
2
+ def gt; Stone::Query.new(self.to_s, :gt); end
3
+ def gte; Stone::Query.new(self.to_s, :gte); end
4
+ def lt; Stone::Query.new(self.to_s, :lt); end
5
+ def lte; Stone::Query.new(self.to_s, :lte); end
6
+
7
+ def includes
8
+ Stone::Query.new(self.to_s, :includes)
9
+ end
10
+
11
+ def matches
12
+ Stone::Query.new(self.to_s, :matches)
13
+ end
14
+
15
+ def equals
16
+ Stone::Query.new(self.to_s, :equals)
17
+ end
18
+
19
+ def not
20
+ Stone::Query.new(self.to_s, :not)
21
+ end
22
+ end
@@ -0,0 +1,80 @@
1
+ module Stone
2
+ # An in-memory representation of the file-based datastore
3
+ class DataStore
4
+
5
+ class << self
6
+ @dir ||= ""
7
+
8
+ def local_dir=(value) #:nodoc:
9
+ @dir = value
10
+ end
11
+
12
+ # Provides the directory path to the local (app-specific) datastore
13
+ def local_dir
14
+ @dir || Dir.pwd/"datastore"
15
+ end
16
+
17
+ # Loads yaml files specific to the resource represented by +sym+
18
+ # === Parameters
19
+ # +sym+::
20
+ # Symbol representing resource data to load
21
+ def load_data(sym)
22
+ dir = self.local_dir
23
+ ymls = Dir.glob(dir/sym.to_s.pluralize/"*.yml")
24
+ objs = []
25
+ unless ymls.empty?
26
+ ymls.each do |yml|
27
+ obj = YAML.load_file yml
28
+ objs << [obj.id, obj]
29
+ end
30
+ end
31
+ return objs
32
+ end
33
+
34
+ # If the object already exists (id was found),
35
+ # this returns +put+(update), else +post+(create)
36
+ # === Parameters
37
+ # +obj+::
38
+ # The instantiated resource to be saved
39
+ # +store+::
40
+ # DataStore object
41
+ def determine_save_method(obj, store)
42
+ store.resources[obj.class.to_s.make_key].each do |o|
43
+ return :put if o[0] == obj.id
44
+ end
45
+ :post
46
+ end
47
+
48
+ # Persist the object via YAML
49
+ # === Parameters
50
+ # +obj+:: The object to be persisted
51
+ def write_yaml(obj)
52
+ path = self.local_dir/obj.class.to_s.downcase.pluralize/"#{obj.id}.yml"
53
+ File.open(path, 'w') do |out|
54
+ YAML.dump(obj, out)
55
+ end
56
+ end
57
+
58
+ # Removes object's yaml file
59
+ # === Parameters
60
+ # +id+:: id of the object to be removed
61
+ # +klass_dir+:: directory in which object resides
62
+ def delete(id, klass_dir)
63
+ raise "Object could not be found" \
64
+ unless File.exists?(self.local_dir/klass_dir/"#{id}.yml")
65
+
66
+ FileUtils.remove_file(self.local_dir/klass_dir/"#{id}.yml")
67
+ true
68
+ end
69
+ end # self
70
+
71
+ def initialize
72
+ @resources = {}
73
+ end
74
+
75
+ def resources
76
+ @resources
77
+ end
78
+
79
+ end # DataStore
80
+ end # Stone
@@ -0,0 +1,44 @@
1
+ module Stone
2
+ # Represents a single query condition
3
+ class Query
4
+
5
+ attr_accessor :field, :op
6
+
7
+ def initialize(field,op)
8
+ self.field = field
9
+ self.op = case op
10
+ when :gt
11
+ ".>"
12
+ when :lt
13
+ ".<"
14
+ when :gte
15
+ ".>="
16
+ when :lte
17
+ ".<="
18
+ when :includes
19
+ ".include?"
20
+ when :matches
21
+ ".=~"
22
+ when :equals
23
+ ".=="
24
+ when :not
25
+ ".!="
26
+ end
27
+ end
28
+
29
+ # Builds an expression from the conditions given during first or all
30
+ # === Parameters
31
+ # +arg+:: Some conditional argument
32
+ def expression_for(arg)
33
+ if arg.is_a? String
34
+ "#{self.field}#{self.op}('#{arg}')"
35
+ elsif arg.is_a? Regexp
36
+ "#{self.field}#{self.op}(#{arg.inspect})"
37
+ elsif arg.is_a? Date
38
+ "#{self.field}#{self.op}(DateTime.parse(\"#{arg}\"))"
39
+ else
40
+ "#{self.field}#{self.op}(#{arg})"
41
+ end
42
+ end
43
+ end
44
+ end