├── lib ├── dm-machinist.rb ├── dm-machinist │ └── version.rb └── machinist │ ├── data_mapper.rb │ └── data_mapper │ ├── lathe.rb │ └── blueprint.rb ├── Gemfile ├── Readme.md ├── spec ├── spec_helper.rb ├── support │ └── data_mapper_environment.rb └── data_mapper_spec.rb ├── .gitignore ├── Rakefile └── dm-machinist.gemspec /lib/dm-machinist.rb: -------------------------------------------------------------------------------- 1 | require 'dm-machinist/version' 2 | require 'machinist/data_mapper' 3 | -------------------------------------------------------------------------------- /lib/dm-machinist/version.rb: -------------------------------------------------------------------------------- 1 | module Dm 2 | module Machinist 3 | VERSION = "0.0.1" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'http://rubygems.org' 2 | 3 | # Specify your gem's dependencies in dm-machinist.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # dm-machinist 2 | 3 | dm-machinist is a datamapper adapter for machinist 2.0 4 | 5 | usage: include this in your Gemfile 6 | 7 | gem 'dm-machinist' 8 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib' 2 | $LOAD_PATH.unshift File.dirname(__FILE__) 3 | 4 | require 'rubygems' 5 | require 'test/unit' 6 | require 'rspec' 7 | require 'dm-machinist' 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .rvmrc 4 | .bundle 5 | .config 6 | .yardoc 7 | Gemfile.lock 8 | InstalledFiles 9 | _yardoc 10 | coverage 11 | doc/ 12 | lib/bundler/man 13 | pkg 14 | rdoc 15 | spec/reports 16 | test/tmp 17 | test/version_tmp 18 | tmp 19 | -------------------------------------------------------------------------------- /lib/machinist/data_mapper.rb: -------------------------------------------------------------------------------- 1 | require 'dm-core' 2 | require 'dm-transactions' 3 | require 'machinist' 4 | require 'machinist/data_mapper/blueprint' 5 | require 'machinist/data_mapper/lathe' 6 | 7 | module Machinist::DataMapperExtensions 8 | def blueprint_class 9 | Machinist::DataMapper::Blueprint 10 | end 11 | end 12 | 13 | DataMapper::Model.append_extensions(Machinist::Machinable) 14 | DataMapper::Model.append_extensions(Machinist::DataMapperExtensions) 15 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler' 3 | Bundler::GemHelper.install_tasks 4 | 5 | require 'rake' 6 | require 'rspec/core/rake_task' 7 | require 'rdoc/task' 8 | 9 | 10 | RSpec::Core::RakeTask.new 11 | 12 | RSpec::Core::RakeTask.new(:rcov) do |spec| 13 | spec.rcov = true 14 | spec.rcov_opts = ['--exclude', 'spec', '--exclude', '.rvm'] 15 | end 16 | 17 | desc 'Run the specs.' 18 | task :default => :rcov 19 | 20 | 21 | RDoc::Task.new(:rdoc) do |rdoc| 22 | rdoc.rdoc_dir = 'doc' 23 | rdoc.title = 'Machinist' 24 | rdoc.options << '--line-numbers' 25 | rdoc.rdoc_files.include('lib') 26 | end 27 | 28 | task :notes do 29 | system "grep -n -r 'FIXME\\|TODO' lib spec" 30 | end 31 | -------------------------------------------------------------------------------- /lib/machinist/data_mapper/lathe.rb: -------------------------------------------------------------------------------- 1 | module Machinist::DataMapper 2 | 3 | class Lathe < Machinist::Lathe 4 | 5 | def make_one_value(attribute, args) #:nodoc: 6 | if block_given? 7 | raise_argument_error(attribute) unless args.empty? 8 | yield 9 | else 10 | make_association(attribute, args) 11 | end 12 | end 13 | 14 | def make_association(attribute, args) #:nodoc: 15 | association = @klass.relationships[attribute] 16 | if association 17 | if association.is_a?(DataMapper::Associations::ManyToOne::Relationship) 18 | association.parent_model.make(*args) 19 | else 20 | association.child_model.make(*args) 21 | end 22 | else 23 | raise_argument_error(attribute) 24 | end 25 | end 26 | 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/machinist/data_mapper/blueprint.rb: -------------------------------------------------------------------------------- 1 | module Machinist::DataMapper 2 | class Blueprint < Machinist::Blueprint 3 | 4 | # Make and save an object. 5 | def make!(attributes = {}) 6 | object = make(attributes) 7 | object.raise_on_save_failure = true 8 | object.save 9 | object.reload 10 | end 11 | 12 | # Box an object for storage in the warehouse. 13 | def box(object) 14 | object.key 15 | end 16 | 17 | # Unbox an object from the warehouse. 18 | def unbox(id) 19 | @klass.find(id) 20 | end 21 | 22 | # Execute a block on a separate database connection, so that any database 23 | # operations happen outside any open transactions. 24 | def outside_transaction 25 | # ActiveRecord manages connections per-thread, so the only way to 26 | # convince it to open another connection is to start another thread. 27 | thread = Thread.new do 28 | begin 29 | yield 30 | end 31 | end 32 | thread.value 33 | end 34 | 35 | def lathe_class #:nodoc: 36 | Machinist::DataMapper::Lathe 37 | end 38 | 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/support/data_mapper_environment.rb: -------------------------------------------------------------------------------- 1 | require 'datamapper' 2 | 3 | DataMapper.setup(:default, 'sqlite::memory:') 4 | 5 | module DataMapperModels 6 | class User 7 | include DataMapper::Resource 8 | property :username, String, :key => true 9 | validates_presence_of :username 10 | validates_uniqueness_of :username 11 | end 12 | 13 | class Post 14 | include DataMapper::Resource 15 | property :id, Serial 16 | property :title, String, :required => false 17 | property :body, Text, :required => false 18 | 19 | has n, :comments 20 | belongs_to :author, :model => User, :required => false 21 | has n, :tags, :through => Resource 22 | end 23 | 24 | class Comment 25 | include DataMapper::Resource 26 | property :id, Serial 27 | property :body, Text, :required => false 28 | belongs_to :post, :required => false 29 | end 30 | 31 | class Tag 32 | include DataMapper::Resource 33 | property :id, Serial 34 | property :name, Text, :required => false 35 | has n, :posts, :through => Resource, :required => false 36 | end 37 | 38 | 39 | module DataMapperEnvironment 40 | 41 | def empty_database! 42 | [User, Post, Comment].each do |klass| 43 | klass.all.destroy 44 | klass.clear_blueprints! 45 | end 46 | end 47 | 48 | end 49 | end 50 | 51 | DataMapper.auto_migrate! 52 | -------------------------------------------------------------------------------- /dm-machinist.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | require File.expand_path('../lib/dm-machinist/version', __FILE__) 3 | 4 | Gem::Specification.new do |gem| 5 | gem.authors = ["Josep Jaume"] 6 | gem.email = ["josepjaume@gmail.com"] 7 | gem.description = %q{dm-machinist is a datamapper adapter for machinist 2.0} 8 | gem.summary = %q{dm-machinist is a datamapper adapter for machinist 2.0} 9 | gem.homepage = 'http://github.com/codegram/dm-machinist' 10 | 11 | gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 12 | gem.files = `git ls-files`.split("\n") 13 | gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 14 | gem.name = "dm-machinist" 15 | gem.require_paths = ['lib'] 16 | gem.version = Dm::Machinist::VERSION 17 | 18 | gem.add_development_dependency "sqlite3" 19 | gem.add_development_dependency "activesupport" 20 | gem.add_development_dependency "i18n" 21 | gem.add_development_dependency "rake" 22 | gem.add_development_dependency "rcov" 23 | gem.add_development_dependency "rspec" 24 | gem.add_development_dependency "rdoc" 25 | gem.add_development_dependency "datamapper" 26 | gem.add_development_dependency "dm-sqlite-adapter" 27 | 28 | gem.add_runtime_dependency "machinist", ">= 2.0.0.beta2" 29 | gem.add_runtime_dependency "dm-core", ">= 1.1.0" 30 | gem.add_runtime_dependency "dm-transactions", ">= 1.1.0" 31 | end 32 | -------------------------------------------------------------------------------- /spec/data_mapper_spec.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/spec_helper' 2 | require 'support/data_mapper_environment' 3 | 4 | module DataMapperModels 5 | describe Machinist::DataMapper do 6 | include DataMapperEnvironment 7 | 8 | before(:each) do 9 | empty_database! 10 | end 11 | 12 | context "make" do 13 | it "returns an unsaved object" do 14 | Post.blueprint { } 15 | post = Post.make 16 | post.should be_a(Post) 17 | post.should be_new 18 | end 19 | end 20 | 21 | context "make!" do 22 | it "makes and saves objects" do 23 | Post.blueprint { } 24 | post = Post.make! 25 | post.should be_a(Post) 26 | post.should_not be_new 27 | end 28 | 29 | it "raises an exception for an invalid object" do 30 | User.blueprint { } 31 | lambda { 32 | User.make!(:username => "") 33 | }.should raise_error 34 | end 35 | end 36 | 37 | context "associations support" do 38 | it "handles belongs_to associations" do 39 | User.blueprint do 40 | username { "user_#{sn}" } 41 | end 42 | Post.blueprint do 43 | author 44 | end 45 | post = Post.make! 46 | post.should be_a(Post) 47 | post.should_not be_new 48 | post.author.should be_a(User) 49 | post.author.should_not be_new 50 | end 51 | 52 | it "handles has_many associations" do 53 | Post.blueprint do 54 | comments(3) 55 | end 56 | Comment.blueprint { } 57 | post = Post.make! 58 | post.should be_a(Post) 59 | post.should_not be_new 60 | post.should have(3).comments 61 | post.comments.each do |comment| 62 | comment.should be_a(Comment) 63 | comment.should_not be_new 64 | end 65 | end 66 | 67 | it "handles habtm associations" do 68 | Post.blueprint do 69 | tags(3) 70 | end 71 | Tag.blueprint do 72 | name { "tag_#{sn}" } 73 | end 74 | post = Post.make! 75 | post.should be_a(Post) 76 | post.should_not be_new 77 | post.should have(3).tags 78 | post.tags.each do |tag| 79 | tag.should be_a(Tag) 80 | tag.should_not be_new 81 | end 82 | end 83 | 84 | it "handles overriding associations" do 85 | User.blueprint do 86 | username { "user_#{sn}" } 87 | end 88 | Post.blueprint do 89 | author { User.make(:username => "post_author_#{sn}") } 90 | end 91 | post = Post.make! 92 | post.should be_a(Post) 93 | post.should_not be_new 94 | post.author.should be_a(User) 95 | post.author.should_not be_new 96 | post.author.username.should =~ /^post_author_\d+$/ 97 | end 98 | end 99 | 100 | context "error handling" do 101 | it "raises an exception for an attribute with no value" do 102 | User.blueprint { username } 103 | lambda { 104 | User.make 105 | }.should raise_error(ArgumentError) 106 | end 107 | end 108 | 109 | end 110 | end 111 | --------------------------------------------------------------------------------