talia_core 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +41 -0
- data/bin/talia +33 -0
- data/lib/JXslt/jxslt.rb +60 -0
- data/lib/acts_as_roled.rb +11 -0
- data/lib/core_ext/platform.rb +9 -0
- data/lib/core_ext/string.rb +6 -0
- data/lib/core_ext.rb +1 -0
- data/lib/custom_template.rb +4 -0
- data/lib/loader_helper.rb +62 -0
- data/lib/mysql.rb +1214 -0
- data/lib/progressbar.rb +236 -0
- data/lib/role.rb +12 -0
- data/lib/talia_cl/command_line.rb +39 -0
- data/lib/talia_cl/commands/standalone/cl_options.rb +9 -0
- data/lib/talia_cl/commands/standalone/standalone_generate.rb +75 -0
- data/lib/talia_cl/commands/standalone.rb +25 -0
- data/lib/talia_cl/commands/talia_console/cl_options.rb +55 -0
- data/lib/talia_cl/commands/talia_console/console_commands.rb +37 -0
- data/lib/talia_cl/commands/talia_console/talia_commands.rb +131 -0
- data/lib/talia_cl/commands/talia_console.rb +47 -0
- data/lib/talia_cl/core_commands.rb +11 -0
- data/lib/talia_cl.rb +47 -0
- data/lib/talia_core/active_source.rb +372 -0
- data/lib/talia_core/active_source_parts/class_methods.rb +378 -0
- data/lib/talia_core/active_source_parts/predicate_handler.rb +89 -0
- data/lib/talia_core/active_source_parts/rdf.rb +131 -0
- data/lib/talia_core/active_source_parts/sql_helper.rb +36 -0
- data/lib/talia_core/active_source_parts/xml/base_builder.rb +47 -0
- data/lib/talia_core/active_source_parts/xml/generic_reader.rb +363 -0
- data/lib/talia_core/active_source_parts/xml/rdf_builder.rb +88 -0
- data/lib/talia_core/active_source_parts/xml/source_builder.rb +73 -0
- data/lib/talia_core/active_source_parts/xml/source_reader.rb +20 -0
- data/lib/talia_core/agent.rb +14 -0
- data/lib/talia_core/background_jobs/job.rb +82 -0
- data/lib/talia_core/background_jobs/progress_job.rb +68 -0
- data/lib/talia_core/collection.rb +13 -0
- data/lib/talia_core/data_types/data_loader.rb +92 -0
- data/lib/talia_core/data_types/data_record.rb +105 -0
- data/lib/talia_core/data_types/delayed_copier.rb +76 -0
- data/lib/talia_core/data_types/file_record.rb +59 -0
- data/lib/talia_core/data_types/file_store.rb +306 -0
- data/lib/talia_core/data_types/iip_data.rb +153 -0
- data/lib/talia_core/data_types/iip_loader.rb +127 -0
- data/lib/talia_core/data_types/image_data.rb +32 -0
- data/lib/talia_core/data_types/media_link.rb +19 -0
- data/lib/talia_core/data_types/mime_mapping.rb +45 -0
- data/lib/talia_core/data_types/path_helpers.rb +77 -0
- data/lib/talia_core/data_types/pdf_data.rb +42 -0
- data/lib/talia_core/data_types/simple_text.rb +36 -0
- data/lib/talia_core/data_types/temp_file_handling.rb +85 -0
- data/lib/talia_core/data_types/xml_data.rb +169 -0
- data/lib/talia_core/dc_resource.rb +20 -0
- data/lib/talia_core/dummy_handler.rb +34 -0
- data/lib/talia_core/dummy_source.rb +20 -0
- data/lib/talia_core/errors.rb +25 -0
- data/lib/talia_core/initializer.rb +427 -0
- data/lib/talia_core/ordered_source.rb +228 -0
- data/lib/talia_core/rails_ext/actionpack/action_controller/record_identifier.rb +13 -0
- data/lib/talia_core/rails_ext/actionpack/action_controller.rb +1 -0
- data/lib/talia_core/rails_ext/actionpack.rb +1 -0
- data/lib/talia_core/rails_ext.rb +1 -0
- data/lib/talia_core/rdf_import.rb +90 -0
- data/lib/talia_core/rdf_resource.rb +159 -0
- data/lib/talia_core/semantic_collection_item.rb +93 -0
- data/lib/talia_core/semantic_collection_wrapper.rb +324 -0
- data/lib/talia_core/semantic_property.rb +7 -0
- data/lib/talia_core/semantic_relation.rb +67 -0
- data/lib/talia_core/source.rb +323 -0
- data/lib/talia_core/source_transfer_object.rb +38 -0
- data/lib/talia_core/workflow/base.rb +15 -0
- data/lib/talia_core/workflow/publication_workflow.rb +62 -0
- data/lib/talia_core/workflow.rb +300 -0
- data/lib/talia_core.rb +9 -0
- data/lib/talia_dependencies.rb +12 -0
- data/lib/talia_util/bar_progressor.rb +15 -0
- data/lib/talia_util/configuration/config_file.rb +48 -0
- data/lib/talia_util/configuration/database_config.rb +40 -0
- data/lib/talia_util/configuration/mysql_database_setup.rb +104 -0
- data/lib/talia_util/data_import.rb +91 -0
- data/lib/talia_util/image_conversions.rb +82 -0
- data/lib/talia_util/import_job_helper.rb +132 -0
- data/lib/talia_util/io_helper.rb +54 -0
- data/lib/talia_util/progressable.rb +38 -0
- data/lib/talia_util/progressbar.rb +236 -0
- data/lib/talia_util/rdf_update.rb +80 -0
- data/lib/talia_util/some_sigla.xml +1960 -0
- data/lib/talia_util/test_helpers.rb +151 -0
- data/lib/talia_util/util.rb +226 -0
- data/lib/talia_util/yaml_import.rb +80 -0
- data/lib/talia_util.rb +13 -0
- data/lib/user.rb +116 -0
- data/lib/version.rb +15 -0
- data/test/core_ext/string_test.rb +11 -0
- data/test/custom_template_test.rb +8 -0
- data/test/talia_core/active_source_predicate_test.rb +54 -0
- data/test/talia_core/active_source_rdf_test.rb +89 -0
- data/test/talia_core/active_source_test.rb +631 -0
- data/test/talia_core/data_types/data_loader_test.rb +123 -0
- data/test/talia_core/data_types/data_record_test.rb +40 -0
- data/test/talia_core/data_types/file_record_test.rb +171 -0
- data/test/talia_core/data_types/iip_data_test.rb +130 -0
- data/test/talia_core/data_types/image_data_test.rb +88 -0
- data/test/talia_core/data_types/pdf_data_test.rb +68 -0
- data/test/talia_core/data_types/xml_data_test.rb +134 -0
- data/test/talia_core/generic_xml_test.rb +83 -0
- data/test/talia_core/initializer_test.rb +36 -0
- data/test/talia_core/ordered_source_test.rb +398 -0
- data/test/talia_core/rdf_resource_test.rb +115 -0
- data/test/talia_core/semantic_collection_item_test.rb +129 -0
- data/test/talia_core/source_reader_test.rb +33 -0
- data/test/talia_core/source_test.rb +484 -0
- data/test/talia_core/source_transfer_object_test.rb +24 -0
- data/test/talia_core/workflow/publication_workflow_test.rb +242 -0
- data/test/talia_core/workflow/user_class_for_workflow.rb +35 -0
- data/test/talia_core/workflow/workflow_base_test.rb +21 -0
- data/test/talia_core/workflow_test.rb +19 -0
- data/test/talia_util/import_job_helper_test.rb +46 -0
- data/test/test_helper.rb +68 -0
- metadata +262 -0
@@ -0,0 +1,300 @@
|
|
1
|
+
module TaliaCore #:nodoc:
|
2
|
+
module Workflow #:nodoc:
|
3
|
+
class InvalidState < Exception #:nodoc:
|
4
|
+
end
|
5
|
+
class NoInitialState < Exception #:nodoc:
|
6
|
+
end
|
7
|
+
class NoAuthorizedException < Exception #:nodoc:
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def self.included(base) #:nodoc:
|
12
|
+
base.extend WorkflowMacro
|
13
|
+
end
|
14
|
+
|
15
|
+
module SupportingClasses
|
16
|
+
class State
|
17
|
+
attr_reader :name
|
18
|
+
|
19
|
+
def initialize(name, opts)
|
20
|
+
@name, @opts = name, opts
|
21
|
+
end
|
22
|
+
|
23
|
+
def entering(record)
|
24
|
+
enteract = @opts[:enter]
|
25
|
+
record.send(:run_transition_action, enteract) if enteract
|
26
|
+
end
|
27
|
+
|
28
|
+
def entered(record)
|
29
|
+
afteractions = @opts[:after]
|
30
|
+
return unless afteractions
|
31
|
+
Array(afteractions).each do |afteract|
|
32
|
+
record.send(:run_transition_action, afteract)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def exited(record)
|
37
|
+
exitact = @opts[:exit]
|
38
|
+
record.send(:run_transition_action, exitact) if exitact
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class StateTransition
|
43
|
+
attr_reader :from, :to, :opts
|
44
|
+
|
45
|
+
def initialize(opts)
|
46
|
+
@from, @to, @guard = opts[:from], opts[:to], opts[:guard]
|
47
|
+
@opts = opts
|
48
|
+
end
|
49
|
+
|
50
|
+
def guard(obj, args)
|
51
|
+
@guard ? obj.send(:run_transition_action, @guard, args) : true
|
52
|
+
end
|
53
|
+
|
54
|
+
def on_transition(obj, args = nil)
|
55
|
+
action = @opts[:on_transition]
|
56
|
+
obj.send(:run_transition_action, action, args) if action
|
57
|
+
end
|
58
|
+
|
59
|
+
def perform(record, args = nil)
|
60
|
+
return false unless guard(record, args)
|
61
|
+
loopback = record.current_state == to
|
62
|
+
states = record.class.read_inheritable_attribute(:states)
|
63
|
+
next_state = states[to]
|
64
|
+
old_state = states[record.current_state]
|
65
|
+
|
66
|
+
# permform action
|
67
|
+
on_transition(record, args)
|
68
|
+
|
69
|
+
next_state.entering(record) unless loopback
|
70
|
+
|
71
|
+
record.update_attribute(record.class.state_column, to.to_s)
|
72
|
+
|
73
|
+
next_state.entered(record) unless loopback
|
74
|
+
old_state.exited(record) unless loopback
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
def ==(obj)
|
79
|
+
@from == obj.from && @to == obj.to
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Event
|
84
|
+
attr_reader :name
|
85
|
+
attr_reader :transitions
|
86
|
+
attr_reader :opts
|
87
|
+
|
88
|
+
def initialize(name, opts, transition_table, &block)
|
89
|
+
@name = name.to_sym
|
90
|
+
@transitions = transition_table[@name] = []
|
91
|
+
instance_eval(&block) if block
|
92
|
+
@opts = opts
|
93
|
+
@opts.freeze
|
94
|
+
@transitions.freeze
|
95
|
+
freeze
|
96
|
+
end
|
97
|
+
|
98
|
+
def next_states(record)
|
99
|
+
@transitions.select { |t| t.from == record.current_state }
|
100
|
+
end
|
101
|
+
|
102
|
+
def fire(record, user, args = nil)
|
103
|
+
# check user role
|
104
|
+
unless @opts[:require_role].nil?
|
105
|
+
raise NoAuthorizedException unless user.authorized_as?(@opts[:require_role])
|
106
|
+
end
|
107
|
+
|
108
|
+
# perform transition
|
109
|
+
next_states(record).each do |transition|
|
110
|
+
break true if transition.perform(record, args)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def transitions(trans_opts)
|
115
|
+
Array(trans_opts[:from]).each do |s|
|
116
|
+
@transitions << SupportingClasses::StateTransition.new(trans_opts.merge({:from => s.to_sym}))
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
module WorkflowMacro
|
123
|
+
# Configuration options are
|
124
|
+
#
|
125
|
+
# * +column+ - specifies the column name to use for keeping the state (default: state)
|
126
|
+
# * +property+ - specifies the column name to use for keeping the property of current state (default: state_properties)
|
127
|
+
# * +initial+ - specifies an initial state for newly created objects (required)
|
128
|
+
def workflow_machine(opts)
|
129
|
+
self.extend(ClassMethods)
|
130
|
+
raise NoInitialState unless opts[:initial]
|
131
|
+
|
132
|
+
write_inheritable_attribute :states, {}
|
133
|
+
write_inheritable_attribute :initial_state, opts[:initial]
|
134
|
+
write_inheritable_attribute :initial_state_properties, opts[:initial_properties] || {}
|
135
|
+
write_inheritable_attribute :transition_table, {}
|
136
|
+
write_inheritable_attribute :event_table, {}
|
137
|
+
write_inheritable_attribute :state_column, opts[:column] || 'state'
|
138
|
+
write_inheritable_attribute :state_properties_column, opts[:properties] || 'state_properties'
|
139
|
+
|
140
|
+
class_inheritable_reader :initial_state
|
141
|
+
class_inheritable_reader :initial_state_properties
|
142
|
+
class_inheritable_reader :state_column
|
143
|
+
class_inheritable_reader :state_properties_column
|
144
|
+
class_inheritable_reader :transition_table
|
145
|
+
class_inheritable_reader :event_table
|
146
|
+
|
147
|
+
self.send(:include, TaliaCore::Workflow::InstanceMethods)
|
148
|
+
|
149
|
+
before_create :set_initial_state, :set_initial_state_properties
|
150
|
+
after_create :run_initial_state_actions
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
module InstanceMethods
|
155
|
+
def state_properties
|
156
|
+
Marshal.load(self.send(self.class.state_properties_column))
|
157
|
+
end
|
158
|
+
|
159
|
+
def state_properties=(value)
|
160
|
+
write_attribute self.class.state_properties_column, Marshal.dump(value)
|
161
|
+
end
|
162
|
+
|
163
|
+
def set_initial_state #:nodoc:
|
164
|
+
write_attribute self.class.state_column, self.class.initial_state.to_s
|
165
|
+
end
|
166
|
+
|
167
|
+
def set_initial_state_properties #:nodoc:
|
168
|
+
write_attribute self.class.state_properties_column, Marshal.dump(self.class.initial_state_properties)
|
169
|
+
end
|
170
|
+
|
171
|
+
def run_initial_state_actions
|
172
|
+
initial = self.class.read_inheritable_attribute(:states)[self.class.initial_state.to_sym]
|
173
|
+
initial.entering(self)
|
174
|
+
initial.entered(self)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Returns the current state the object is in, as a Ruby symbol.
|
178
|
+
def current_state
|
179
|
+
self.send(self.class.state_column).to_sym
|
180
|
+
end
|
181
|
+
|
182
|
+
# Returns what the next state for a given event would be, as a Ruby symbol.
|
183
|
+
def next_state_for_event(event)
|
184
|
+
ns = next_states_for_event(event)
|
185
|
+
ns.empty? ? nil : ns.first.to
|
186
|
+
end
|
187
|
+
|
188
|
+
def next_states_for_event(event)
|
189
|
+
self.class.read_inheritable_attribute(:transition_table)[event.to_sym].select do |s|
|
190
|
+
s.from == current_state
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def run_transition_action(action, args = nil)
|
195
|
+
Symbol === action ? self.method(action).call(args) : action.call(self)
|
196
|
+
end
|
197
|
+
private :run_transition_action
|
198
|
+
end
|
199
|
+
|
200
|
+
module ClassMethods
|
201
|
+
# Returns an array of all known states.
|
202
|
+
def states
|
203
|
+
read_inheritable_attribute(:states).keys
|
204
|
+
end
|
205
|
+
|
206
|
+
# Define an event. This takes a block which describes all valid transitions
|
207
|
+
# for this event.
|
208
|
+
#
|
209
|
+
# Example:
|
210
|
+
#
|
211
|
+
# class Order < ActiveRecord::Base
|
212
|
+
# acts_as_state_machine :initial => :open
|
213
|
+
#
|
214
|
+
# state :open
|
215
|
+
# state :closed
|
216
|
+
#
|
217
|
+
# event :close_order do
|
218
|
+
# transitions :to => :closed, :from => :open
|
219
|
+
# end
|
220
|
+
# end
|
221
|
+
#
|
222
|
+
# +transitions+ takes a hash where <tt>:to</tt> is the state to transition
|
223
|
+
# to and <tt>:from</tt> is a state (or Array of states) from which this
|
224
|
+
# event can be fired.
|
225
|
+
#
|
226
|
+
# This creates an instance method used for firing the event. The method
|
227
|
+
# created is the name of the event followed by an exclamation point (!).
|
228
|
+
# Example: <tt>order.close_order!</tt>.
|
229
|
+
def event(event, opts={}, &block)
|
230
|
+
tt = read_inheritable_attribute(:transition_table)
|
231
|
+
|
232
|
+
et = read_inheritable_attribute(:event_table)
|
233
|
+
e = et[event.to_sym] = SupportingClasses::Event.new(event, opts, tt, &block)
|
234
|
+
define_method("#{event.to_s}!") { |user, *args| e.fire(self, user, args) }
|
235
|
+
end
|
236
|
+
|
237
|
+
# Define a state of the system. +state+ can take an optional Proc object
|
238
|
+
# which will be executed every time the system transitions into that
|
239
|
+
# state. The proc will be passed the current object.
|
240
|
+
#
|
241
|
+
# Example:
|
242
|
+
#
|
243
|
+
# class Order < ActiveRecord::Base
|
244
|
+
# acts_as_state_machine :initial => :open
|
245
|
+
#
|
246
|
+
# state :open
|
247
|
+
# state :closed, Proc.new { |o| Mailer.send_notice(o) }
|
248
|
+
# end
|
249
|
+
def state(name, opts={})
|
250
|
+
state = SupportingClasses::State.new(name.to_sym, opts)
|
251
|
+
read_inheritable_attribute(:states)[name.to_sym] = state
|
252
|
+
|
253
|
+
define_method("#{state.name}?") { current_state == state.name }
|
254
|
+
end
|
255
|
+
|
256
|
+
# Wraps ActiveRecord::Base.find to conveniently find all records in
|
257
|
+
# a given state. Options:
|
258
|
+
#
|
259
|
+
# * +number+ - This is just :first or :all from ActiveRecord +find+
|
260
|
+
# * +state+ - The state to find
|
261
|
+
# * +args+ - The rest of the args are passed down to ActiveRecord +find+
|
262
|
+
def find_in_state(number, state, *args)
|
263
|
+
with_state_scope state do
|
264
|
+
find(number, *args)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# Wraps ActiveRecord::Base.count to conveniently count all records in
|
269
|
+
# a given state. Options:
|
270
|
+
#
|
271
|
+
# * +state+ - The state to find
|
272
|
+
# * +args+ - The rest of the args are passed down to ActiveRecord +find+
|
273
|
+
def count_in_state(state, *args)
|
274
|
+
with_state_scope state do
|
275
|
+
count(*args)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# Wraps ActiveRecord::Base.calculate to conveniently calculate all records in
|
280
|
+
# a given state. Options:
|
281
|
+
#
|
282
|
+
# * +state+ - The state to find
|
283
|
+
# * +args+ - The rest of the args are passed down to ActiveRecord +calculate+
|
284
|
+
def calculate_in_state(state, *args)
|
285
|
+
with_state_scope state do
|
286
|
+
calculate(*args)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
protected
|
291
|
+
def with_state_scope(state)
|
292
|
+
raise InvalidState unless states.include?(state)
|
293
|
+
|
294
|
+
with_scope :find => {:conditions => ["#{table_name}.#{state_column} = ?", state.to_s]} do
|
295
|
+
yield if block_given?
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
data/lib/talia_core.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# TaliaCore loader
|
2
|
+
require File.dirname(__FILE__) + '/loader_helper'
|
3
|
+
|
4
|
+
# This is also needed for local loading
|
5
|
+
RAILS_GEM_VERSION = '2.3.4' unless defined? RAILS_GEM_VERSION
|
6
|
+
|
7
|
+
# Stuff we may need to load from sources/uninstalled versions
|
8
|
+
TLoad::require_module("assit", "assit", "/../../assit") unless(defined?(assit))
|
9
|
+
TLoad::require_module("activerdf", "active_rdf", "/../../ActiveRDF")
|
10
|
+
TLoad::require_module("semantic_naming", "semantic_naming", "/../../semantic_naming")
|
11
|
+
|
12
|
+
require 'version'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'progressbar')
|
2
|
+
|
3
|
+
module TaliaUtil
|
4
|
+
|
5
|
+
# Helper class for command-line progress bars as progressor objects
|
6
|
+
class BarProgressor
|
7
|
+
|
8
|
+
def self.run_with_progress(message, size)
|
9
|
+
progress = ProgressBar.new(message, size)
|
10
|
+
yield(progress)
|
11
|
+
progress.finish
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module TaliaUtil
|
4
|
+
module Configuration
|
5
|
+
|
6
|
+
# This is an object representation of a configuration file, the elements
|
7
|
+
# of the file can be directly accessed using dynamic getters/setters on the
|
8
|
+
# the class.
|
9
|
+
class ConfigFile
|
10
|
+
|
11
|
+
# Initialize from the given template
|
12
|
+
def initialize(template)
|
13
|
+
@config_doc = YAML::load_file(template)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Write the configuration to the given file
|
17
|
+
def write(file)
|
18
|
+
open(file, 'w') { |io| io.puts(@config_doc.to_yaml) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def [](id)
|
22
|
+
@config_doc[id]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Automatically creates "accessors" for the config properties.
|
26
|
+
def method_missing(method, *params)
|
27
|
+
method = method.to_s
|
28
|
+
assign = method[-1..-1] == '=' # True if last char is a =
|
29
|
+
|
30
|
+
result = nil
|
31
|
+
|
32
|
+
if(assign)
|
33
|
+
return super if(params.size != 1)
|
34
|
+
result = @config_doc[method[0..-2]] = params[0]
|
35
|
+
else
|
36
|
+
return super if(params.size != 0)
|
37
|
+
result = @config_doc[method]
|
38
|
+
end
|
39
|
+
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/config_file'
|
2
|
+
|
3
|
+
module TaliaUtil
|
4
|
+
module Configuration
|
5
|
+
|
6
|
+
# This contains some special methods for database config files
|
7
|
+
class DatabaseConfig < ConfigFile
|
8
|
+
|
9
|
+
def initialize(template)
|
10
|
+
@environments = ['test', 'development', 'production']
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
# Set the credentials for all environments
|
15
|
+
def set_credentials(db_user, db_pass)
|
16
|
+
@environments.each do |env|
|
17
|
+
@config_doc[env]['username'] = db_user
|
18
|
+
@config_doc[env]['password'] = db_pass
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sets the database adapter for all environments
|
23
|
+
def set_adapter(db_adapter)
|
24
|
+
@environments.each { |env| @config_doc[env]['adapter'] = db_adapter }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Sets the database names based on the given application name
|
28
|
+
def set_database_names(app_name)
|
29
|
+
@environments.each { |env| @config_doc[env]['database'] = "#{app_name}_#{env}" }
|
30
|
+
end
|
31
|
+
|
32
|
+
# Sets the socket file for the db
|
33
|
+
def set_socket(socket)
|
34
|
+
@environments.each { |env| @config_doc[env]['socket'] = socket }
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module TaliaUtil
|
4
|
+
module Configuration
|
5
|
+
|
6
|
+
# This contains some methods to set mysql databases on a production system
|
7
|
+
# from scratch. Setting the root password will apply immediately, the SQL
|
8
|
+
# operations will be cached and applied in one go.
|
9
|
+
class MysqlDatabaseSetup
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@sql_statements = []
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :host
|
16
|
+
attr_accessor :app_name
|
17
|
+
attr_accessor :sock
|
18
|
+
attr_accessor :db_prefix # Prefix for having multiple databases on one install
|
19
|
+
|
20
|
+
# Set the root user/pw
|
21
|
+
def root_credentials(root_user = 'root', root_pw = nil)
|
22
|
+
@root_user = root_user
|
23
|
+
@root_pw = root_pw
|
24
|
+
end
|
25
|
+
|
26
|
+
# Set the normal user/pw
|
27
|
+
def rails_credentials(rails_user, rails_pw)
|
28
|
+
@rails_user = rails_user
|
29
|
+
@rails_pw = rails_pw
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# Assign a new root password
|
34
|
+
def assign_root_pw(new_root_pw)
|
35
|
+
success = mysqladmin("password #{new_root_pw}")
|
36
|
+
@root_pw = new_root_pw if(success)
|
37
|
+
success
|
38
|
+
end
|
39
|
+
|
40
|
+
# Create the given database and set the permssions on it
|
41
|
+
def create_database(database)
|
42
|
+
raise(ArgumentError, "Credentials incomplete") unless(@rails_user && @rails_pw)
|
43
|
+
@sql_statements << "CREATE DATABASE #{database};"
|
44
|
+
@sql_statements << "GRANT ALL ON #{database}.* TO '#{@rails_user}'@'#{@host || 'localhost'}' IDENTIFIED BY '#{@rails_pw}'"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Creates the default databases for the application. You can call back a
|
48
|
+
# block for each db to do something depending on the success of the
|
49
|
+
# operation
|
50
|
+
def create_default_databases
|
51
|
+
raise(ArgumentError, "App name not set") unless(@app_name)
|
52
|
+
%w(production test development).each do |db_suffix|
|
53
|
+
db_name = "#{db_prefix}#{@app_name}_#{db_suffix}"
|
54
|
+
create_database(db_name)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Executes all stored statements
|
59
|
+
def execute
|
60
|
+
execute_as_root do |connection|
|
61
|
+
connection.transaction do
|
62
|
+
@sql_statements.each do |statement|
|
63
|
+
connection.execute(statement)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# Call the mysqladmin command (as root)
|
72
|
+
def mysqladmin(command)
|
73
|
+
if(@root_pw)
|
74
|
+
system("mysqladmin -u #{@root_user} #{command}")
|
75
|
+
else
|
76
|
+
system("mysqladmin -u #{@root_user} -p#{@root_pw} #{command}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Calls sql commands on the database using root credentials. The open
|
81
|
+
# database (ActiveRecord) connection will be passed. This will open
|
82
|
+
# the given database.
|
83
|
+
def execute_as_root(database = nil)
|
84
|
+
ActiveRecord::Base.establish_connection(root_con_opts(database))
|
85
|
+
yield(ActiveRecord::Base.connection)
|
86
|
+
ActiveRecord::Base.remove_connection
|
87
|
+
end
|
88
|
+
|
89
|
+
# options for root connection
|
90
|
+
def root_con_opts(database)
|
91
|
+
{
|
92
|
+
:adapter => "mysql",
|
93
|
+
:host => @host || "localhost",
|
94
|
+
:username => @root_user,
|
95
|
+
:password => @root_pw,
|
96
|
+
:database => database,
|
97
|
+
:socket => @sock || '/tmp/mysql.sock'
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module TaliaUtil
|
4
|
+
|
5
|
+
# Import data files into the Talia store. This can be used to bootstrap
|
6
|
+
# simple installations
|
7
|
+
class DataImport
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# Import files with the given type. This is a simple import feature,
|
12
|
+
# it's assumed that the file (without extension is named like the
|
13
|
+
# Source it should be assigned to.
|
14
|
+
def import(files, type)
|
15
|
+
|
16
|
+
# First get the class for the data type and the directory
|
17
|
+
data_klass = get_data_class(type)
|
18
|
+
replace = ENV['replace_files'] && (ENV['replace_files'] == "yes")
|
19
|
+
|
20
|
+
progress = ProgressBar.new("Importing #{data_klass}", files.size)
|
21
|
+
not_found = []
|
22
|
+
created = 0
|
23
|
+
|
24
|
+
files.each do |file|
|
25
|
+
# Get the basename without extension and additions. This strips off
|
26
|
+
# everything after the first point or - character. Examples:
|
27
|
+
# book.html
|
28
|
+
# book-picture.jpg
|
29
|
+
# => Will all be assigned to "book"
|
30
|
+
name = File.basename(file).gsub(/[-|\.].+$/, '')
|
31
|
+
if(TaliaCore::Source.exists?(name))
|
32
|
+
src = TaliaCore::Source.find(name)
|
33
|
+
|
34
|
+
# Get the filename with extension
|
35
|
+
file_name = File.basename(file)
|
36
|
+
|
37
|
+
# Create the record if necessary
|
38
|
+
unless(data = src.data_records.find_by_location(file_name))
|
39
|
+
data = data_klass.new
|
40
|
+
File.open(file) do |io|
|
41
|
+
data.create_from_data(file_name, io)
|
42
|
+
end
|
43
|
+
src.data_records << data
|
44
|
+
src.save!
|
45
|
+
data.save!
|
46
|
+
created += 1
|
47
|
+
end
|
48
|
+
else
|
49
|
+
not_found << file
|
50
|
+
end
|
51
|
+
progress.inc
|
52
|
+
end
|
53
|
+
|
54
|
+
progress.finish
|
55
|
+
puts "Done, #{not_found.size} of #{files.size} files had no record associated."
|
56
|
+
puts "#{created} new records created."
|
57
|
+
puts "\nNot found:" unless(not_found.size == 0)
|
58
|
+
not_found.each { |file| puts file}
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# Get the data class for the type. That does some sanity checks
|
63
|
+
def get_data_class(type)
|
64
|
+
data_klass = nil
|
65
|
+
begin
|
66
|
+
data_klass = TaliaCore::DataTypes.const_get(type)
|
67
|
+
rescue Exception => e
|
68
|
+
puts("Could get the data type #{type}: #{e}")
|
69
|
+
Util.print_options
|
70
|
+
exit(1)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Do the basic check
|
74
|
+
unless(data_klass && data_klass.kind_of?(Class) && data_klass.method_defined?('data_directory'))
|
75
|
+
puts("Cannot create data class from #{type}")
|
76
|
+
exit(1)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Now check if we are a subclass of the data class
|
80
|
+
my_instance = data_klass.new
|
81
|
+
|
82
|
+
unless(my_instance.kind_of?(TaliaCore::DataTypes::DataRecord))
|
83
|
+
puts("The class #{data_klass} is not a DataRecord, can't create data for it.")
|
84
|
+
exit(1)
|
85
|
+
end
|
86
|
+
|
87
|
+
data_klass
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|