datamapper4rail 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/Manifest.txt +22 -0
- data/README.txt +101 -0
- data/Rakefile +32 -0
- data/generators/dm_install/dm_install_generator.rb +12 -0
- data/generators/dm_install/templates/datamapper.rake +42 -0
- data/generators/dm_migration/dm_migration_generator.rb +10 -0
- data/generators/dm_migration/templates/migration.rb +16 -0
- data/generators/dm_model/dm_model_generator.rb +27 -0
- data/generators/dm_model/templates/model.rb +14 -0
- data/generators/dm_model/templates/unit_test.rb +8 -0
- data/generators/rspec_default_values.rb +20 -0
- data/generators/rspec_dm_model/rspec_dm_model_generator.rb +33 -0
- data/generators/rspec_dm_model/templates/model.rb +16 -0
- data/generators/rspec_dm_model/templates/model_spec.rb +41 -0
- data/lib/datamapper4rails.rb +53 -0
- data/lib/datamapper4rails/adapters/base_adapter.rb +198 -0
- data/lib/datamapper4rails/adapters/restful_adapter.rb +252 -0
- data/lib/datamapper4rails/database_config.rb +49 -0
- data/lib/datamapper4rails/datamapper_store.rb +67 -0
- data/lib/datamapper4rails/restful_transactions.rb +42 -0
- data/lib/datamapper4rails/version.rb +3 -0
- metadata +97 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
generators/dm_install/dm_install_generator.rb
|
6
|
+
generators/dm_install/templates/datamapper.rake
|
7
|
+
generators/dm_migration/dm_migration_generator.rb
|
8
|
+
generators/dm_migration/templates/migration.rb
|
9
|
+
generators/dm_model/dm_model_generator.rb
|
10
|
+
generators/dm_model/templates/model.rb
|
11
|
+
generators/dm_model/templates/unit_test.rb
|
12
|
+
generators/rspec_default_values.rb
|
13
|
+
generators/rspec_dm_model/rspec_dm_model_generator.rb
|
14
|
+
generators/rspec_dm_model/templates/model.rb
|
15
|
+
generators/rspec_dm_model/templates/model_spec.rb
|
16
|
+
lib/datamapper4rails.rb
|
17
|
+
lib/datamapper4rails/adapters/base_adapter.rb
|
18
|
+
lib/datamapper4rails/adapters/restful_adapter.rb
|
19
|
+
lib/datamapper4rails/database_config.rb
|
20
|
+
lib/datamapper4rails/datamapper_store.rb
|
21
|
+
lib/datamapper4rails/restful_transactions.rb
|
22
|
+
lib/datamapper4rails/version.rb
|
data/README.txt
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
= datamapper4rails
|
2
|
+
|
3
|
+
* http://datamapper4rail.rubyforge.org
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
collection of datamapper related extensions. mostly needed to run within rails. the restful transactions is around filter for rails. the restful adapter can be outside of rails. datamapper store is a session store for rails which uses datamapper as persistent layer. the generators produces datamapper models for your rails application. quite a few things are "stolen" from dm-more/rails_datamapper. a lot of things do not work there and patches are still in process to be applied so until dm-more/rails_datamapper catches up, ut I hope these two project merge someday again.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* restful adapter does handle associations partially and does not handle collections
|
12
|
+
|
13
|
+
== SYNOPSIS:
|
14
|
+
|
15
|
+
=== restful transaction
|
16
|
+
|
17
|
+
wraps all modifying requests (POST, PUT, DELETE) into a transaction. any error/exception as well render of a page will rollback the transaction. typically if a POST, PUT or DELETE succeeds then a redirect gets send back to browser.
|
18
|
+
|
19
|
+
credits of the main idea goes to http://www.redhillonrails.org
|
20
|
+
|
21
|
+
is implemented as around filter in rails and gets prepend to the filters of the action_controller of rails
|
22
|
+
|
23
|
+
require 'datamapper4rails/restful_transations
|
24
|
+
|
25
|
+
=== datamapper session store
|
26
|
+
|
27
|
+
this is just the datamapper compaign to the activerecord_store.
|
28
|
+
|
29
|
+
in config/environment.rb add
|
30
|
+
|
31
|
+
config.action_controller.session_store = :datamapper_store
|
32
|
+
|
33
|
+
in case you need a memory cache for your sessions add this
|
34
|
+
|
35
|
+
config.action_controller.session = { :cache => true }
|
36
|
+
|
37
|
+
=== generators for datamapper models
|
38
|
+
|
39
|
+
this is taken from dm-more/rails_datamapper and extended it - to my liking. patches are submitted upstream until they get applied this will remain here.
|
40
|
+
|
41
|
+
* dm-install: rake task for datamapper: automigrate, autoupgrade
|
42
|
+
* dm_model
|
43
|
+
* rspec_dm_model
|
44
|
+
|
45
|
+
=== database config
|
46
|
+
|
47
|
+
this is also taken from dm-more/rails_datamapper and just uses the
|
48
|
+
'config/database.yml' to configure a database connection. it also allows to configure multiple repositories for a single environment just nest the config in such a way:
|
49
|
+
|
50
|
+
development:
|
51
|
+
repositories:
|
52
|
+
default:
|
53
|
+
adapter: sqlite3
|
54
|
+
database: db/development.sqlite3
|
55
|
+
pool: 5
|
56
|
+
timeout: 5000
|
57
|
+
users:
|
58
|
+
adapter: ldap
|
59
|
+
host: localhost
|
60
|
+
port: 389
|
61
|
+
base: dc=example,dc=com
|
62
|
+
bind_name: cn=admin,dc=example,dc=com
|
63
|
+
password: secret
|
64
|
+
|
65
|
+
|
66
|
+
=== restful adapter
|
67
|
+
|
68
|
+
this comes partly from dm-ldap-adapter and partly from dm-more/adapter/rest_adapter. the restful adapter allows to Create, Retrieve, Update and Delete resources via a restful service.
|
69
|
+
|
70
|
+
== REQUIREMENTS:
|
71
|
+
|
72
|
+
* datamapper
|
73
|
+
|
74
|
+
== INSTALL:
|
75
|
+
|
76
|
+
* sudo gem install datamapper4rails
|
77
|
+
|
78
|
+
== LICENSE:
|
79
|
+
|
80
|
+
(The MIT License)
|
81
|
+
|
82
|
+
Copyright (c) 2009 Kristian Meier
|
83
|
+
|
84
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
85
|
+
a copy of this software and associated documentation files (the
|
86
|
+
'Software'), to deal in the Software without restriction, including
|
87
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
88
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
89
|
+
permit persons to whom the Software is furnished to do so, subject to
|
90
|
+
the following conditions:
|
91
|
+
|
92
|
+
The above copyright notice and this permission notice shall be
|
93
|
+
included in all copies or substantial portions of the Software.
|
94
|
+
|
95
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
96
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
97
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
98
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
99
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
100
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
101
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/datamapper4rails/version.rb'
|
6
|
+
|
7
|
+
Hoe.new('datamapper4rail', Datamapper4rails::VERSION) do |p|
|
8
|
+
p.rubyforge_name = 'datamapper4rail'
|
9
|
+
p.developer('mkristian', 'm.kristian@web.de')
|
10
|
+
p.extra_deps = ['slf4r']
|
11
|
+
p.remote_rdoc_dir = '' # Release to root
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'Install the package as a gem.'
|
15
|
+
task :install => [:clean, :package] do
|
16
|
+
gem = Dir['pkg/*.gem'].first
|
17
|
+
sh "gem install --local #{gem} --no-ri --no-rdoc"
|
18
|
+
end
|
19
|
+
|
20
|
+
# desc 'Run specifications'
|
21
|
+
# Spec::Rake::SpecTask.new(:spec) do |t|
|
22
|
+
# if File.exists?('spec/spec.opts')
|
23
|
+
# t.spec_opts << '--options' << 'spec/spec.opts'
|
24
|
+
# end
|
25
|
+
# t.spec_files = Pathname.glob('./spec/**/*_spec.rb')
|
26
|
+
# end
|
27
|
+
|
28
|
+
# require 'yard'
|
29
|
+
|
30
|
+
# YARD::Rake::YardocTask.new
|
31
|
+
|
32
|
+
# vim: syntax=Ruby
|
@@ -0,0 +1,42 @@
|
|
1
|
+
namespace :db do
|
2
|
+
|
3
|
+
desc "Perform automigration"
|
4
|
+
task :automigrate => :environment do
|
5
|
+
FileList["app/models/**/*.rb"].each do |model|
|
6
|
+
load model
|
7
|
+
end
|
8
|
+
::DataMapper.auto_migrate!
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Perform non destructive automigration"
|
12
|
+
task :autoupgrade => :environment do
|
13
|
+
FileList["app/models/**/*.rb"].each do |model|
|
14
|
+
load model
|
15
|
+
end
|
16
|
+
::DataMapper.auto_upgrade!
|
17
|
+
end
|
18
|
+
|
19
|
+
namespace :migrate do
|
20
|
+
task :load => :environment do
|
21
|
+
gem 'dm-migrations'
|
22
|
+
FileList["db/migrations/*.rb"].each do |migration|
|
23
|
+
load migration
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Migrate up using migrations"
|
28
|
+
task :up, :version, :needs => :load do |t, args|
|
29
|
+
version = args[:version]
|
30
|
+
migrate_up!(version)
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Migrate down using migrations"
|
34
|
+
task :down, :version, :needs => :load do |t, args|
|
35
|
+
version = args[:version]
|
36
|
+
migrate_down!(version)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Migrate the database to the latest version"
|
41
|
+
task :migrate => 'db:migrate:up'
|
42
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class <%= migration_name %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :<%= table_name %> do |t|
|
4
|
+
<% for attribute in attributes -%>
|
5
|
+
t.<%= attribute.type %> :<%= attribute.name %>
|
6
|
+
<% end -%>
|
7
|
+
<% unless options[:skip_timestamps] %>
|
8
|
+
t.timestamps
|
9
|
+
<% end -%>
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :<%= table_name %>
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rails_generator/generators/components/model/model_generator'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
class DmModelGenerator <ModelGenerator
|
5
|
+
|
6
|
+
def manifest
|
7
|
+
record do |m|
|
8
|
+
# Check for class naming collisions.
|
9
|
+
m.class_collisions class_path, class_name, "#{class_name}Test"
|
10
|
+
|
11
|
+
# Model, test, and fixture directories.
|
12
|
+
m.directory File.join('app/models', class_path)
|
13
|
+
m.directory File.join('test/unit', class_path)
|
14
|
+
|
15
|
+
# Model class, unit test, and fixtures.
|
16
|
+
m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
|
17
|
+
m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
|
18
|
+
|
19
|
+
unless options[:skip_migration]
|
20
|
+
m.migration_template 'model:migration.rb', 'db/migrate', :assigns => {
|
21
|
+
:migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
|
22
|
+
}, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class <%= class_name %>
|
2
|
+
include DataMapper::Resource
|
3
|
+
property :id, Serial
|
4
|
+
|
5
|
+
<% for attribute in attributes -%>
|
6
|
+
property :<%= attribute.name %>, <%= attribute.type.to_s.capitalize %>, :nullable => false
|
7
|
+
|
8
|
+
<% end -%>
|
9
|
+
<% unless options[:skip_timestamps] %>
|
10
|
+
property :created_at, DateTime, :nullable => false
|
11
|
+
property :updated_at, DateTime, :nullable => false
|
12
|
+
|
13
|
+
<% end -%>
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Rails
|
2
|
+
module Generator
|
3
|
+
class GeneratedAttribute
|
4
|
+
def default_value
|
5
|
+
@default_value ||= case type
|
6
|
+
when :int, :integer then "1"
|
7
|
+
when :float then "1.5"
|
8
|
+
when :decimal, :big_decimal then "9.99"
|
9
|
+
when :date_time, :datetime,
|
10
|
+
:timestamp, :time then "Time.now"
|
11
|
+
when :date then "Date.today"
|
12
|
+
when :string, :text then "\"value for #{@name}\""
|
13
|
+
when :boolean then "false"
|
14
|
+
else
|
15
|
+
""
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rails_generator/generators/components/model/model_generator'
|
2
|
+
require 'active_record'
|
3
|
+
require File.dirname(__FILE__) + '/../rspec_default_values'
|
4
|
+
|
5
|
+
class RspecDmModelExtendedGenerator <ModelGenerator
|
6
|
+
|
7
|
+
def manifest
|
8
|
+
record do |m|
|
9
|
+
|
10
|
+
# Check for class naming collisions.
|
11
|
+
m.class_collisions class_path, class_name
|
12
|
+
|
13
|
+
# Model, spec, and fixture directories.
|
14
|
+
m.directory File.join('app/models', class_path)
|
15
|
+
m.directory File.join('spec/models', class_path)
|
16
|
+
|
17
|
+
# Model class, spec and fixtures.
|
18
|
+
m.template 'model.rb', File.join('app/models',
|
19
|
+
class_path,
|
20
|
+
"#{file_name}.rb")
|
21
|
+
m.template 'model_spec.rb', File.join('spec/models',
|
22
|
+
class_path,
|
23
|
+
"#{file_name}_spec.rb")
|
24
|
+
end
|
25
|
+
|
26
|
+
# unless options[:skip_migration]
|
27
|
+
# m.migration_template 'model:migration.rb', 'db/migrate', :assigns => {
|
28
|
+
# :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
|
29
|
+
# }, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
|
30
|
+
# end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class <%= class_name %>
|
2
|
+
include DataMapper::Resource
|
3
|
+
property :id, Serial
|
4
|
+
|
5
|
+
<% for attribute in attributes -%>
|
6
|
+
property :<%= attribute.name %>, <%= attribute.type.to_s.camelize %>, :nullable => false <% if attribute.type == :string or attribute.type == :text -%>, :format => /^[^<'&">]*$/<% if attribute.type == :string %>, :length => 50<% end -%>
|
7
|
+
<% else -%>
|
8
|
+
|
9
|
+
<% end -%>
|
10
|
+
<% end -%>
|
11
|
+
<% unless options[:skip_timestamps] %>
|
12
|
+
property :created_at, DateTime, :nullable => false
|
13
|
+
property :updated_at, DateTime, :nullable => false
|
14
|
+
|
15
|
+
<% end -%>
|
16
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../spec_helper')
|
2
|
+
|
3
|
+
describe <%= class_name %> do
|
4
|
+
before(:each) do
|
5
|
+
@valid_attributes = {
|
6
|
+
<% attributes.each_with_index do |attribute, attribute_index| -%>
|
7
|
+
:<%= attribute.name %> => <%= attribute.default_value %><%= attribute_index == attributes.length - 1 ? '' : ','%>
|
8
|
+
<% end -%>
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
<% attributes.each do |attribute| -%>
|
13
|
+
it "should require <%= attribute.name %>" do
|
14
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => nil))
|
15
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
16
|
+
end
|
17
|
+
|
18
|
+
<% if attribute.type == :string or attribute.type == :text -%>
|
19
|
+
it 'should not match <%= attribute.name %>' do
|
20
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "<script" ))
|
21
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
22
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "sc'ript" ))
|
23
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
24
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "scr&ipt" ))
|
25
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
26
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => 'scr"ipt' ))
|
27
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
28
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "script>" ))
|
29
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
30
|
+
end
|
31
|
+
|
32
|
+
<% elsif [:integer, :big_decimal, :float].member? attribute.type %>
|
33
|
+
it "should be numerical <%= attribute.name %>" do
|
34
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "none-numberic" ))
|
35
|
+
<%= singular_name %>.<%= attribute.name %>.to_i.should == 0
|
36
|
+
<%= singular_name %>.errors.size.should == 0
|
37
|
+
end
|
38
|
+
|
39
|
+
<% end -%>
|
40
|
+
<% end -%>
|
41
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
def config_file()
|
3
|
+
RAILS_ROOT + "/config/database.yml"
|
4
|
+
end
|
5
|
+
|
6
|
+
def create_connection()
|
7
|
+
conf = config.dup
|
8
|
+
if repositories = conf.delete(:repositories)
|
9
|
+
repositories.each do |repo, conf|
|
10
|
+
::DataMapper.setup(repo, conf) unless conf.empty?
|
11
|
+
end
|
12
|
+
else
|
13
|
+
::DataMapper.setup(:default, conf) unless conf.empty?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_config_for_environment
|
18
|
+
if hash = full_config[RAILS_ENV]
|
19
|
+
symbolize_keys(hash)
|
20
|
+
elsif hash = full_config[RAILS_ENV.to_sym]
|
21
|
+
hash
|
22
|
+
else
|
23
|
+
raise ArgumentError, "missing environment '#{RAILS_ENV}' in config file #{config_file}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def full_config
|
28
|
+
@full_config ||= YAML::load(ERB.new(IO.read(config_file)).result)
|
29
|
+
end
|
30
|
+
|
31
|
+
def config
|
32
|
+
@config ||= get_config_for_environment
|
33
|
+
end
|
34
|
+
|
35
|
+
def symbolize_keys(h)
|
36
|
+
config = {}
|
37
|
+
|
38
|
+
h.each do |k, v|
|
39
|
+
if k == 'port'
|
40
|
+
config[k.to_sym] = v.to_i
|
41
|
+
elsif k == 'adapter' && v == 'postgresql'
|
42
|
+
config[k.to_sym] = 'postgres'
|
43
|
+
elsif v.is_a?(Hash)
|
44
|
+
config[k.to_sym] = symbolize_keys(v)
|
45
|
+
else
|
46
|
+
config[k.to_sym] = v
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
config
|
51
|
+
end
|
52
|
+
|
53
|
+
create_connection()
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
require 'slf4r'
|
3
|
+
|
4
|
+
module DataMapper
|
5
|
+
module Adapters
|
6
|
+
class NoopTransaction
|
7
|
+
|
8
|
+
def close ; end
|
9
|
+
def begin ; end
|
10
|
+
def prepare ; end
|
11
|
+
def commit ; end
|
12
|
+
def rollback ; end
|
13
|
+
def rollback_prepared ; end
|
14
|
+
|
15
|
+
end
|
16
|
+
class BaseAdapter < AbstractAdapter
|
17
|
+
|
18
|
+
include Slf4r::Logger
|
19
|
+
|
20
|
+
# @see AbstractAdapter
|
21
|
+
def transaction_primitive
|
22
|
+
NoopTransaction.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(name, uri_or_options)
|
26
|
+
super(name, uri_or_options)
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
# checks whether a given resource fullfils the conditions
|
32
|
+
# @param [DataMapper::Resource] resource
|
33
|
+
# @param [Array<Condition>] conditions
|
34
|
+
# @return [Boolean]
|
35
|
+
# true if the resource are within the conditions otherwise false
|
36
|
+
def filter_resource(resource, conditions)
|
37
|
+
#puts "condi"
|
38
|
+
#p conditions
|
39
|
+
# no conditation => no filter
|
40
|
+
if conditions.size == 0
|
41
|
+
true
|
42
|
+
else
|
43
|
+
conditions.all? do |tuple|
|
44
|
+
operator, property, bind_value = *tuple
|
45
|
+
|
46
|
+
value = property.get!(resource)
|
47
|
+
case operator
|
48
|
+
when :eql, :in then equality_comparison(bind_value, value)
|
49
|
+
when :not then !equality_comparison(bind_value, value)
|
50
|
+
when :like then Regexp.new(bind_value.gsub(/%/, ".*")) =~ value
|
51
|
+
when :gt then !value.nil? && value > bind_value
|
52
|
+
when :gte then !value.nil? && value >= bind_value
|
53
|
+
when :lt then !value.nil? && value < bind_value
|
54
|
+
when :lte then !value.nil? && value <= bind_value
|
55
|
+
else raise "Invalid query operator: #{operator.inspect}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# helper method to dispatch the equality test for different
|
62
|
+
# classes
|
63
|
+
def equality_comparison(bind_value, value)
|
64
|
+
case bind_value
|
65
|
+
when Array, Range then bind_value.include?(value)
|
66
|
+
when NilClass then value.nil?
|
67
|
+
else bind_value == value
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
public
|
72
|
+
|
73
|
+
# @see AbstractAdapter
|
74
|
+
# @param [Array<DataMapper::Resources>] resources
|
75
|
+
# aaaa
|
76
|
+
# @return [Fixnum]
|
77
|
+
# number of the newly created resources
|
78
|
+
def create(resources)
|
79
|
+
resources.select do |resource|
|
80
|
+
|
81
|
+
create_resource(resource)
|
82
|
+
|
83
|
+
end.size # just return the number of create resources
|
84
|
+
end
|
85
|
+
|
86
|
+
# @see AbstractAdapter
|
87
|
+
# @param [Hash] attributes
|
88
|
+
# collection of attribute, i.e. the name/value pairs which
|
89
|
+
# needs to be updated
|
90
|
+
# @param [Query]
|
91
|
+
# on all resources which are selected by that query the
|
92
|
+
# update will be applied
|
93
|
+
# @return [Fixnum]
|
94
|
+
# number of the updated resources
|
95
|
+
def update(attributes, query)
|
96
|
+
read_many(query).select do |resource|
|
97
|
+
|
98
|
+
update_resource(resource, attributes)
|
99
|
+
|
100
|
+
end.size
|
101
|
+
end
|
102
|
+
|
103
|
+
# @see AbstractAdapter
|
104
|
+
# @param [DataMapper::Query] query
|
105
|
+
# which selects the resource
|
106
|
+
# @return [DataMapper::Resource]
|
107
|
+
# the found Resource or nil
|
108
|
+
def read_one(query)
|
109
|
+
result = read_resource(query)
|
110
|
+
if result.is_a? Resource
|
111
|
+
result
|
112
|
+
elsif result # assume result to be Array with the values
|
113
|
+
#puts "------------------"
|
114
|
+
#p result
|
115
|
+
query.model.load(result, query)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# @see AbstractAdapter
|
120
|
+
# @param [DataMapper::Query] query
|
121
|
+
# which selects the resources
|
122
|
+
# @return [DataMapper::Collection]
|
123
|
+
# collection of Resources
|
124
|
+
def read_many(query)
|
125
|
+
Collection.new(query) do |set|
|
126
|
+
result = read_resources(query)
|
127
|
+
#puts "read_many"
|
128
|
+
#p result
|
129
|
+
if result.size > 0 and result.first.is_a? Resource
|
130
|
+
set.replace(result)
|
131
|
+
else
|
132
|
+
result.each do |values|
|
133
|
+
set.load(values)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# @see AbstractAdapter
|
140
|
+
# @param [Query] query
|
141
|
+
# which selects the resources to be deleted
|
142
|
+
# @return [Fixnum]
|
143
|
+
# number of the deleted resources
|
144
|
+
def delete(query)
|
145
|
+
read_many(query).each do |resource|
|
146
|
+
|
147
|
+
delete_resource(resource)
|
148
|
+
|
149
|
+
end.size
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
# @param [DataMapper::Resource] resource
|
155
|
+
# which will be created
|
156
|
+
# @return [DataMapper::Resource]
|
157
|
+
# either the resource itself if the creation was successful or nil
|
158
|
+
def create_resource(resource)
|
159
|
+
raise NotImplementedError.new
|
160
|
+
end
|
161
|
+
|
162
|
+
# @param [DataMapper::Query] query
|
163
|
+
# which selects the resource
|
164
|
+
# @return [DataMapper::Resource,Array<String>]
|
165
|
+
# the resource or a set of values ordered in the same manner as query.fields attributes
|
166
|
+
def read_resource(query)
|
167
|
+
raise NotImplementedError.new
|
168
|
+
end
|
169
|
+
|
170
|
+
# @param [DataMapper::Query] query
|
171
|
+
# which selects the resources
|
172
|
+
# @return [Array<DataMapper::Resource>,Array<String>]
|
173
|
+
# resources or ordered values
|
174
|
+
# @see #read_resource
|
175
|
+
def read_resources(query)
|
176
|
+
raise NotImplementedError.new
|
177
|
+
end
|
178
|
+
|
179
|
+
# @param [DataMapper::Resource] resource
|
180
|
+
# which will be updated with the given attributes.
|
181
|
+
# @param [Hash] attributes
|
182
|
+
# the keys are the property names and the values are the new values of that property.
|
183
|
+
# @return [DataMapper::Resource]
|
184
|
+
# resource on success otherwise nil
|
185
|
+
def update_resource(resource, attributes)
|
186
|
+
raise NotImplementedError.new
|
187
|
+
end
|
188
|
+
|
189
|
+
# @param [DataMapper::Resource] resource
|
190
|
+
# which will be deleted
|
191
|
+
# @return [DataMapper::Resource]
|
192
|
+
# either the resource if the deletion was successful or nil
|
193
|
+
def delete_resource(resource)
|
194
|
+
raise NotImplementedError.new
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,252 @@
|
|
1
|
+
require 'adapters/restful_adapter'
|
2
|
+
require 'net/http'
|
3
|
+
require 'extlib/inflection'
|
4
|
+
require 'extlib/module'
|
5
|
+
|
6
|
+
module DataMapper
|
7
|
+
module Adapters
|
8
|
+
class RestfulAdapter < BaseAdapter
|
9
|
+
|
10
|
+
include ::Slf4r::Logger
|
11
|
+
|
12
|
+
def resource_name_from_model(model)
|
13
|
+
::Extlib::Inflection.underscore(model.name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def resource_name_from_query(query)
|
17
|
+
resource_name_from_model(query.model)
|
18
|
+
end
|
19
|
+
|
20
|
+
def keys_from_query(query)
|
21
|
+
keys = query.model.key
|
22
|
+
# work around strange missing of properties in model
|
23
|
+
# but the query has still the fields :P
|
24
|
+
if keys.size == 0
|
25
|
+
query.fields.select do |f|
|
26
|
+
f.key?
|
27
|
+
end
|
28
|
+
else
|
29
|
+
keys
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def key_value_from_query(query)
|
34
|
+
keys = keys_from_query(query)
|
35
|
+
logger.debug { "keys=#{keys.inspect}" }
|
36
|
+
if keys.size == 1
|
37
|
+
key = keys[0]
|
38
|
+
# return the third element of the condition array
|
39
|
+
# which belongs to the key
|
40
|
+
query.conditions.detect do |c|
|
41
|
+
c[1] == key
|
42
|
+
end[2]
|
43
|
+
else
|
44
|
+
raise "compound keys are not supported"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def http_get(uri)
|
49
|
+
send_request do |http|
|
50
|
+
request = Net::HTTP::Get.new(uri)
|
51
|
+
request.basic_auth(@uri[:login],
|
52
|
+
@uri[:password]) unless @uri[:login].blank?
|
53
|
+
http.request(request)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def http_post(uri, data = nil)
|
58
|
+
send_request do |http|
|
59
|
+
request = Net::HTTP::Post.new(uri, {
|
60
|
+
'content-type' => 'application/xml',
|
61
|
+
'content-length' => data.length.to_s
|
62
|
+
})
|
63
|
+
request.basic_auth(@uri[:login],
|
64
|
+
@uri[:password]) unless @uri[:login].blank?
|
65
|
+
http.request(request, data)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def http_put(uri, data = {})
|
70
|
+
send_request do |http|
|
71
|
+
request = Net::HTTP::Put.new(uri)
|
72
|
+
request.basic_auth(@uri[:login],
|
73
|
+
@uri[:password]) unless @uri[:login].blank?
|
74
|
+
request.set_form_data(data)
|
75
|
+
http.request(request)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def http_delete(uri)
|
80
|
+
send_request do |http|
|
81
|
+
request = Net::HTTP::Delete.new(uri)
|
82
|
+
request.basic_auth(@uri[:login],
|
83
|
+
@uri[:password]) unless @uri[:login].blank?
|
84
|
+
http.request(request)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def send_request(&block)
|
89
|
+
res = nil
|
90
|
+
Net::HTTP.start(@uri[:host], @uri[:port].to_i) do |http|
|
91
|
+
res = yield(http)
|
92
|
+
end
|
93
|
+
logger.debug { "response=" + res.code }
|
94
|
+
res
|
95
|
+
end
|
96
|
+
|
97
|
+
def parse_resource(xml, model, query = nil)
|
98
|
+
elements = {}
|
99
|
+
associations = {}
|
100
|
+
many_to_many = {}
|
101
|
+
xml.elements.collect do |element|
|
102
|
+
if element.text.nil?
|
103
|
+
if element.attributes['type'] == 'array'
|
104
|
+
many_to_many[element.name.gsub('-','_').to_sym] = element
|
105
|
+
else
|
106
|
+
associations[element.name.gsub('-','_').to_sym] = element
|
107
|
+
end
|
108
|
+
else
|
109
|
+
elements[element.name.gsub('-','_').to_sym] = element.text
|
110
|
+
end
|
111
|
+
end
|
112
|
+
#puts
|
113
|
+
#puts "elements"
|
114
|
+
#p elements
|
115
|
+
resource = model.load(model.properties.collect do |f|
|
116
|
+
elements[f.name]
|
117
|
+
end, query)
|
118
|
+
resource.send("#{keys_from_query(query)[0].name}=".to_sym, elements[keys_from_query(query)[0].name] )
|
119
|
+
#p resource
|
120
|
+
associations.each do |name, association|
|
121
|
+
model =
|
122
|
+
if rel = model.relationships[name]
|
123
|
+
if rel.child_model == model
|
124
|
+
rel.parent_model
|
125
|
+
else
|
126
|
+
rel.child_model
|
127
|
+
end
|
128
|
+
# else
|
129
|
+
#::Extlib::Inflection.constantize(::Extlib::Inflection.classify(name))
|
130
|
+
# model.find_const(::Extlib::Inflection.classify(name))
|
131
|
+
end
|
132
|
+
if resource.respond_to? "#{name}=".to_sym
|
133
|
+
resource.send("#{name}=".to_sym,
|
134
|
+
parse_resource(association, model,
|
135
|
+
::DataMapper::Query.new(query.repository, model )))
|
136
|
+
else
|
137
|
+
resource.send(("#{name.to_s.pluralize}<" + "<").to_sym,
|
138
|
+
parse_resource(association, model,
|
139
|
+
::DataMapper::Query.new(query.repository, model )))
|
140
|
+
end
|
141
|
+
end
|
142
|
+
resource.instance_variable_set(:@new_record, false)
|
143
|
+
resource
|
144
|
+
end
|
145
|
+
|
146
|
+
# @see BaseAdapter
|
147
|
+
def create_resource(resource)
|
148
|
+
name = resource.model.name
|
149
|
+
uri = "/#{name.pluralize}.xml"
|
150
|
+
logger.debug { "post #{uri}" }
|
151
|
+
response = http_post(uri, resource.to_xml )
|
152
|
+
resource_new = parse_resource(REXML::Document::new(response.body).root,
|
153
|
+
resource.model,
|
154
|
+
::DataMapper::Query.new(resource.repository,
|
155
|
+
resource.model ))
|
156
|
+
|
157
|
+
# copy all attributes/associations from the downloaded resource
|
158
|
+
# to the given resource
|
159
|
+
# TODO better pass the given resource into parse_resource
|
160
|
+
resource_new.attributes.each do |key, value|
|
161
|
+
resource.send(:properties)[key].set!(resource, value)
|
162
|
+
end
|
163
|
+
resource_new.send(:relationships).each do |key, value|
|
164
|
+
resource.send("#{key}=".to_sym, resource_new.send(key))
|
165
|
+
end
|
166
|
+
resource
|
167
|
+
end
|
168
|
+
|
169
|
+
# @see BaseAdapter
|
170
|
+
def read_resource(query)
|
171
|
+
if(query.conditions.empty?)
|
172
|
+
raise "not implemented"
|
173
|
+
else
|
174
|
+
key = key_value_from_query(query)
|
175
|
+
uri = "/#{resource_name_from_query(query).pluralize}/#{key}.xml"
|
176
|
+
logger.debug { "get #{uri}" }
|
177
|
+
response = http_get(uri)
|
178
|
+
if response.kind_of?(Net::HTTPSuccess)
|
179
|
+
parse_resource(REXML::Document::new(response.body).root,
|
180
|
+
query.model,
|
181
|
+
query)
|
182
|
+
else
|
183
|
+
#TODO may act on different response codes differently
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# @see BaseAdapter
|
189
|
+
def read_resources(query)
|
190
|
+
# raise "not implemented"
|
191
|
+
[read_resource(query)]
|
192
|
+
end
|
193
|
+
|
194
|
+
# @overwrite BaseAdapter
|
195
|
+
def update(attributes, query)
|
196
|
+
name = resource_name_from_query(query)
|
197
|
+
params = {}
|
198
|
+
attributes.each do |attr, val|
|
199
|
+
params["#{name}[#{attr.name}]"]=val
|
200
|
+
end
|
201
|
+
key = key_value_from_query(query)
|
202
|
+
uri = "/#{name.pluralize}/#{key}.xml"
|
203
|
+
logger.debug { "put #{uri}" }
|
204
|
+
response = http_put(uri, params)
|
205
|
+
response.kind_of?(Net::HTTPSuccess)
|
206
|
+
end
|
207
|
+
|
208
|
+
# @see BaseAdapter
|
209
|
+
def update_resource(resource, attributes)
|
210
|
+
query = resource.to_query
|
211
|
+
if(query.conditions.empty?)
|
212
|
+
raise "not implemented"
|
213
|
+
else
|
214
|
+
name = resource.name
|
215
|
+
params = {}
|
216
|
+
attributes.each do |attr, val|
|
217
|
+
params["#{name}[#{attr.name}]"]=val
|
218
|
+
end
|
219
|
+
key = key_value_from_query(query)
|
220
|
+
logger.debug {resource.to_xml}
|
221
|
+
response = http_put("/#{resource_name_from_query(query).pluralize}/#{key}.xml", params)
|
222
|
+
response.kind_of?(Net::HTTPSuccess)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# @overwrite BaseAdapter
|
227
|
+
def delete(query)
|
228
|
+
# TODO limit == 1 is NOT sufficient ONLY necessary
|
229
|
+
if query.limit == 1
|
230
|
+
name = resource_name_from_query(query)
|
231
|
+
key = key_value_from_query(query)
|
232
|
+
uri = "/#{name.pluralize}/#{key}.xml"
|
233
|
+
logger.debug { "delete #{uri}" }
|
234
|
+
response = http_delete(uri)
|
235
|
+
response.kind_of?(Net::HTTPSuccess)
|
236
|
+
else
|
237
|
+
super
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# @see BaseAdapter
|
242
|
+
def delete_resource(resource)
|
243
|
+
name = resource.name
|
244
|
+
key = key_value_from_query(resource.to_queryquery)
|
245
|
+
uri = "/#{name.pluralize}/#{key}.xml"
|
246
|
+
logger.debug { "delete #{uri}" }
|
247
|
+
response = http_delete(uri)
|
248
|
+
response.kind_of?(Net::HTTPSuccess)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
|
3
|
+
def config_file()
|
4
|
+
RAILS_ROOT + "/config/database.yml"
|
5
|
+
end
|
6
|
+
|
7
|
+
def create_connection()
|
8
|
+
conf = config.dup
|
9
|
+
repositories = conf.delete(:repositories)
|
10
|
+
::DataMapper.setup(:default, conf) unless conf.empty?
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_config_for_environment
|
14
|
+
if hash = full_config[RAILS_ENV]
|
15
|
+
symbolize_keys(hash)
|
16
|
+
elsif hash = full_config[RAILS_ENV.to_sym]
|
17
|
+
hash
|
18
|
+
else
|
19
|
+
raise ArgumentError, "missing environment '#{RAILS_ENV}' in config file #{config_file}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def full_config
|
24
|
+
@full_config ||= YAML::load(ERB.new(IO.read(config_file)).result)
|
25
|
+
end
|
26
|
+
|
27
|
+
def config
|
28
|
+
@config ||= get_config_for_environment
|
29
|
+
end
|
30
|
+
|
31
|
+
def symbolize_keys(h)
|
32
|
+
config = {}
|
33
|
+
|
34
|
+
h.each do |k, v|
|
35
|
+
if k == 'port'
|
36
|
+
config[k.to_sym] = v.to_i
|
37
|
+
elsif k == 'adapter' && v == 'postgresql'
|
38
|
+
config[k.to_sym] = 'postgres'
|
39
|
+
elsif v.is_a?(Hash)
|
40
|
+
config[k.to_sym] = symbolize_keys(v)
|
41
|
+
else
|
42
|
+
config[k.to_sym] = v
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
config
|
47
|
+
end
|
48
|
+
|
49
|
+
create_connection()
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
|
3
|
+
module ActionController
|
4
|
+
module Session
|
5
|
+
class DatamapperStore < AbstractStore
|
6
|
+
|
7
|
+
def initialize(app, options = {})
|
8
|
+
super
|
9
|
+
if options.delete(:cache)
|
10
|
+
@@cache = {}
|
11
|
+
end
|
12
|
+
@@session_class = ::DatamapperStore::Session
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def get_session(env, sid)
|
17
|
+
sid ||= generate_sid
|
18
|
+
session =
|
19
|
+
if @@cache
|
20
|
+
@@cache[sid] || @@session_class.get(sid)
|
21
|
+
else
|
22
|
+
@@session_class.get(sid)
|
23
|
+
end
|
24
|
+
[sid, session.nil? ? {} : session.data]
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_session(env, sid, session_data)
|
28
|
+
session =
|
29
|
+
if @@cache
|
30
|
+
@@cache[sid] || @@session_class.get(sid)
|
31
|
+
else
|
32
|
+
@@session_class.get(sid)
|
33
|
+
end || @@session_class.new(:session_id => sid)
|
34
|
+
session.data = session_data || {}
|
35
|
+
if session.new_record?
|
36
|
+
session.updated_at = Time.now
|
37
|
+
@@cache[sid] = session if @@cache
|
38
|
+
end
|
39
|
+
session.save
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module DatamapperStore
|
46
|
+
class Session
|
47
|
+
|
48
|
+
include ::DataMapper::Resource
|
49
|
+
|
50
|
+
def self.name
|
51
|
+
"session"
|
52
|
+
end
|
53
|
+
|
54
|
+
property :session_id, String, :key => true
|
55
|
+
|
56
|
+
property :data, Text, :nullable => false, :default => ::Base64.encode64(Marshal.dump({}))
|
57
|
+
|
58
|
+
property :updated_at, DateTime, :nullable => true, :index => true
|
59
|
+
|
60
|
+
def data=(data)
|
61
|
+
attribute_set(:data, ::Base64.encode64(Marshal.dump(data)))
|
62
|
+
end
|
63
|
+
def data
|
64
|
+
Marshal.load(::Base64.decode64(attribute_get(:data)))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Datamapper4rails
|
2
|
+
module RestfulTransactions
|
3
|
+
|
4
|
+
class Rollback < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
module Base
|
8
|
+
def self.included(base)
|
9
|
+
base.prepend_around_filter(TransactionFilter)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class TransactionFilter
|
14
|
+
def self.filter(controller)
|
15
|
+
case controller.request.method
|
16
|
+
when :post, :put, :delete then
|
17
|
+
begin
|
18
|
+
DataMapper::Transaction.new(DataMapper.repository(:default)) do |*block_args|
|
19
|
+
if block_given?
|
20
|
+
yield (*block_args)
|
21
|
+
# added rollback for all actions which just render
|
22
|
+
# a page with validation errors and do not redirect to new idem potent
|
23
|
+
# page (http-method get is idem potent within the
|
24
|
+
# restful paradigma
|
25
|
+
unless controller.response.redirected_to
|
26
|
+
raise Datamapper4rails::RestfulTransactions::Rollback
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
rescue Datamapper4rails::RestfulTransactions::Rollback
|
31
|
+
# ignore,
|
32
|
+
# this is just needed to trigger the rollback on the transaction
|
33
|
+
end
|
34
|
+
else
|
35
|
+
yield if block_given?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
::ActionController::Base.send(:include, Datamapper4rails::RestfulTransactions::Base)
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: datamapper4rail
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- mkristian
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-21 00:00:00 +05:30
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: slf4r
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hoe
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.8.3
|
34
|
+
version:
|
35
|
+
description: collection of datamapper related extensions. mostly needed to run within rails. the restful transactions is around filter for rails. the restful adapter can be outside of rails. datamapper store is a session store for rails which uses datamapper as persistent layer. the generators produces datamapper models for your rails application. quite a few things are "stolen" from dm-more/rails_datamapper. a lot of things do not work there and patches are still in process to be applied so until dm-more/rails_datamapper catches up, ut I hope these two project merge someday again.
|
36
|
+
email:
|
37
|
+
- m.kristian@web.de
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files:
|
43
|
+
- History.txt
|
44
|
+
- Manifest.txt
|
45
|
+
- README.txt
|
46
|
+
files:
|
47
|
+
- History.txt
|
48
|
+
- Manifest.txt
|
49
|
+
- README.txt
|
50
|
+
- Rakefile
|
51
|
+
- generators/dm_install/dm_install_generator.rb
|
52
|
+
- generators/dm_install/templates/datamapper.rake
|
53
|
+
- generators/dm_migration/dm_migration_generator.rb
|
54
|
+
- generators/dm_migration/templates/migration.rb
|
55
|
+
- generators/dm_model/dm_model_generator.rb
|
56
|
+
- generators/dm_model/templates/model.rb
|
57
|
+
- generators/dm_model/templates/unit_test.rb
|
58
|
+
- generators/rspec_default_values.rb
|
59
|
+
- generators/rspec_dm_model/rspec_dm_model_generator.rb
|
60
|
+
- generators/rspec_dm_model/templates/model.rb
|
61
|
+
- generators/rspec_dm_model/templates/model_spec.rb
|
62
|
+
- lib/datamapper4rails.rb
|
63
|
+
- lib/datamapper4rails/adapters/base_adapter.rb
|
64
|
+
- lib/datamapper4rails/adapters/restful_adapter.rb
|
65
|
+
- lib/datamapper4rails/database_config.rb
|
66
|
+
- lib/datamapper4rails/datamapper_store.rb
|
67
|
+
- lib/datamapper4rails/restful_transactions.rb
|
68
|
+
- lib/datamapper4rails/version.rb
|
69
|
+
has_rdoc: true
|
70
|
+
homepage: http://datamapper4rail.rubyforge.org
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options:
|
73
|
+
- --main
|
74
|
+
- README.txt
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: "0"
|
82
|
+
version:
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: "0"
|
88
|
+
version:
|
89
|
+
requirements: []
|
90
|
+
|
91
|
+
rubyforge_project: datamapper4rail
|
92
|
+
rubygems_version: 1.3.1
|
93
|
+
signing_key:
|
94
|
+
specification_version: 2
|
95
|
+
summary: collection of datamapper related extensions
|
96
|
+
test_files: []
|
97
|
+
|