hassox-machinist 0.1.7

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 (3) hide show
  1. data/lib/machinist.rb +88 -0
  2. data/lib/sham.rb +75 -0
  3. metadata +54 -0
data/lib/machinist.rb ADDED
@@ -0,0 +1,88 @@
1
+ require 'active_support'
2
+ require 'sham'
3
+ require File.join(File.dirname(__FILE__), "adapters", "abstract")
4
+
5
+ module Machinist
6
+ # :api: private
7
+ def self.adapters
8
+ @adapters ||= []
9
+ @_adapter_size ||= @adapters.size
10
+ unless @adapters.size == @_adapter_size
11
+ @adapters = @adapters.uniq.sort_by{|a| a.priority}.reverse
12
+ @_adapter_size = @adapters.size
13
+ end
14
+ @adapters
15
+ end
16
+
17
+ # :api: private
18
+ def self.add_adapter(adapter)
19
+ adapters << adapter
20
+ end
21
+
22
+ # :api: private
23
+ def self.adapter_for(klass)
24
+ adapters.detect{|a| a.use_for_class?(klass)} || raise("No Adapter found for #{klass}")
25
+ end
26
+
27
+ module Extensions
28
+ def self.included(base)
29
+ base.extend(ClassMethods)
30
+ end
31
+
32
+ module ClassMethods
33
+ def blueprint(&blueprint)
34
+ @blueprint = blueprint
35
+ @machinist_adapter = Machinist.adapter_for(self)
36
+ end
37
+
38
+ def make(attributes = {}, &block)
39
+ obj = make_unsaved(attributes.merge(:_save_ => true), &block)
40
+ @machinist_adapter.save(obj)
41
+ end
42
+
43
+ def make_unsaved(attributes = {})
44
+ raise "No blueprint for class #{self}" if @blueprint.nil?
45
+ lathe = Lathe.new(self, attributes)
46
+ lathe.instance_eval(&@blueprint)
47
+ returning(lathe.object) do |object|
48
+ yield object if block_given?
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ class Lathe
55
+ def initialize(klass, attributes = {})
56
+ @save = !!attributes.delete(:_save_)
57
+ @object = klass.new
58
+ attributes.each {|key, value| @object.send("#{key}=", value) }
59
+ @assigned_attributes = attributes.keys.map(&:to_sym)
60
+ end
61
+
62
+ # Undef a couple of methods that are common ActiveRecord attributes.
63
+ # (Both of these are deprecated in Ruby 1.8 anyway.)
64
+ undef_method :id
65
+ undef_method :type
66
+
67
+ attr_reader :object
68
+
69
+ def method_missing(symbol, *args, &block)
70
+ if @assigned_attributes.include?(symbol)
71
+ @object.send(symbol)
72
+ else
73
+ value = if block
74
+ block.call
75
+ elsif args.first.is_a?(Hash) || args.empty?
76
+ meth = @save ? :make : :make_unsaved
77
+ symbol.to_s.camelize.constantize.send(meth, (args.first || {}))
78
+ else
79
+ args.first
80
+ end
81
+ @object.send("#{symbol}=", value)
82
+ @assigned_attributes << symbol
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ require File.join(File.dirname(__FILE__), 'adapters/active_record') if defined?(ActiveRecord)
data/lib/sham.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'active_support'
2
+
3
+ class Sham
4
+ @@shams = {}
5
+
6
+ # Over-ride module's built-in name method, so we can re-use it for
7
+ # generating names. This is a bit of a no-no, but we get away with
8
+ # it in this context.
9
+ def self.name(*args, &block)
10
+ method_missing(:name, *args, &block)
11
+ end
12
+
13
+ def self.method_missing(symbol, *args, &block)
14
+ if block_given?
15
+ @@shams[symbol] = Sham.new(symbol, args.pop || {}, &block)
16
+ else
17
+ sham = @@shams[symbol]
18
+ raise "No sham defined for #{symbol}" if sham.nil?
19
+ sham.fetch_value
20
+ end
21
+ end
22
+
23
+ def self.reset
24
+ @@shams.values.each(&:reset)
25
+ end
26
+
27
+ def self.define(&block)
28
+ definer = Object.new
29
+ class << definer
30
+ def method_missing(*args, &block)
31
+ Sham.send(*args, &block)
32
+ end
33
+ end
34
+ definer.instance_eval(&block)
35
+ end
36
+
37
+ def initialize(name, options = {}, &block)
38
+ @name = name
39
+ @generator = block
40
+ @offset = 0
41
+ @unique = options.has_key?(:unique) ? options[:unique] : true
42
+ generate_values(12)
43
+ end
44
+
45
+ def reset
46
+ @offset = 0
47
+ end
48
+
49
+ def fetch_value
50
+ # Generate more values if we need them.
51
+ if @offset >= @values.length
52
+ generate_values(2 * @values.length)
53
+ raise "Can't generate more unique values for Sham.#{@name}" if @offset >= @values.length
54
+ end
55
+ returning @values[@offset] do
56
+ @offset += 1
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def generate_values(count)
63
+ @values = seeded { (1..count).map(&@generator) }
64
+ @values.uniq! if @unique
65
+ end
66
+
67
+ def seeded
68
+ begin
69
+ srand(1)
70
+ yield
71
+ ensure
72
+ srand
73
+ end
74
+ end
75
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hassox-machinist
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.7
5
+ platform: ruby
6
+ authors:
7
+ - Pete Yandell
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-22 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: pete@nothat.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/machinist.rb
26
+ - lib/sham.rb
27
+ has_rdoc: false
28
+ homepage: http://github.com/notahat/machinist
29
+ post_install_message:
30
+ rdoc_options: []
31
+
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: "0"
39
+ version:
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ requirements: []
47
+
48
+ rubyforge_project:
49
+ rubygems_version: 1.2.0
50
+ signing_key:
51
+ specification_version: 2
52
+ summary: Fixtures aren't fun. Machinist is.
53
+ test_files: []
54
+