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/script/txt2html ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ begin
5
+ require 'newgem'
6
+ rescue LoadError
7
+ puts "\n\nGenerating the website requires the newgem RubyGem"
8
+ puts "Install: gem install newgem\n\n"
9
+ exit(1)
10
+ end
11
+ require 'redcloth'
12
+ require 'syntax/convertors/html'
13
+ require 'erb'
14
+ require File.dirname(__FILE__) + '/../lib/stone/version.rb'
15
+
16
+ version = Stone::VERSION::STRING
17
+ download = 'http://rubyforge.org/projects/stone'
18
+
19
+ class Fixnum
20
+ def ordinal
21
+ # teens
22
+ return 'th' if (10..19).include?(self % 100)
23
+ # others
24
+ case self % 10
25
+ when 1: return 'st'
26
+ when 2: return 'nd'
27
+ when 3: return 'rd'
28
+ else return 'th'
29
+ end
30
+ end
31
+ end
32
+
33
+ class Time
34
+ def pretty
35
+ return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
36
+ end
37
+ end
38
+
39
+ def convert_syntax(syntax, source)
40
+ return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
41
+ end
42
+
43
+ if ARGV.length >= 1
44
+ src, template = ARGV
45
+ template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb')
46
+
47
+ else
48
+ puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html")
49
+ exit!
50
+ end
51
+
52
+ template = ERB.new(File.open(template).read)
53
+
54
+ title = nil
55
+ body = nil
56
+ File.open(src) do |fsrc|
57
+ title_text = fsrc.readline
58
+ body_text = fsrc.read
59
+ syntax_items = []
60
+ body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
61
+ ident = syntax_items.length
62
+ element, syntax, source = $1, $2, $3
63
+ syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
64
+ "syntax-temp-#{ident}"
65
+ }
66
+ title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
67
+ body = RedCloth.new(body_text).to_html
68
+ body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
69
+ end
70
+ stat = File.stat(src)
71
+ created = stat.ctime
72
+ modified = stat.mtime
73
+
74
+ $stdout << template.result(binding)
data/setup.rb ADDED
File without changes
@@ -0,0 +1,43 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe Stone::Callbacks do
4
+ before(:all) do
5
+ get_resources
6
+ Stone.start(STONE_ROOT/"sandbox_for_specs", @resources)
7
+
8
+ class Dude
9
+ include Stone::Resource
10
+
11
+ def raise_hell
12
+ raise "Zomgz!"
13
+ end
14
+ end
15
+ end
16
+
17
+ before(:each) do
18
+ @c = Stone::Callbacks.new
19
+ end
20
+
21
+ it "should register a class for callbacks" do
22
+ @c.register_klass(Dude)
23
+ @c.include?(:dude).should be_true
24
+ @c[:dude].include?(:before_save).should be_true
25
+ end
26
+
27
+ it "should register a method to execute for a given callback" do
28
+ @c.register_klass(Dude)
29
+ @c.register(:before_save, :raise_hell, Dude)
30
+ @c[:dude][:before_save].include?(:raise_hell).should be_true
31
+ end
32
+
33
+ it "should fire the correct method when a callback is executed" do
34
+ # had to define say_hello to raise an error because fire() always
35
+ # returns true
36
+
37
+ @c.register_klass(Dude)
38
+ @c.register(:before_save, :raise_hell, Dude)
39
+
40
+ # raises "Zomgz!"
41
+ Dude.class_eval {fire(:before_save)}.should raise_error
42
+ end
43
+ end
@@ -0,0 +1,19 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe Stone::Query do
4
+ before(:all) do
5
+ get_resources
6
+ Stone.start(STONE_ROOT/"sandbox_for_specs", @resources)
7
+ end
8
+
9
+ it "should craft a correct Query when initialized" do
10
+ q = Stone::Query.new("email", :lt)
11
+ q.field.should == "email"
12
+ q.op.should == ".<"
13
+ end
14
+
15
+ it "should craft a proper expression for a given argument" do
16
+ q = Stone::Query.new("email", :not)
17
+ q.expression_for("nick@cladby.com").should == "email.!=('nick@cladby.com')"
18
+ end
19
+ end
@@ -0,0 +1,190 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe Stone::Resource do
4
+
5
+ before(:all) do
6
+ get_resources
7
+ Stone.start(STONE_ROOT/"sandbox_for_specs", @resources)
8
+ end
9
+
10
+ before(:each) do
11
+ @author = Author.new
12
+ end
13
+
14
+ it "should extend any class in which it is included" do
15
+ class Blah #:nodoc:
16
+ include Stone::Resource
17
+ end
18
+ Blah.new.respond_to?(:field).should be_true
19
+ end
20
+
21
+ it "should be valid when validates_ methods are fulfilled" do
22
+ @author.name = "Nick DeMonner"
23
+ @author.email = "nick@cladby.com"
24
+ @author.should be_valid
25
+ end
26
+
27
+ it "should be invalid when validates_ methods are not fulfilled" do
28
+ @author.name = "Nick DeMonner"
29
+ @author.should_not be_valid
30
+ end
31
+
32
+ it "should be invalid when a field's class does not match its declaration" do
33
+ @author.name = 3
34
+ @author.email = "nick@cladby.com"
35
+ @author.save.should_not be_true
36
+ end
37
+
38
+ it "should create a yaml file for each saved object" do
39
+ @author.name = "Nick DeMonner"
40
+ @author.email = "nick@cladby.com"
41
+ @author.save
42
+ File.exists?(Stone::DataStore.local_dir/"authors"/"1.yml").should be_true
43
+ end
44
+
45
+ it "should create an object whose id is last object.id + 1" do
46
+ @author.id.should == 2
47
+ end
48
+
49
+ it "should not save unless all validations pass" do
50
+ @author.name = "Heyo McGee"
51
+ @author.save.should_not be_true
52
+ end
53
+
54
+ it "should find and return an object using get" do
55
+ @author.name = "Mike McMichaels"
56
+ @author.email = "heyo@something.com"
57
+ @author.save
58
+ person = Author.get(@author.id)
59
+ person.name.should == "Mike McMichaels"
60
+ end
61
+
62
+ it "should find and return an object using []" do
63
+ @author.name = "Mary Poppins"
64
+ @author.email = "weyo@something.com"
65
+ @author.save
66
+ person = Author[@author.id]
67
+ person.name.should == "Mary Poppins"
68
+ end
69
+
70
+ it "should accept Resource.find(hash) form" do
71
+ author = Author.first(:name => "Nick DeMonner")
72
+ author.should be_instance_of(Author)
73
+ end
74
+
75
+ it "should accept be able to find an object using a regex" do
76
+ author = Author.first(:name.matches => /nick/i)
77
+ author.should be_instance_of(Author)
78
+ end
79
+
80
+ it "should raise an exception anything other than a Hash is provided for find" do
81
+ lambda {Author.first("Nick")}.should raise_error
82
+ end
83
+
84
+ it "should find and return all objects that match conditions provided" do
85
+ @author.name = "Nick Hicklesby"
86
+ @author.email = "nick@gmail.com"
87
+ @author.save
88
+ people = Author.all(:name.includes => "Nick")
89
+ people.size.should == 2
90
+ end
91
+
92
+ it "should find and return the first object that matches conditions provided" do
93
+ person = Author.first(:name.equals => 'Nick DeMonner')
94
+ person.id.should == 1
95
+ end
96
+
97
+ it "should let .first and .all work with fields that aren't Strings" do
98
+ @author.name = "Higglesby Wordsworth"
99
+ @author.email = "higglebear@higgly.com"
100
+ @author.favorite_number = 3
101
+ @author.save
102
+ Author.first(:favorite_number.equals => 3).should be_instance_of(Author)
103
+ end
104
+
105
+ it "should perform a put if the object already exists on save" do
106
+ author = Author.first(:name.equals => 'Nick DeMonner')
107
+ author.email = "nick@bzzybee.com"
108
+ author.save
109
+ Author.get(author.id).email.should == "nick@bzzybee.com"
110
+ end
111
+
112
+ it "should delete an object and it's yaml file upon Resource.delete" do
113
+ author = Author.first(:favorite_number.equals => 3)
114
+ Author.delete(author.id).should be_true
115
+ end
116
+
117
+ it "should execute Resource callbacks" do
118
+ @author.name = "ben hurr"
119
+ @author.email = "chariot_guy@hotmail.com"
120
+ @author.save
121
+ @author.name.should == "Ben Hurr"
122
+ end
123
+
124
+ it "should not save if there is a duplicate and the field is unique" do
125
+ @author.name = "John Doe"
126
+ @author.email = "nick@bzzybee.com"
127
+ @author.save.should_not be_true
128
+ end
129
+
130
+ it "should retrieve a parent object if belongs_to has been set" do
131
+ @post = Post.new
132
+ @post.title = "Stone is Cool"
133
+ @post.body = "Stone is cool because..."
134
+ author = Author.first(:name.equals => 'Nick DeMonner')
135
+ @post.author_id = author.id
136
+ @post.save
137
+ @post.author.should be_instance_of(Author)
138
+ end
139
+
140
+ it "should retrieve children objects id has_many has been set" do
141
+ @post = Post.new
142
+ @post.title = "Stone is Awesome"
143
+ @post.body = "Stone is awesome because..."
144
+ author = Author.first(:name.equals => 'Nick DeMonner')
145
+ @post.author_id = author.id
146
+ @post.save
147
+ author.posts.size.should == 2
148
+ end
149
+
150
+ it "should accept Resource.new(hash) form" do
151
+ @author = Author.new(:name => "Ron DeMonner", :email => "ron@cladby.com")
152
+ @author.should be_valid
153
+ end
154
+
155
+ it "should accept Resource.new(params[:resource]) form" do
156
+ params = {}
157
+ params[:author] = {:name => "Ron DeMonner", :email => "ron@cladby.com"}
158
+ @author = Author.new(params[:author])
159
+ @author.should be_valid
160
+ end
161
+
162
+ it "should accept Resource.update_attributes(hash)" do
163
+ params = {}
164
+ params[:author] = {:name => "Ron DeMonner", :email => "ron@cladby.com"}
165
+
166
+ plain_hash = {:name => "Nick DeMonner", :email => "nick@cladby.com"}
167
+
168
+ author = Author.first(:name => "Nick DeMonner")
169
+ author.update_attributes(params[:author]).should be_true
170
+ author.update_attributes(plain_hash).should be_true
171
+ end
172
+
173
+ it "should allow an attribute to accessed via obj[attribute]" do
174
+ author = Author.first(:name => "Nick DeMonner")
175
+ author[:id].should == 1
176
+ end
177
+
178
+ it "should allow for DateTime queries" do
179
+ # bring back all authors who were created before a month from now
180
+ # i.e., bring all of them back
181
+ authors = Author.all(:created_at.lt => DateTime.now>>1)
182
+ authors.size.should == 5
183
+ end
184
+
185
+ it "should allow for complex queries" do
186
+ authors = Author.all(:name.matches => /o/, :created_at.lt => DateTime.now>>1)
187
+ authors.size.should == 2
188
+ end
189
+
190
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'lib/stone'
4
+
5
+ def get_resources
6
+ @resources = Dir.glob(STONE_ROOT/"sandbox_for_specs"/"sample_resources/*")
7
+ end
@@ -0,0 +1,12 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe Stone do
4
+ before(:all) do
5
+ get_resources
6
+ Stone.start(STONE_ROOT/"sandbox_for_specs", @resources)
7
+ end
8
+
9
+ it "should create a new, blank datastore at a given path" do
10
+ File.exists?(STONE_ROOT/"sandbox_for_specs"/"datastore").should be_true
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe String do
4
+ before(:all) do
5
+ get_resources
6
+ Stone.start(STONE_ROOT/"sandbox_for_specs", @resources)
7
+ end
8
+
9
+ it "should correctly form paths using /" do
10
+ ("this"/"should"/"work").should == "this/should/work"
11
+ end
12
+
13
+ it "should make a proper key given a stringified class" do
14
+ String.to_s.make_key.should == :string
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe Symbol do
4
+ before(:all) do
5
+ get_resources
6
+ Stone.start(STONE_ROOT/"sandbox_for_specs", @resources)
7
+ end
8
+
9
+ it "should return a correct Query when a comparison method is used" do
10
+ :name.gt.should be_instance_of(Stone::Query)
11
+ :name.gt.op.should == ".>"
12
+
13
+ :name.matches.should be_instance_of(Stone::Query)
14
+ :name.matches.op.should == ".=~"
15
+ end
16
+ end
@@ -0,0 +1,34 @@
1
+ desc 'Release the website and new gem version'
2
+ task :deploy => [:check_version, :website, :release] do
3
+ puts "Remember to create SVN tag:"
4
+ puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
5
+ "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
6
+ puts "Suggested comment:"
7
+ puts "Tagging release #{CHANGES}"
8
+ end
9
+
10
+ desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
11
+ task :local_deploy => [:website_generate, :install_gem]
12
+
13
+ task :check_version do
14
+ unless ENV['VERSION']
15
+ puts 'Must pass a VERSION=x.y.z release version'
16
+ exit
17
+ end
18
+ unless ENV['VERSION'] == VERS
19
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
20
+ exit
21
+ end
22
+ end
23
+
24
+ desc 'Install the package as a gem, without generating documentation(ri/rdoc)'
25
+ task :install_gem_no_doc => [:clean, :package] do
26
+ sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri"
27
+ end
28
+
29
+ namespace :manifest do
30
+ desc 'Recreate Manifest.txt to include ALL files'
31
+ task :refresh do
32
+ `rake check_manifest | patch -p0 > Manifest.txt`
33
+ end
34
+ end
@@ -0,0 +1,7 @@
1
+ task :ruby_env do
2
+ RUBY_APP = if RUBY_PLATFORM =~ /java/
3
+ "jruby"
4
+ else
5
+ "ruby"
6
+ end unless defined? RUBY_APP
7
+ end
@@ -0,0 +1,17 @@
1
+ desc 'Generate website files'
2
+ task :website_generate => :ruby_env do
3
+ (Dir['website/**/*.txt'] - Dir['website/version*.txt']).each do |txt|
4
+ sh %{ #{RUBY_APP} script/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
5
+ end
6
+ end
7
+
8
+ desc 'Upload website files to rubyforge'
9
+ task :website_upload do
10
+ host = "#{rubyforge_username}@rubyforge.org"
11
+ remote_dir = "/var/www/gforge-projects/#{PATH}/"
12
+ local_dir = 'website'
13
+ sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
14
+ end
15
+
16
+ desc 'Generate and upload website files'
17
+ task :website => [:website_generate, :website_upload, :publish_docs]
Binary file