dm-rails 1.0.0.rc1

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.
@@ -0,0 +1,12 @@
1
+ module Rails
2
+ module DataMapper
3
+
4
+ module I18nSupport
5
+ # Set the i18n scope to overwrite ActiveModel.
6
+ def i18n_scope #:nodoc:
7
+ :data_mapper
8
+ end
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,31 @@
1
+ module DataMapper
2
+ module Railties
3
+
4
+ class LogSubscriber < Rails::LogSubscriber
5
+
6
+ def sql(event)
7
+ name = '%s (%.1fms)' % [event.payload[:name], event.duration]
8
+ sql = event.payload[:sql].squeeze(' ')
9
+
10
+ if odd?
11
+ name = color(name, :cyan, true)
12
+ sql = color(sql, nil, true)
13
+ else
14
+ name = color(name, :magenta, true)
15
+ end
16
+
17
+ debug " #{name} #{sql}"
18
+ end
19
+
20
+ def odd?
21
+ @odd_or_even = !@odd_or_even
22
+ end
23
+
24
+ def logger
25
+ ::DataMapper.logger
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,61 @@
1
+ require 'dm-core'
2
+
3
+ # Implements DataMapper-specific session store.
4
+
5
+ module Rails
6
+ module DataMapper
7
+
8
+ class SessionStore < ActionDispatch::Session::AbstractStore
9
+
10
+ class Session
11
+
12
+ include ::DataMapper::Resource
13
+
14
+ property :id, Serial
15
+ property :session_id, String, :required => true, :unique => true, :unique_index => true
16
+ property :data, Object, :required => true, :default => ActiveSupport::Base64.encode64(Marshal.dump({}))
17
+ property :updated_at, DateTime, :required => false, :index => true
18
+
19
+ def self.name
20
+ 'session'
21
+ end
22
+
23
+ end
24
+
25
+ SESSION_RECORD_KEY = 'rack.session.record'.freeze
26
+
27
+ cattr_accessor :session_class
28
+ self.session_class = Session
29
+
30
+ private
31
+
32
+ def get_session(env, sid)
33
+ sid ||= generate_sid
34
+ session = find_session(sid)
35
+ env[SESSION_RECORD_KEY] = session
36
+ [ sid, session.data ]
37
+ end
38
+
39
+ def set_session(env, sid, session_data)
40
+ session = get_session_resource(env, sid)
41
+ session.data = session_data
42
+ session.updated_at = Time.now if session.dirty?
43
+ session.save ? sid : false
44
+ end
45
+
46
+ def get_session_resource(env, sid)
47
+ if env[ENV_SESSION_OPTIONS_KEY][:id].nil?
48
+ env[SESSION_RECORD_KEY] = find_session(sid)
49
+ else
50
+ env[SESSION_RECORD_KEY] ||= find_session(sid)
51
+ end
52
+ end
53
+
54
+ def find_session(sid)
55
+ self.class.session_class.first_or_new(:session_id => sid)
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,41 @@
1
+ require 'active_support/core_ext/hash/except'
2
+
3
+ require 'dm-rails/configuration'
4
+ require 'dm-rails/railties/benchmarking_mixin'
5
+
6
+ module Rails
7
+ module DataMapper
8
+
9
+ def self.setup(environment)
10
+ puts "[datamapper] Setting up the #{environment.inspect} environment:"
11
+ configuration.repositories[environment].each do |name, config|
12
+ setup_with_instrumentation(name.to_sym, config)
13
+ end
14
+ initialize_foreign_keys
15
+ end
16
+
17
+ def self.setup_logger(logger)
18
+ ::DataMapper.logger = logger
19
+ end
20
+
21
+ def self.setup_with_instrumentation(name, options)
22
+ puts "[datamapper] Setting up #{name.inspect} repository: '#{options['database']}' on #{options['adapter']}"
23
+ adapter = ::DataMapper.setup(name, options)
24
+ adapter.extend ::DataMapper::Adapters::Benchmarking
25
+ end
26
+
27
+ def self.initialize_foreign_keys
28
+ ::DataMapper::Model.descendants.each do |model|
29
+ model.relationships.each_value { |r| r.child_key }
30
+ end
31
+ end
32
+
33
+ def self.preload_models(app)
34
+ app.config.paths.app.models.each do |path|
35
+ Dir.glob("#{path}/**/*.rb").sort.each { |file| require_dependency file }
36
+ end
37
+ initialize_foreign_keys
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,165 @@
1
+ module Rails
2
+ module DataMapper
3
+
4
+ def self.storage
5
+ Storage
6
+ end
7
+
8
+ class Storage
9
+ attr_reader :name, :config
10
+
11
+ def self.create_all
12
+ with_local_repositories { |config| create_environment(config) }
13
+ end
14
+
15
+ def self.drop_all
16
+ with_local_repositories { |config| drop_environment(config) }
17
+ end
18
+
19
+ def self.create_environment(config)
20
+ config.each { |repo_name, repo_config| new(repo_name, repo_config).create }
21
+ end
22
+
23
+ def self.drop_environment(config)
24
+ config.each { |repo_name, repo_config| new(repo_name, repo_config).drop }
25
+ end
26
+
27
+ def self.new(name, config)
28
+ klass = lookup_class(config['adapter'])
29
+ if klass.equal?(self)
30
+ super(name, config)
31
+ else
32
+ klass.new(name, config)
33
+ end
34
+ end
35
+
36
+ class << self
37
+ private
38
+
39
+ def with_local_repositories
40
+ Rails::DataMapper.configuration.repositories.each_value do |config|
41
+ if config['host'].blank? || %w[ 127.0.0.1 localhost ].include?(config['host'])
42
+ yield(config)
43
+ else
44
+ puts "This task only modifies local databases. #{config['database']} is on a remote host."
45
+ end
46
+ end
47
+ end
48
+
49
+ def lookup_class(adapter)
50
+ klass_name = adapter.camelize.to_sym
51
+
52
+ unless Storage.const_defined?(klass_name)
53
+ raise "Adapter #{adapter} not supported (#{klass_name.inspect})"
54
+ end
55
+
56
+ const_get(klass_name)
57
+ end
58
+
59
+ end
60
+
61
+ def initialize(name, config)
62
+ @name, @config = name.to_sym, config
63
+ end
64
+
65
+ def create
66
+ _create
67
+ puts "[datamapper] Created database '#{database}'"
68
+ end
69
+
70
+ def drop
71
+ _drop
72
+ puts "[datamapper] Dropped database '#{database}'"
73
+ end
74
+
75
+ def database
76
+ @database ||= config['database'] || config['path']
77
+ end
78
+
79
+ def username
80
+ @username ||= config['username'] || ''
81
+ end
82
+
83
+ def password
84
+ @password ||= config['password'] || ''
85
+ end
86
+
87
+ def charset
88
+ @charset ||= config['charset'] || ENV['CHARSET'] || 'utf8'
89
+ end
90
+
91
+ class Sqlite3 < Storage
92
+ def _create
93
+ return if in_memory?
94
+ ::DataMapper.setup(name, config.merge('database' => path))
95
+ end
96
+
97
+ def _drop
98
+ return if in_memory?
99
+ path.unlink if path.file?
100
+ end
101
+
102
+ private
103
+
104
+ def in_memory?
105
+ database == ':memory:'
106
+ end
107
+
108
+ def path
109
+ @path ||= Pathname(File.expand_path(database, Rails.root))
110
+ end
111
+
112
+ end
113
+
114
+ class Mysql < Storage
115
+ def _create
116
+ execute("CREATE DATABASE `#{database}` DEFAULT CHARACTER SET #{charset} DEFAULT COLLATE #{collation}")
117
+ end
118
+
119
+ def _drop
120
+ execute("DROP DATABASE IF EXISTS `#{database}`")
121
+ end
122
+
123
+ private
124
+
125
+ def execute(statement)
126
+ system(
127
+ 'mysql',
128
+ (username.blank? ? '' : "--user=#{username}"),
129
+ (password.blank? ? '' : "--password=#{password}"),
130
+ '-e',
131
+ statement
132
+ )
133
+ end
134
+
135
+ def collation
136
+ @collation ||= config['collation'] || ENV['COLLATION'] || 'utf8_unicode_ci'
137
+ end
138
+
139
+ end
140
+
141
+ class Postgres < Storage
142
+ def _create
143
+ system(
144
+ 'createdb',
145
+ '-E',
146
+ charset,
147
+ '-U',
148
+ username,
149
+ database
150
+ )
151
+ end
152
+
153
+ def _drop
154
+ system(
155
+ 'dropdb',
156
+ '-U',
157
+ username,
158
+ database
159
+ )
160
+ end
161
+
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,82 @@
1
+ require 'rails/generators/named_base'
2
+ require 'rails/generators/migration'
3
+ require 'rails/generators/active_model'
4
+
5
+ module DataMapper
6
+ module Generators
7
+
8
+ class Base < ::Rails::Generators::NamedBase #:nodoc:
9
+
10
+ include ::Rails::Generators::Migration
11
+
12
+ def self.source_root
13
+ @_datamapper_source_root ||=
14
+ File.expand_path("../#{base_name}/#{generator_name}/templates", __FILE__)
15
+ end
16
+
17
+ protected
18
+
19
+ # Datamapper does not care if migrations have the same name as long as
20
+ # they have different ids.
21
+ #
22
+ def migration_exists?(dirname, file_name) #:nodoc:
23
+ false
24
+ end
25
+
26
+ # Implement the required interface for Rails::Generators::Migration.
27
+ #
28
+ def self.next_migration_number(dirname) #:nodoc:
29
+ "%.3d" % (current_migration_number(dirname) + 1)
30
+ end
31
+
32
+ end
33
+
34
+ class ActiveModel < ::Rails::Generators::ActiveModel #:nodoc:
35
+ def self.all(klass)
36
+ "#{klass}.all"
37
+ end
38
+
39
+ def self.find(klass, params=nil)
40
+ "#{klass}.get(#{params})"
41
+ end
42
+
43
+ def self.build(klass, params=nil)
44
+ if params
45
+ "#{klass}.new(#{params})"
46
+ else
47
+ "#{klass}.new"
48
+ end
49
+ end
50
+
51
+ def save
52
+ "#{name}.save"
53
+ end
54
+
55
+ def update_attributes(params=nil)
56
+ "#{name}.update(#{params})"
57
+ end
58
+
59
+ def errors
60
+ "#{name}.errors"
61
+ end
62
+
63
+ def destroy
64
+ "#{name}.destroy"
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+
71
+ module Rails
72
+
73
+ module Generators
74
+ class GeneratedAttribute #:nodoc:
75
+ def type_class
76
+ return 'DateTime' if type.to_s == 'datetime'
77
+ return type.to_s.camelcase
78
+ end
79
+ end
80
+ end
81
+
82
+ end
@@ -0,0 +1,30 @@
1
+ require 'generators/data_mapper'
2
+
3
+ module DataMapper
4
+ module Generators
5
+
6
+ class MigrationGenerator < Base
7
+
8
+ argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
9
+ class_option :id, :type => :numeric, :desc => "The id to be used in this migration"
10
+
11
+ def create_migration_file
12
+ set_local_assigns!
13
+ migration_template "migration.rb", "db/migrate/#{file_name}.rb"
14
+ end
15
+
16
+ protected
17
+
18
+ attr_reader :migration_action
19
+
20
+ def set_local_assigns!
21
+ if file_name =~ /^(add|remove|drop)_.*_(?:to|from)_(.*)/
22
+ @migration_action = $1 == 'add' ? 'add' : 'drop'
23
+ @table_name = $2.pluralize
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ migration <%= migration_number.to_i %>, :<%= migration_file_name %> do
2
+
3
+ up do
4
+ <% unless attributes.empty? -%>
5
+ modify_table :<%= table_name %> do
6
+ <% attributes.each do |attribute| -%>
7
+ <%= migration_action %>_column :<%= attribute.name %><% if migration_action == 'add' %>, :<%= attribute.type_class %><% end -%>
8
+ <% end -%>
9
+ end
10
+ <% end -%>
11
+ end
12
+
13
+ down do
14
+ <% unless attributes.empty? -%>
15
+ modify_table :<%= table_name %> do
16
+ <% attributes.reverse.each do |attribute| -%>
17
+ <%= migration_action == 'add' ? 'drop' : 'add' %>_column :<%= attribute.name %><% if migration_action == 'drop' %>, :<%= attribute.type_class %><% end -%>
18
+ <% end -%>
19
+ end
20
+ <% end -%>
21
+ end
22
+
23
+ end