first commit
This commit is contained in:
parent
fc71f38dec
commit
6fb6677a1e
51
README.md
51
README.md
@ -1,56 +1,35 @@
|
||||
NAME
|
||||
----
|
||||
mongoid-grid_fs
|
||||
mongoid-sequence
|
||||
|
||||
INSTALL
|
||||
-------
|
||||
gem install mongoid-grid_fs
|
||||
gem install mongoid-sequence
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
|
||||
````ruby
|
||||
|
||||
require 'mongoid-grid_fs'
|
||||
require 'mongoid'
|
||||
require 'mongoid-sequence'
|
||||
|
||||
g = GridFs.put readable
|
||||
|
||||
GridFS.get id
|
||||
class Page
|
||||
include Mongoid::Document
|
||||
include Mongoid::Sequence
|
||||
|
||||
GridFS.delete id
|
||||
sequence :number
|
||||
end
|
||||
|
||||
p Page.create.number #=> 1
|
||||
p Page.create.number #=> 2
|
||||
p Page.create.number #=> 3
|
||||
|
||||
|
||||
````
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
mongoid_grid_fs is a pure mongoid 3 / moped implementation of the mongodb
|
||||
grid_fs specification
|
||||
|
||||
ref: http://www.mongodb.org/display/DOCS/GridFS+Specification
|
||||
|
||||
it has the following features:
|
||||
|
||||
- implementation is on top of mongoid for portability. moped (the driver) is
|
||||
barely used
|
||||
|
||||
- simple, REST-like api
|
||||
|
||||
- support for custom namespaces (fs.files vs. image.files)
|
||||
|
||||
- pathnames and io-like objects can be written to the grid
|
||||
|
||||
- auto-unique pathnames are generated (by default) to avoid collisions using #put
|
||||
|
||||
'path/info/a.rb' -> '$object_id/a.rb'
|
||||
|
||||
- [] and []= methods which allow the grid to be used like a giant file
|
||||
hash in the sky
|
||||
|
||||
- supprt for data_uris
|
||||
|
||||
````erb
|
||||
|
||||
<%= image_tag :src => file.data_uri %>
|
||||
|
||||
````
|
||||
mongoid_sequence is a pure mongoid sequence generator based on mongodb's
|
||||
increment operator
|
||||
|
4
Rakefile
4
Rakefile
@ -1,8 +1,8 @@
|
||||
This.name =
|
||||
"Mongoid::GridFs"
|
||||
"Mongoid::Sequence"
|
||||
|
||||
This.synopsis =
|
||||
"a mongoid 3/moped compatible implementation of the grid_fs specification"
|
||||
"a mongoid 3/moped compatible sequence generator for your models"
|
||||
|
||||
This.rubyforge_project = 'codeforpeople'
|
||||
This.author = "Ara T. Howard"
|
||||
|
125
lib/mongoid-sequence.rb
Normal file
125
lib/mongoid-sequence.rb
Normal file
@ -0,0 +1,125 @@
|
||||
require 'mongoid'
|
||||
|
||||
module Mongoid
|
||||
module Sequence
|
||||
def Sequence.version
|
||||
'1.0.0'
|
||||
end
|
||||
|
||||
ClassMethods = proc do
|
||||
def sequence(fieldname, *args, &block)
|
||||
options = args.extract_options!.to_options!
|
||||
|
||||
sequence_name = (
|
||||
options.delete(:sequence) || sequence_name_for(fieldname)
|
||||
)
|
||||
|
||||
args.push(options)
|
||||
|
||||
before_create do |doc|
|
||||
doc[fieldname] = SequenceGenerator.for(sequence_name).next
|
||||
end
|
||||
|
||||
field(fieldname, *args, &block)
|
||||
|
||||
SequenceGenerator.for(sequence_name)
|
||||
end
|
||||
|
||||
def sequence_for(fieldname)
|
||||
SequenceGenerator.for(sequence_name_for(fieldname))
|
||||
end
|
||||
|
||||
def sequence_name_for(fieldname)
|
||||
SequenceGenerator.sequence_name_for(self, fieldname)
|
||||
end
|
||||
end
|
||||
|
||||
InstanceMethods = proc do
|
||||
def sequence_for(fieldname)
|
||||
self.class.sequence_for(fieldname)
|
||||
end
|
||||
end
|
||||
|
||||
def Sequence.included(other)
|
||||
other.send(:instance_eval, &ClassMethods)
|
||||
other.send(:class_eval, &InstanceMethods)
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
class SequenceGenerator
|
||||
include Mongoid::Document
|
||||
|
||||
field(:name, :type => String)
|
||||
|
||||
field(:value, :default => 0, :type => Integer)
|
||||
|
||||
validates_presence_of(:name)
|
||||
validates_uniqueness_of(:name)
|
||||
|
||||
validates_presence_of(:value)
|
||||
|
||||
index({:name => 1}, {:unique => true})
|
||||
|
||||
Cache = Hash.new
|
||||
|
||||
class << self
|
||||
def for(name)
|
||||
name = name.to_s
|
||||
|
||||
Cache[name] ||= (
|
||||
begin
|
||||
create!(:name => name)
|
||||
rescue
|
||||
where(:name => name).first || create!(:name => name)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
alias_method('[]', 'for')
|
||||
|
||||
def sequence_name_for(klass, fieldname)
|
||||
"#{ klass.name.underscore }-#{ fieldname }"
|
||||
end
|
||||
end
|
||||
|
||||
after_destroy do |sequence|
|
||||
Cache.delete(sequence.name)
|
||||
end
|
||||
|
||||
def next
|
||||
inc(:value, 1)
|
||||
end
|
||||
|
||||
def current_value
|
||||
reload.value
|
||||
end
|
||||
|
||||
def reset!
|
||||
update_attributes!(:value => 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
if $0 == __FILE__
|
||||
|
||||
Mongoid.configure do |config|
|
||||
config.connect_to('mongoid-sequence')
|
||||
end
|
||||
|
||||
class A
|
||||
include Mongoid::Document
|
||||
include Mongoid::Sequence
|
||||
|
||||
p sequence(:number)
|
||||
end
|
||||
|
||||
A.sequence_for(:number).destroy
|
||||
|
||||
a = A.create!
|
||||
p a
|
||||
|
||||
end
|
36
mongoid-sequence.gemspec
Normal file
36
mongoid-sequence.gemspec
Normal file
@ -0,0 +1,36 @@
|
||||
## mongoid-sequence.gemspec
|
||||
#
|
||||
|
||||
Gem::Specification::new do |spec|
|
||||
spec.name = "mongoid-sequence"
|
||||
spec.version = "1.0.0"
|
||||
spec.platform = Gem::Platform::RUBY
|
||||
spec.summary = "mongoid-sequence"
|
||||
spec.description = "a mongoid 3/moped compatible sequence generator for your models"
|
||||
|
||||
spec.files =
|
||||
["README.md",
|
||||
"Rakefile",
|
||||
"lib",
|
||||
"lib/mongoid-sequence.rb",
|
||||
"test",
|
||||
"test/helper.rb",
|
||||
"test/mongoid-sequence.rb",
|
||||
"test/mongoid-sequence_test.rb",
|
||||
"test/testing.rb"]
|
||||
|
||||
spec.executables = []
|
||||
|
||||
spec.require_path = "lib"
|
||||
|
||||
spec.test_files = "test/mongoid-sequence.rb"
|
||||
|
||||
|
||||
|
||||
spec.extensions.push(*[])
|
||||
|
||||
spec.rubyforge_project = "codeforpeople"
|
||||
spec.author = "Ara T. Howard"
|
||||
spec.email = "ara.t.howard@gmail.com"
|
||||
spec.homepage = "https://github.com/ahoward/mongoid-sequence"
|
||||
end
|
@ -1,18 +1,8 @@
|
||||
# -*- encoding : utf-8 -*-
|
||||
require 'pp'
|
||||
require_relative 'testing'
|
||||
require_relative '../lib/mongoid-grid_fs.rb'
|
||||
require_relative '../lib/mongoid-sequence.rb'
|
||||
|
||||
Mongoid.configure do |config|
|
||||
config.connect_to('mongoid-grid_fs_test')
|
||||
end
|
||||
|
||||
require 'stringio'
|
||||
|
||||
class SIO < StringIO
|
||||
attr_accessor :filename
|
||||
|
||||
def initialize(filename, *args, &block)
|
||||
@filename = filename
|
||||
super(*args, &block)
|
||||
end
|
||||
config.connect_to('mongoid-sequence')
|
||||
end
|
||||
|
84
test/mongoid-sequence.rb
Normal file
84
test/mongoid-sequence.rb
Normal file
@ -0,0 +1,84 @@
|
||||
require_relative 'helper'
|
||||
|
||||
Testing Mongoid::Sequence do
|
||||
##
|
||||
#
|
||||
Sequence =
|
||||
Mongoid::Sequence
|
||||
|
||||
SequenceGenerator =
|
||||
Mongoid::SequenceGenerator
|
||||
|
||||
prepare do
|
||||
SequenceGenerator.destroy_all
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
test 'can be included' do
|
||||
assert do
|
||||
model_class do
|
||||
include Mongoid::Sequence
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test 'provided a "sequence" class method that builds a field' do
|
||||
m =
|
||||
assert do
|
||||
model_class do
|
||||
include Mongoid::Sequence
|
||||
|
||||
sequence 'number'
|
||||
end
|
||||
end
|
||||
|
||||
assert{ m.fields['number'].name == 'number' }
|
||||
end
|
||||
|
||||
test 'autoincrements the field on create' do
|
||||
m =
|
||||
assert do
|
||||
model_class do
|
||||
include Mongoid::Sequence
|
||||
|
||||
sequence 'number'
|
||||
end
|
||||
end
|
||||
|
||||
10.times do |i|
|
||||
assert{ m.create.number == i.succ }
|
||||
end
|
||||
end
|
||||
|
||||
test 'allows the sequence to be reset' do
|
||||
m =
|
||||
assert do
|
||||
model_class do
|
||||
include Mongoid::Sequence
|
||||
|
||||
sequence 'number'
|
||||
end
|
||||
end
|
||||
|
||||
assert{ m.sequence_for(:number).reset! }
|
||||
assert{ m.sequence_for(:number).next == 1 }
|
||||
assert{ m.sequence_for(:number).next != 1 }
|
||||
assert{ m.sequence_for(:number).reset! }
|
||||
assert{ m.sequence_for(:number).next == 1 }
|
||||
end
|
||||
|
||||
|
||||
|
||||
protected
|
||||
def model_class(&block)
|
||||
m = Class.new
|
||||
m.class_eval do
|
||||
def m.name() 'm' end
|
||||
include Mongoid::Document
|
||||
end
|
||||
m.destroy_all
|
||||
m.class_eval(&block) if block
|
||||
m
|
||||
end
|
||||
end
|
84
test/mongoid-sequence_test.rb
Normal file
84
test/mongoid-sequence_test.rb
Normal file
@ -0,0 +1,84 @@
|
||||
require_relative 'helper'
|
||||
|
||||
Testing Mongoid::Sequence do
|
||||
##
|
||||
#
|
||||
Sequence =
|
||||
Mongoid::Sequence
|
||||
|
||||
SequenceGenerator =
|
||||
Mongoid::SequenceGenerator
|
||||
|
||||
prepare do
|
||||
SequenceGenerator.destroy_all
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
test 'can be included' do
|
||||
assert do
|
||||
model_class do
|
||||
include Mongoid::Sequence
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test 'provided a "sequence" class method that builds a field' do
|
||||
m =
|
||||
assert do
|
||||
model_class do
|
||||
include Mongoid::Sequence
|
||||
|
||||
sequence 'number'
|
||||
end
|
||||
end
|
||||
|
||||
assert{ m.fields['number'].name == 'number' }
|
||||
end
|
||||
|
||||
test 'autoincrements the field on create' do
|
||||
m =
|
||||
assert do
|
||||
model_class do
|
||||
include Mongoid::Sequence
|
||||
|
||||
sequence 'number'
|
||||
end
|
||||
end
|
||||
|
||||
10.times do |i|
|
||||
assert{ m.create.number == i.succ }
|
||||
end
|
||||
end
|
||||
|
||||
test 'allows the sequence to be reset' do
|
||||
m =
|
||||
assert do
|
||||
model_class do
|
||||
include Mongoid::Sequence
|
||||
|
||||
sequence 'number'
|
||||
end
|
||||
end
|
||||
|
||||
assert{ m.sequence_for(:number).reset! }
|
||||
assert{ m.sequence_for(:number).next == 1 }
|
||||
assert{ m.sequence_for(:number).next != 1 }
|
||||
assert{ m.sequence_for(:number).reset! }
|
||||
assert{ m.sequence_for(:number).next == 1 }
|
||||
end
|
||||
|
||||
|
||||
|
||||
protected
|
||||
def model_class(&block)
|
||||
m = Class.new
|
||||
m.class_eval do
|
||||
def m.name() 'm' end
|
||||
include Mongoid::Document
|
||||
end
|
||||
m.destroy_all
|
||||
m.class_eval(&block) if block
|
||||
m
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user