orm_adapter_rails4_fix 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,57 @@
1
+ require 'dm-core'
2
+
3
+ module DataMapper
4
+ module Model
5
+ include OrmAdapter::ToAdapter
6
+ end
7
+
8
+ module Resource
9
+ class OrmAdapter < ::OrmAdapter::Base
10
+ # get a list of column names for a given class
11
+ def column_names
12
+ klass.properties.map(&:name)
13
+ end
14
+
15
+ # @see OrmAdapter::Base#get!
16
+ def get!(id)
17
+ klass.get!(id)
18
+ end
19
+
20
+ # @see OrmAdapter::Base#get
21
+ def get(id)
22
+ klass.get(id)
23
+ end
24
+
25
+ # @see OrmAdapter::Base#find_first
26
+ def find_first(options = {})
27
+ conditions, order = extract_conditions!(options)
28
+ klass.first :conditions => conditions, :order => order_clause(order)
29
+ end
30
+
31
+ # @see OrmAdapter::Base#find_all
32
+ def find_all(options = {})
33
+ conditions, order, limit, offset = extract_conditions!(options)
34
+ opts = { :conditions => conditions, :order => order_clause(order) }
35
+ opts = opts.merge({ :limit => limit }) unless limit.nil?
36
+ opts = opts.merge({ :offset => offset }) unless offset.nil?
37
+ klass.all opts
38
+ end
39
+
40
+ # @see OrmAdapter::Base#create!
41
+ def create!(attributes = {})
42
+ klass.create(attributes)
43
+ end
44
+
45
+ # @see OrmAdapter::Base#destroy
46
+ def destroy(object)
47
+ object.destroy if valid_object?(object)
48
+ end
49
+
50
+ protected
51
+
52
+ def order_clause(order)
53
+ order.map {|pair| pair.first.send(pair.last)}
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,65 @@
1
+ require 'mongo_mapper'
2
+
3
+ module MongoMapper
4
+ module Document
5
+ module ClassMethods
6
+ include OrmAdapter::ToAdapter
7
+ end
8
+
9
+ class OrmAdapter < ::OrmAdapter::Base
10
+ # get a list of column names for a given class
11
+ def column_names
12
+ klass.column_names
13
+ end
14
+
15
+ # @see OrmAdapter::Base#get!
16
+ def get!(id)
17
+ klass.find!(wrap_key(id))
18
+ end
19
+
20
+ # @see OrmAdapter::Base#get
21
+ def get(id)
22
+ klass.first({ :id => wrap_key(id) })
23
+ end
24
+
25
+ # @see OrmAdapter::Base#find_first
26
+ def find_first(conditions = {})
27
+ conditions, order = extract_conditions!(conditions)
28
+ conditions = conditions.merge(:sort => order) unless order.nil?
29
+ klass.first(conditions_to_fields(conditions))
30
+ end
31
+
32
+ # @see OrmAdapter::Base#find_all
33
+ def find_all(conditions = {})
34
+ conditions, order, limit, offset = extract_conditions!(conditions)
35
+ conditions = conditions.merge(:sort => order) unless order.nil?
36
+ conditions = conditions.merge(:limit => limit) unless limit.nil?
37
+ conditions = conditions.merge(:offset => offset) unless limit.nil? || offset.nil?
38
+ klass.all(conditions_to_fields(conditions))
39
+ end
40
+
41
+ # @see OrmAdapter::Base#create!
42
+ def create!(attributes = {})
43
+ klass.create!(attributes)
44
+ end
45
+
46
+ # @see OrmAdapter::Base#destroy
47
+ def destroy(object)
48
+ object.destroy if valid_object?(object)
49
+ end
50
+
51
+ protected
52
+
53
+ # converts and documents to ids
54
+ def conditions_to_fields(conditions)
55
+ conditions.inject({}) do |fields, (key, value)|
56
+ if value.is_a?(MongoMapper::Document) && klass.key?("#{key}_id")
57
+ fields.merge("#{key}_id" => value.id)
58
+ else
59
+ fields.merge(key => value)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,63 @@
1
+ require 'mongoid'
2
+
3
+ module Mongoid
4
+ module Document
5
+ module ClassMethods
6
+ include OrmAdapter::ToAdapter
7
+ end
8
+
9
+ class OrmAdapter < ::OrmAdapter::Base
10
+ # get a list of column names for a given class
11
+ def column_names
12
+ klass.fields.keys
13
+ end
14
+
15
+ # @see OrmAdapter::Base#get!
16
+ def get!(id)
17
+ klass.find(wrap_key(id))
18
+ end
19
+
20
+ # @see OrmAdapter::Base#get
21
+ def get(id)
22
+ klass.where(:_id => wrap_key(id)).first
23
+ end
24
+
25
+ # @see OrmAdapter::Base#find_first
26
+ def find_first(options = {})
27
+ conditions, order = extract_conditions!(options)
28
+ klass.limit(1).where(conditions_to_fields(conditions)).order_by(order).first
29
+ end
30
+
31
+ # @see OrmAdapter::Base#find_all
32
+ def find_all(options = {})
33
+ conditions, order, limit, offset = extract_conditions!(options)
34
+ klass.where(conditions_to_fields(conditions)).order_by(order).limit(limit).offset(offset)
35
+ end
36
+
37
+ # @see OrmAdapter::Base#create!
38
+ def create!(attributes = {})
39
+ klass.create!(attributes)
40
+ end
41
+
42
+ # @see OrmAdapter::Base#destroy
43
+ def destroy(object)
44
+ object.destroy if valid_object?(object)
45
+ end
46
+
47
+ protected
48
+
49
+ # converts and documents to ids
50
+ def conditions_to_fields(conditions)
51
+ conditions.inject({}) do |fields, (key, value)|
52
+ if value.is_a?(Mongoid::Document) && klass.fields.keys.include?("#{key}_id")
53
+ fields.merge("#{key}_id" => value.id)
54
+ elsif key.to_s == 'id'
55
+ fields.merge('_id' => value)
56
+ else
57
+ fields.merge(key => value)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,127 @@
1
+ module OrmAdapter
2
+ class Base
3
+ attr_reader :klass
4
+
5
+ # Your ORM adapter needs to inherit from this Base class and its adapter
6
+ # will be registered. To create an adapter you should create an inner
7
+ # constant "OrmAdapter" e.g. ActiveRecord::Base::OrmAdapter
8
+ #
9
+ # @see orm_adapters/active_record
10
+ # @see orm_adapters/datamapper
11
+ # @see orm_adapters/mongoid
12
+ def self.inherited(adapter)
13
+ OrmAdapter.adapters << adapter
14
+ super
15
+ end
16
+
17
+ def initialize(klass)
18
+ @klass = klass
19
+ end
20
+
21
+ # Get a list of column/property/field names
22
+ def column_names
23
+ raise NotSupportedError
24
+ end
25
+
26
+ # Get an instance by id of the model. Raises an error if a model is not found.
27
+ # This should comply with ActiveModel#to_key API, i.e.:
28
+ #
29
+ # User.to_adapter.get!(@user.to_key) == @user
30
+ #
31
+ def get!(id)
32
+ raise NotSupportedError
33
+ end
34
+
35
+ # Get an instance by id of the model. Returns nil if a model is not found.
36
+ # This should comply with ActiveModel#to_key API, i.e.:
37
+ #
38
+ # User.to_adapter.get(@user.to_key) == @user
39
+ #
40
+ def get(id)
41
+ raise NotSupportedError
42
+ end
43
+
44
+ # Find the first instance, optionally matching conditions, and specifying order
45
+ #
46
+ # You can call with just conditions, providing a hash
47
+ #
48
+ # User.to_adapter.find_first :name => "Fred", :age => 23
49
+ #
50
+ # Or you can specify :order, and :conditions as keys
51
+ #
52
+ # User.to_adapter.find_first :conditions => {:name => "Fred", :age => 23}
53
+ # User.to_adapter.find_first :order => [:age, :desc]
54
+ # User.to_adapter.find_first :order => :name, :conditions => {:age => 18}
55
+ #
56
+ # When specifying :order, it may be
57
+ # * a single arg e.g. <tt>:order => :name</tt>
58
+ # * a single pair with :asc, or :desc as last, e.g. <tt>:order => [:name, :desc]</tt>
59
+ # * an array of single args or pairs (with :asc or :desc as last), e.g. <tt>:order => [[:name, :asc], [:age, :desc]]</tt>
60
+ #
61
+ def find_first(options = {})
62
+ raise NotSupportedError
63
+ end
64
+
65
+ # Find all models, optionally matching conditions, and specifying order
66
+ # @see OrmAdapter::Base#find_first for how to specify order and conditions
67
+ def find_all(options = {})
68
+ raise NotSupportedError
69
+ end
70
+
71
+ # Create a model using attributes
72
+ def create!(attributes = {})
73
+ raise NotSupportedError
74
+ end
75
+
76
+ # Destroy an instance by passing in the instance itself.
77
+ def destroy(object)
78
+ raise NotSupportedError
79
+ end
80
+
81
+ protected
82
+
83
+ def valid_object?(object)
84
+ object.class == klass
85
+ end
86
+
87
+ def wrap_key(key)
88
+ key.is_a?(Array) ? key.first : key
89
+ end
90
+
91
+ # given an options hash,
92
+ # with optional :conditions, :order, :limit and :offset keys,
93
+ # returns conditions, normalized order, limit and offset
94
+ def extract_conditions!(options = {})
95
+ order = normalize_order(options.delete(:order))
96
+ limit = options.delete(:limit)
97
+ offset = options.delete(:offset)
98
+ conditions = options.delete(:conditions) || options
99
+
100
+ [conditions, order, limit, offset]
101
+ end
102
+
103
+ # given an order argument, returns an array of pairs, with each pair containing the attribute, and :asc or :desc
104
+ def normalize_order(order)
105
+ order = Array(order)
106
+
107
+ if order.length == 2 && !order[0].is_a?(Array) && [:asc, :desc].include?(order[1])
108
+ order = [order]
109
+ else
110
+ order = order.map {|pair| pair.is_a?(Array) ? pair : [pair, :asc] }
111
+ end
112
+
113
+ order.each do |pair|
114
+ pair.length == 2 or raise ArgumentError, "each order clause must be a pair (unknown clause #{pair.inspect})"
115
+ [:asc, :desc].include?(pair[1]) or raise ArgumentError, "order must be specified with :asc or :desc (unknown key #{pair[1].inspect})"
116
+ end
117
+
118
+ order
119
+ end
120
+ end
121
+
122
+ class NotSupportedError < NotImplementedError
123
+ def to_s
124
+ "method not supported by this orm adapter"
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,8 @@
1
+ module OrmAdapter
2
+ # Extend into a class that has an OrmAdapter
3
+ module ToAdapter
4
+ def to_adapter
5
+ @_to_adapter ||= self::OrmAdapter.new(self)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module OrmAdapter
2
+ VERSION = "0.4.1"
3
+ end
@@ -0,0 +1,35 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "orm_adapter/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "orm_adapter_rails4_fix"
6
+ s.version = OrmAdapter::VERSION.dup
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Ian White", "Jose Valim"]
9
+ s.description = "Provides a single point of entry for using basic features of ruby ORMs"
10
+ s.summary = "orm_adapter provides a single point of entry for using basic features of popular ruby ORMs. Its target audience is gem authors who want to support many ruby ORMs."
11
+ s.email = "ian.w.white@gmail.com"
12
+ s.homepage = "http://github.com/ianwhite/orm_adapter"
13
+
14
+ s.rubyforge_project = "orm_adapter"
15
+ s.required_rubygems_version = ">= 1.3.6"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "bundler", ">= 1.0.0"
22
+ s.add_development_dependency "git", ">= 1.2.5"
23
+ s.add_development_dependency "yard", ">= 0.6.0"
24
+ s.add_development_dependency "rake", ">= 0.8.7"
25
+ s.add_development_dependency "activerecord", ">= 3.0.0"
26
+ s.add_development_dependency "mongoid", ">= 2.0.0.beta.20"
27
+ s.add_development_dependency "mongo_mapper", ">= 0.9.0"
28
+ s.add_development_dependency "bson_ext", ">= 1.3.0"
29
+ s.add_development_dependency "rspec", ">= 2.4.0"
30
+ s.add_development_dependency "sqlite3", ">= 1.3.2"
31
+ s.add_development_dependency "datamapper", ">= 1.0"
32
+ s.add_development_dependency "dm-sqlite-adapter", ">= 1.0"
33
+ s.add_development_dependency "dm-active_model", ">= 1.0"
34
+ end
35
+
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+ require 'orm_adapter/example_app_shared'
3
+
4
+ if !defined?(ActiveRecord::Base)
5
+ puts "** require 'active_record' to run the specs in #{__FILE__}"
6
+ else
7
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ":memory:")
8
+
9
+ ActiveRecord::Migration.suppress_messages do
10
+ ActiveRecord::Schema.define(:version => 0) do
11
+ create_table(:users, :force => true) {|t| t.string :name; t.integer :rating; }
12
+ create_table(:notes, :force => true) {|t| t.belongs_to :owner, :polymorphic => true }
13
+ end
14
+ end
15
+
16
+ module ArOrmSpec
17
+ class User < ActiveRecord::Base
18
+ has_many :notes, :as => :owner
19
+ end
20
+
21
+ class AbstractNoteClass < ActiveRecord::Base
22
+ self.abstract_class = true
23
+ end
24
+
25
+ class Note < AbstractNoteClass
26
+ belongs_to :owner, :polymorphic => true
27
+ end
28
+
29
+ # here be the specs!
30
+ describe '[ActiveRecord orm adapter]' do
31
+ before do
32
+ User.delete_all
33
+ Note.delete_all
34
+ end
35
+
36
+ it_should_behave_like "example app with orm_adapter" do
37
+ let(:user_class) { User }
38
+ let(:note_class) { Note }
39
+ end
40
+
41
+ describe "#conditions_to_fields" do
42
+ describe "with non-standard association keys" do
43
+ class PerverseNote < Note
44
+ belongs_to :user, :foreign_key => 'owner_id'
45
+ belongs_to :pwner, :polymorphic => true, :foreign_key => 'owner_id', :foreign_type => 'owner_type'
46
+ end
47
+
48
+ let(:user) { User.create! }
49
+ let(:adapter) { PerverseNote.to_adapter }
50
+
51
+ it "should convert polymorphic object in conditions to the appropriate fields" do
52
+ adapter.send(:conditions_to_fields, :pwner => user).should == {'owner_id' => user.id, 'owner_type' => user.class.name}
53
+ end
54
+
55
+ it "should convert belongs_to object in conditions to the appropriate fields" do
56
+ adapter.send(:conditions_to_fields, :user => user).should == {'owner_id' => user.id}
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'orm_adapter/example_app_shared'
3
+
4
+ if !defined?(DataMapper)
5
+ puts "** require 'dm-core' to run the specs in #{__FILE__}"
6
+ else
7
+
8
+ DataMapper.setup(:default, 'sqlite::memory:')
9
+
10
+ module DmOrmSpec
11
+ class User
12
+ include DataMapper::Resource
13
+ property :id, Serial
14
+ property :name, String
15
+ property :rating, Integer
16
+ has n, :notes, :child_key => [:owner_id]
17
+ end
18
+
19
+ class Note
20
+ include DataMapper::Resource
21
+ property :id, Serial
22
+ property :body, String
23
+ belongs_to :owner, 'User'
24
+ end
25
+
26
+ require 'dm-migrations'
27
+ DataMapper.finalize
28
+ DataMapper.auto_migrate!
29
+
30
+ # here be the specs!
31
+ describe DataMapper::Resource::OrmAdapter do
32
+ before do
33
+ User.destroy
34
+ Note.destroy
35
+ end
36
+
37
+ it_should_behave_like "example app with orm_adapter" do
38
+ let(:user_class) { User }
39
+ let(:note_class) { Note }
40
+
41
+ def reload_model(model)
42
+ model.class.get(model.id)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end