stone 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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