hydra-tutorial 0.1.3 → 0.2.0
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.
- data/.gitignore +2 -0
- data/README.md +92 -22
- data/bin/hydra-tutorial +4 -2
- data/development_notes.txt +476 -0
- data/hydra-tutorial.gemspec +9 -11
- data/{templates → old_tutorial/templates}/application/dataset_hydra_mods_om.rb +0 -0
- data/{templates → old_tutorial/templates}/application/dataset_hydra_om.rb +0 -0
- data/{templates → old_tutorial/templates}/application/datasets_controller.rb +0 -0
- data/{or_templates/adding_our_models → old_tutorial/templates/application}/mods_desc_metadata.rb +0 -0
- data/{templates → old_tutorial/templates}/building_a_basic_rails_app/dataset_af_om.rb +0 -0
- data/{templates → old_tutorial/templates}/building_a_basic_rails_app/dataset_simple_om.rb +0 -0
- data/{or_templates → old_tutorial/templates}/building_a_basic_rails_app/fedora.yml +0 -0
- data/{templates → old_tutorial/templates}/building_a_basic_rails_app/om_record.rb +0 -0
- data/{or_templates → old_tutorial/templates}/building_a_basic_rails_app/solr.yml +0 -0
- data/old_tutorial/tutorial.thor +493 -0
- data/{or_templates/sprinkle_some_styling → templates}/_add_assets_links.html.erb +0 -0
- data/{or_templates/add_file_upload/_form.html.erb → templates/_form.add_file_upload.html.erb} +0 -0
- data/{or_templates/wiring_it_into_rails/_form.html.erb → templates/_form.wiring_it_into_rails.html.erb} +0 -0
- data/{or_templates/adding_our_models → templates}/basic_af_model.rb +0 -0
- data/{or_templates/adding_our_models → templates}/basic_mods_model.rb +0 -0
- data/{or_templates/adding_our_models → templates}/basic_om_model.rb +0 -0
- data/{or_templates/add_tests → templates}/ci.rake +0 -0
- data/{or_templates/add_tests → templates}/ci_with_coverage.rake +0 -0
- data/templates/{building_a_basic_rails_app/fedora.yml → fedora.yml} +0 -0
- data/{or_templates/add_tests → templates}/integration_spec.rb +0 -0
- data/templates/{application/mods_desc_metadata.rb → mods_desc_metadata.rb} +0 -0
- data/{or_templates → templates}/records_controller.rb +0 -0
- data/{or_templates/add_tests → templates}/records_controller_spec.rb +0 -0
- data/{or_templates/wiring_it_into_rails → templates}/show.html.erb +0 -0
- data/templates/{building_a_basic_rails_app/solr.yml → solr.yml} +0 -0
- data/tutorial.thor +806 -341
- metadata +32 -30
- data/open-repositories-tutorial.thor +0 -888
File without changes
|
data/{or_templates/add_file_upload/_form.html.erb → templates/_form.add_file_upload.html.erb}
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/tutorial.thor
CHANGED
@@ -1,493 +1,958 @@
|
|
1
|
-
|
1
|
+
#! /usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'thor'
|
5
5
|
require 'thor/group'
|
6
6
|
require 'rails/generators/actions'
|
7
7
|
require 'active_support/core_ext/array/extract_options'
|
8
|
+
require 'active_support/core_ext/string/inflections'
|
9
|
+
require 'fileutils'
|
10
|
+
require 'yaml'
|
11
|
+
require 'set'
|
8
12
|
|
9
|
-
|
13
|
+
# Colors used in messages to the user.
|
14
|
+
STATEMENT = Thor::Shell::Color::YELLOW
|
15
|
+
QUESTION = Thor::Shell::Color::GREEN
|
16
|
+
WAIT = Thor::Shell::Color::CYAN
|
17
|
+
WARNING = Thor::Shell::Color::RED
|
10
18
|
|
11
|
-
class HydraTutorialApp < Thor::Group
|
12
|
-
class_option :quick, :default => false
|
13
19
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
Welcome to this Hydra tutorial. We're going to go through some steps to
|
18
|
-
set up a working Hydra head. We'll build the application gradually, and give you
|
19
|
-
opportunities to stop and look around on the way.
|
20
|
-
}, Thor::Shell::Color::YELLOW
|
20
|
+
####
|
21
|
+
# Some utility methods used by the tutorial.
|
22
|
+
####
|
21
23
|
|
22
|
-
|
23
|
-
say %Q{
|
24
|
-
We'll quickly build the application, give you some Hydra models, and send you on your way.
|
25
|
-
}, Thor::Shell::Color::YELLOW
|
24
|
+
module HydraTutorialHelpers
|
26
25
|
|
27
|
-
|
28
|
-
say %Q{
|
29
|
-
We'll go through this tour slowly, starting by creating a pure Rails application,
|
30
|
-
and then introduce Hydra components. If you want to speed things along,
|
31
|
-
}, Thor::Shell::Color::YELLOW
|
32
|
-
|
33
|
-
exit unless yes? %Q{
|
34
|
-
If you want to speed things along, you should quit this tutorial (by saying 'no'),
|
35
|
-
and run it again with ./tutorial.thor --quick=yes.
|
26
|
+
@@conf = nil
|
36
27
|
|
37
|
-
|
38
|
-
|
28
|
+
# Runs the Rails console for the user.
|
29
|
+
def rails_console
|
30
|
+
return if @@conf.quick
|
31
|
+
say %Q{
|
32
|
+
We'll launch the console again. Give some of those commands a try.\n}, STATEMENT
|
33
|
+
say %Q{
|
34
|
+
Hit Ctrl-D (^D) to stop the Rails console and continue this tutorial.\n}, WAIT
|
35
|
+
run "rails c"
|
39
36
|
end
|
40
37
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
38
|
+
# Runs the Rails server for the user, optionally
|
39
|
+
# directing their attention to a particular URL.
|
40
|
+
def rails_server url = '/'
|
41
|
+
return if @@conf.quick
|
42
|
+
say %Q{
|
43
|
+
We'll start the Rails server for you. It should be available in
|
44
|
+
your browser at:
|
48
45
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
46
|
+
http://localhost:3000#{url}\n}, STATEMENT
|
47
|
+
say %Q{
|
48
|
+
Hit Ctrl-C (^C) to stop the Rails server and continue this tutorial.\n}, WAIT
|
49
|
+
run "rails s"
|
50
|
+
end
|
54
51
|
|
52
|
+
# Offers the user a continue prompt. This is relevant only if
|
53
|
+
# the user is running all steps at once rather than one by one.
|
54
|
+
def continue_prompt
|
55
|
+
return if @@conf.quick
|
56
|
+
return unless @@conf.run_all
|
57
|
+
ask %Q{
|
58
|
+
HIT <ENTER> KEY TO CONTINUE}, WAIT
|
59
|
+
end
|
55
60
|
|
56
|
-
|
61
|
+
# Takes a commit message an an optional array of git commands.
|
62
|
+
# Runs either the given commands or the default commands.
|
63
|
+
def run_git(msg, *cmds)
|
64
|
+
return if @@conf.no_git
|
65
|
+
cmds = ['add -A', 'commit -m'] if cmds.size == 0
|
66
|
+
cmds.each do |cmd|
|
67
|
+
cmd += " '#{msg}'" if cmd =~ /^commit/
|
68
|
+
run "git #{cmd}", :capture => false
|
69
|
+
end
|
70
|
+
end
|
57
71
|
|
58
|
-
|
59
|
-
You are running this using:
|
60
|
-
#{ruby_executable}
|
61
|
-
}, Thor::Shell::Color::YELLOW
|
72
|
+
end
|
62
73
|
|
63
|
-
if ruby_executable =~ /rvm/ or ruby_executable =~ /rbenv/ or ruby_executable =~ /home/ or ruby_Executable =~ /Users/
|
64
|
-
say %Q{
|
65
|
-
It looks like you're using rvm/rbenv/etc. (with a gemset?) We'll use this environment to build the application.
|
66
|
-
}, Thor::Shell::Color::YELLOW
|
67
74
|
|
68
|
-
|
75
|
+
####
|
76
|
+
# The tutorial contains the following major components:
|
77
|
+
#
|
78
|
+
# - A couple of class methods to define the steps in the tutorial.
|
79
|
+
# Each step is a Thor task.
|
80
|
+
#
|
81
|
+
# - A main() task. This is the task invoked when the user runs
|
82
|
+
# the bin/hydra-tutorial script. It's job is to determine
|
83
|
+
# the which steps to run (either the next step in the process
|
84
|
+
# or the specific steps requested on the command line). As
|
85
|
+
# the main() task invokes those other tasks, it also persists
|
86
|
+
# information to a YAML file to keep track of the user's
|
87
|
+
# progress through the tutorial.
|
88
|
+
#
|
89
|
+
# - The other tasks: these are the steps in the tutorial, defined
|
90
|
+
# in the order that they should be run.
|
91
|
+
#
|
92
|
+
####
|
93
|
+
|
94
|
+
class HydraTutorial < Thor
|
69
95
|
|
70
|
-
|
71
|
-
|
72
|
-
|
96
|
+
include Thor::Actions
|
97
|
+
include Rails::Generators::Actions
|
98
|
+
include HydraTutorialHelpers
|
73
99
|
|
74
|
-
|
75
|
-
|
76
|
-
|
100
|
+
# Returns an array of task names for the tasks that
|
101
|
+
# constituting the steps in the tutorial.
|
102
|
+
def self.tutorial_tasks
|
103
|
+
return tasks.keys.reject { |t| t == 'main' }
|
104
|
+
end
|
77
105
|
|
78
|
-
|
79
|
-
|
106
|
+
# Returns a set of task names for the tasks that should not
|
107
|
+
# be run inside the Rails application directory.
|
108
|
+
def self.outside_tasks
|
109
|
+
return Set.new(%w(
|
110
|
+
welcome
|
111
|
+
install_ruby
|
112
|
+
install_bundler_and_rails
|
113
|
+
new_rails_app
|
114
|
+
))
|
115
|
+
end
|
80
116
|
|
81
|
-
|
82
|
-
|
83
|
-
|
117
|
+
# Returns array of directory paths used by Thor to find
|
118
|
+
# source files when running copy_file().
|
119
|
+
def self.source_paths
|
120
|
+
[@@conf.templates_path]
|
121
|
+
end
|
84
122
|
|
123
|
+
####
|
124
|
+
# The main task that is invoked by the gem's executable script.
|
125
|
+
#
|
126
|
+
# This task invokes either the next task in the tutorial or
|
127
|
+
# the task(s) explicitly requested by the user.
|
128
|
+
####
|
129
|
+
|
130
|
+
# Define a Struct that we will use hold some global values we need.
|
131
|
+
# An instance of this Struct will be kept in @@conf.
|
132
|
+
HTConf = Struct.new(
|
133
|
+
# Command-line options.
|
134
|
+
:run_all, # If true, run all remaining tasks rather than only the next task.
|
135
|
+
:quick, # If true, bypass interactive user confirmations.
|
136
|
+
:reset, # If true, reset the tutorial back to the beginning.
|
137
|
+
:gems_from_git, # If true, get a couple of gems directly from github.
|
138
|
+
:debug_steps, # If true, just print task names rather than running tasks.
|
139
|
+
:no_git, # If true, do not create Git commits as the Rails app is modified.
|
140
|
+
:diff, # If true, run git diff: previous vs. current code.
|
141
|
+
:app, # Name of the Rails application's subdirectory.
|
142
|
+
|
143
|
+
# Other config.
|
144
|
+
:progress_file, # Name of YAML file used to keep track of finished steps.
|
145
|
+
:done, # Array of tasks that have been completed already.
|
146
|
+
:templates_path # Directory where Thor can file source files for copy_file().
|
147
|
+
)
|
148
|
+
|
149
|
+
# Command-line options for the main() method.
|
150
|
+
desc('main: FIX', 'FIX')
|
151
|
+
method_options(
|
152
|
+
:run_all => :boolean,
|
153
|
+
:quick => :boolean,
|
154
|
+
:reset => :boolean,
|
155
|
+
:gems_from_git => :boolean,
|
156
|
+
:debug_steps => :boolean,
|
157
|
+
:no_git => :boolean,
|
158
|
+
:diff => :boolean,
|
159
|
+
:app => :string
|
160
|
+
)
|
161
|
+
|
162
|
+
def main(*requested_tasks)
|
163
|
+
# Setup.
|
164
|
+
HydraTutorial.initialize_config(options)
|
165
|
+
HydraTutorial.initialize_progress_file
|
166
|
+
HydraTutorial.load_progress_info
|
167
|
+
ts = HydraTutorial.determine_tasks_to_run(requested_tasks)
|
168
|
+
outside = HydraTutorial.outside_tasks
|
169
|
+
|
170
|
+
# If user requests --diff, just run git diff and exit.
|
171
|
+
if @@conf.diff
|
172
|
+
inside(@@conf.app) { run 'git diff HEAD^1..HEAD' }
|
173
|
+
exit
|
85
174
|
end
|
86
175
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
176
|
+
# Run tasks.
|
177
|
+
ts.each do |t|
|
178
|
+
# Either print the task that would be run (in debug mode) or run the task.
|
179
|
+
if @@conf.debug_steps
|
180
|
+
say "Running: task=#{t.inspect}", STATEMENT
|
181
|
+
else
|
182
|
+
# A few of the initial tasks run outside the Rails app directory,
|
183
|
+
# but most run inside the app directory.
|
184
|
+
if outside.include?(t)
|
185
|
+
invoke(t, [], {})
|
186
|
+
else
|
187
|
+
inside(@@conf.app) { invoke(t, [], {}) }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
# Persist the fact that the task was run to the YAML progress file.
|
191
|
+
@@conf.done << t
|
192
|
+
File.open(@@conf.progress_file, "w") { |f| f.puts(@@conf.to_yaml) }
|
92
193
|
end
|
93
194
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
run 'rails new hydra_tutorial_app'
|
99
|
-
run 'cd hydra_tutorial_app'
|
100
|
-
|
195
|
+
# Inform user if the tutorial is finished.
|
196
|
+
if ts.size == 0
|
197
|
+
msg = "All tasks have been completed. Use the --reset option to start over."
|
198
|
+
say(msg, WARNING)
|
101
199
|
end
|
102
200
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
Here's a chance to look around. You can see the structure of a Rails application.
|
107
|
-
./app
|
108
|
-
./config
|
109
|
-
./lib
|
110
|
-
Gemfile
|
111
|
-
}
|
112
|
-
|
113
|
-
ask %Q{
|
114
|
-
|
115
|
-
Hit ENTER when you're ready to continue.
|
116
|
-
}, Thor::Shell::Color::GREEN
|
117
|
-
end
|
201
|
+
# In debug mode, we print the contents of the progress file.
|
202
|
+
run("cat #{@@conf.progress_file}", :verbose => false) if @@conf.debug_steps
|
203
|
+
end
|
118
204
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
205
|
+
# Sets up configuration information in the @@conf variable.
|
206
|
+
def self.initialize_config(opts)
|
207
|
+
@@conf = HTConf.new
|
208
|
+
@@conf.run_all = opts[:run_all]
|
209
|
+
@@conf.quick = opts[:quick]
|
210
|
+
@@conf.reset = opts[:reset]
|
211
|
+
@@conf.gems_from_git = opts[:gems_from_git]
|
212
|
+
@@conf.debug_steps = opts[:debug_steps]
|
213
|
+
@@conf.no_git = opts[:no_git]
|
214
|
+
@@conf.diff = opts[:diff]
|
215
|
+
@@conf.app = (opts[:app] || 'hydra_tutorial_app').strip.parameterize('_')
|
216
|
+
@@conf.progress_file = (opts[:progress_file] || '.hydra-tutorial-progress')
|
217
|
+
@@conf.done = nil
|
218
|
+
@@conf.templates_path = File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
|
128
219
|
end
|
129
220
|
|
130
|
-
|
131
|
-
|
132
|
-
|
221
|
+
# Initializes the YAML progress file that keeps track of which
|
222
|
+
# tutorial tasks have been completed. This needs to occur if
|
223
|
+
# the YAML file does not exist yet or if the user requested a reset.
|
224
|
+
# In the latter case, the program exits immediately.
|
225
|
+
def self.initialize_progress_file
|
226
|
+
return if (File.file?(@@conf.progress_file) and ! @@conf.reset)
|
227
|
+
File.open(@@conf.progress_file, "w") { |f|
|
228
|
+
f.puts("---\n") # Empty YAML file.
|
229
|
+
}
|
230
|
+
exit if @@conf.reset
|
231
|
+
end
|
133
232
|
|
134
|
-
|
135
|
-
|
136
|
-
|
233
|
+
# Loads the progress info from the YAML file, and
|
234
|
+
# sets the corresponding @@conf.done value.
|
235
|
+
def self.load_progress_info
|
236
|
+
h = YAML.load_file(@@conf.progress_file) || {}
|
237
|
+
@@conf.done = (h[:done] || [])
|
238
|
+
end
|
137
239
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
240
|
+
# Takes an array of task names: those requested on the command line
|
241
|
+
# by the user (typically this list is empty).
|
242
|
+
# Returns an arrray of task names: those that the main() taks will invoke.
|
243
|
+
def self.determine_tasks_to_run(requested_tasks)
|
244
|
+
if requested_tasks.size == 0
|
245
|
+
# User did not request any tasks, so we determine which tasks
|
246
|
+
# have not been done yet. We either return all of those tasks
|
247
|
+
# or, more commonly, just the next text.
|
248
|
+
done = Set.new(@@conf.done)
|
249
|
+
ts = tutorial_tasks.reject { |t| done.include?(t) }
|
250
|
+
ts = [ts.first] unless (@@conf.run_all or ts == [])
|
251
|
+
return ts
|
252
|
+
else
|
253
|
+
# User requested particular tasks, so we will simply return
|
254
|
+
# them, provided that they are valid task names.
|
255
|
+
valid = Set.new(tutorial_tasks)
|
256
|
+
requested_tasks.each { |rt|
|
257
|
+
abort "Invalid task name: #{rt}." unless valid.include?(rt)
|
258
|
+
}
|
259
|
+
return requested_tasks
|
142
260
|
end
|
261
|
+
end
|
143
262
|
|
144
|
-
def as_if_this_was_just_a_rails_applications
|
145
|
-
say %Q{
|
146
|
-
If we wanted to build a Rails application to do this, we would add some models and controllers.
|
147
263
|
|
148
|
-
|
149
|
-
|
264
|
+
####
|
265
|
+
# The remaining methods represent the steps in the tutorial.
|
266
|
+
# The tasks should be defined in the order they should run.
|
267
|
+
####
|
150
268
|
|
151
|
-
|
152
|
-
|
269
|
+
desc('welcome: FIX', 'FIX')
|
270
|
+
def welcome
|
271
|
+
say %Q{
|
272
|
+
Welcome to this Hydra tutorial. We're going to step through building a
|
273
|
+
working Hydra application. We'll build the application gradually, starting
|
274
|
+
by building our "business logic", wiring in HTML views, and then
|
275
|
+
connecting it to our Rails application.
|
153
276
|
|
154
|
-
|
155
|
-
|
156
|
-
|
277
|
+
At several points in this tutorial, as we iteratively develop our files,
|
278
|
+
you may be prompted to review conflicts between versions of files. It is
|
279
|
+
safe to blindly accept the changes ('y'), however you may wish to view
|
280
|
+
the diff ('d') to see the things we're change.
|
157
281
|
|
158
|
-
|
159
|
-
Take a look around. Hit ENTER when you're ready to continue.
|
160
|
-
}, Thor::Shell::Color::GREEN
|
161
|
-
end
|
282
|
+
This tutorial, a README file, and our bug tracker are at:
|
162
283
|
|
163
|
-
|
164
|
-
say %Q{
|
165
|
-
But it turns out a relational database is not a great place to store complex metadata objects,
|
166
|
-
with nesting, hierarchy, repetition, etc like we often fine in the digital library world. We'd
|
167
|
-
also like to store and manage our data in an exchangeable form rather than a custom-built database.
|
284
|
+
https://github.com/projecthydra/hydra-tutorial
|
168
285
|
|
169
|
-
|
170
|
-
|
171
|
-
|
286
|
+
We'll generate a stub application in the #{@@conf.app}
|
287
|
+
folder. You can change that using the --app option.\n}, STATEMENT
|
288
|
+
end
|
172
289
|
|
173
|
-
|
174
|
-
|
290
|
+
desc('install_ruby: FIX', 'FIX')
|
291
|
+
def install_ruby
|
292
|
+
return if @@conf.quick
|
293
|
+
say %Q{
|
294
|
+
Obviously, if you can run this tutorial, you have already installed ruby.
|
295
|
+
}, STATEMENT
|
175
296
|
|
176
|
-
|
177
|
-
|
178
|
-
OM Documents on the filesystem (in db/datasets) and then add a simple OM terminology as a drop-in
|
179
|
-
replacement for the ActiveRecord scaffold object.
|
297
|
+
ruby_executable = run 'which ruby', :capture => true, :verbose => false
|
298
|
+
ruby_executable.strip!
|
180
299
|
|
181
|
-
|
300
|
+
say %Q{
|
301
|
+
You are running this using:
|
182
302
|
|
183
|
-
|
184
|
-
copy_file "om_record.rb", "app/models/om_record.rb"
|
303
|
+
#{ruby_executable}}, STATEMENT
|
185
304
|
|
305
|
+
if ruby_executable =~ /rvm/ or ruby_executable =~ /rbenv/ or ruby_executable =~ /home/ or ruby_executable =~ /Users/
|
186
306
|
say %Q{
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
307
|
+
It looks like you're using rvm/rbenv/etc. We'll use
|
308
|
+
this environment to build the application.\n}, STATEMENT
|
309
|
+
else
|
310
|
+
say %Q{
|
311
|
+
We checked, and it looks like you might be using a system-wide ruby.
|
312
|
+
We suggest you use somethng like rvm [1], rbenv [2], etc to manage
|
313
|
+
your ruby projects.
|
191
314
|
|
192
|
-
|
193
|
-
|
315
|
+
You can continue and hope for the best, or go install one of these
|
316
|
+
ruby managers, which may make your life easier.
|
194
317
|
|
195
|
-
|
196
|
-
|
318
|
+
[1] http://rvm.io/
|
319
|
+
[2] https://github.com/sstephenson/rbenv/\n}, WARNING
|
197
320
|
|
321
|
+
continue_prompt
|
198
322
|
end
|
323
|
+
end
|
324
|
+
|
325
|
+
desc('install_bundler_and_rails: FIX', 'FIX')
|
326
|
+
def install_bundler_and_rails
|
327
|
+
say %Q{
|
328
|
+
We're going to install some prerequisite gems in order to create our
|
329
|
+
skeleton Rails application.\n}, STATEMENT
|
330
|
+
run 'gem install bundler rails', :capture => false
|
331
|
+
end
|
199
332
|
|
333
|
+
desc('new_rails_app: FIX', 'FIX')
|
334
|
+
def new_rails_app
|
335
|
+
say %Q{
|
336
|
+
Now we'll create the application.\n}, STATEMENT
|
200
337
|
|
201
|
-
|
338
|
+
if File.exists? @@conf.app
|
202
339
|
say %Q{
|
203
|
-
|
204
|
-
|
340
|
+
#{@@conf.app} already exists. Either remove it or provide
|
341
|
+
a different application name using the --app option.}, WARNING
|
342
|
+
exit
|
343
|
+
end
|
205
344
|
|
206
|
-
|
207
|
-
|
208
|
-
Fedora. We'll have a section on Solr and discovery interfaces later.
|
345
|
+
run "rails new #{@@conf.app}", :capture => false
|
346
|
+
end
|
209
347
|
|
210
|
-
|
211
|
-
|
348
|
+
desc('git_initial_commit: FIX', 'FIX')
|
349
|
+
def git_initial_commit
|
350
|
+
say %Q{
|
351
|
+
We will keep track of our work using Git so that you can see how
|
352
|
+
the files in the project change from one step to the next. To see
|
353
|
+
the difference you can open a terminal in the Rails application
|
354
|
+
directory and run the following Git command.
|
212
355
|
|
213
|
-
|
214
|
-
Fedora runs as a java servlet inside a container like Tomcat or Jetty. Hydra provides a bundled
|
215
|
-
version of Fedora and Solr for testing and development.
|
216
|
-
}, Thor::Shell::Color::YELLOW
|
356
|
+
git diff HEAD^1..HEAD
|
217
357
|
|
218
|
-
|
219
|
-
We'll download a copy now. It may take awhile.
|
220
|
-
}, Thor::Shell::Color::YELLOW
|
221
|
-
unless File.exists? '../jetty'
|
222
|
-
git :clone => 'git://github.com/projecthydra/hydra-jetty.git ../jetty'
|
223
|
-
end
|
224
|
-
run 'cp -R ../jetty jetty'
|
225
|
-
# run 'rake hydra:jetty:config'
|
358
|
+
Or you can simply run the tutorial with the --diff option.
|
226
359
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
360
|
+
Alternatively, you can use a tool like Gitx to see the differences
|
361
|
+
in the code from one step in the tutorial to the next.
|
362
|
+
|
363
|
+
First, we'll initialize our project's Git repository.\n\n}, STATEMENT
|
364
|
+
run_git('', 'init')
|
365
|
+
run_git('Initial commit')
|
366
|
+
end
|
231
367
|
|
232
|
-
|
233
|
-
|
368
|
+
desc('out_of_the_box: FIX', 'FIX')
|
369
|
+
def out_of_the_box
|
370
|
+
say %Q{
|
371
|
+
Here's a chance to look around. You can see the structure of
|
372
|
+
a Rails application. In particular, look at:
|
373
|
+
./app
|
374
|
+
./config
|
375
|
+
./lib
|
376
|
+
Gemfile
|
377
|
+
|
378
|
+
If we launched the Rails application server, we can see the application
|
379
|
+
running in the browser and you can see if everything is working.\n}, STATEMENT
|
380
|
+
rails_server
|
381
|
+
end
|
234
382
|
|
235
|
-
|
236
|
-
|
237
|
-
|
383
|
+
desc('adding_dependencies: FIX', 'FIX')
|
384
|
+
def adding_dependencies
|
385
|
+
gem 'execjs'
|
386
|
+
gem 'therubyracer'
|
387
|
+
run_git('Added gems for Javascript: execjs and therubyracer')
|
388
|
+
end
|
238
389
|
|
239
|
-
|
240
|
-
|
241
|
-
|
390
|
+
desc('add_fedora_and_solr_with_hydrajetty: FIX', 'FIX')
|
391
|
+
def add_fedora_and_solr_with_hydrajetty
|
392
|
+
say %Q{
|
393
|
+
Fedora runs as a Java servlet inside a container like Tomcat or Jetty.
|
394
|
+
Hydra provides a bundled version of Fedora and Solr for
|
395
|
+
testing and development.\n}, STATEMENT
|
396
|
+
|
397
|
+
say %Q{
|
398
|
+
We'll download it now and put a copy into your application's directory.
|
399
|
+
This might take awhile.\n}, STATEMENT
|
400
|
+
unless File.exists? '../jetty'
|
401
|
+
git :clone => '-b 4.x git://github.com/projecthydra/hydra-jetty.git ../jetty'
|
402
|
+
end
|
403
|
+
unless File.exists? 'jetty'
|
404
|
+
run 'cp -R ../jetty jetty'
|
405
|
+
end
|
406
|
+
append_to_file '.gitignore', "\njetty\n"
|
407
|
+
run_git('Added jetty to project and git-ignored it')
|
408
|
+
end
|
242
409
|
|
243
|
-
|
244
|
-
|
410
|
+
desc('jetty_configuration: FIX', 'FIX')
|
411
|
+
def jetty_configuration
|
412
|
+
say %Q{
|
413
|
+
We'll add some configuration yml files with information to connect
|
414
|
+
to Solr and Fedora.\n\n}, STATEMENT
|
245
415
|
|
246
|
-
|
416
|
+
copy_file 'solr.yml', 'config/solr.yml'
|
417
|
+
copy_file 'fedora.yml', 'config/fedora.yml'
|
247
418
|
|
248
|
-
|
419
|
+
say %Q{
|
420
|
+
Add the 'jettywrapper' gem, which adds Rake tasks to start and stop Jetty.\n}, STATEMENT
|
249
421
|
|
250
|
-
|
251
|
-
|
422
|
+
gem 'jettywrapper'
|
423
|
+
run 'bundle install', :capture => false
|
424
|
+
run_git('Solr and Fedora configuration')
|
252
425
|
|
253
|
-
|
254
|
-
|
255
|
-
|
426
|
+
say %Q{
|
427
|
+
Starting Jetty\n}, STATEMENT
|
428
|
+
rake 'jetty:start'
|
256
429
|
|
257
|
-
|
430
|
+
say %Q{
|
431
|
+
Take a look around. Jetty should be running on port 8983. You can see
|
432
|
+
the Fedora server at:
|
258
433
|
|
259
|
-
|
260
|
-
say %Q{
|
261
|
-
We'll update our Dataset object to use ActiveFedora.
|
262
|
-
}, Thor::Shell::Color::YELLOW
|
434
|
+
http://localhost:8983/fedora/
|
263
435
|
|
264
|
-
|
265
|
-
run 'bundle install'
|
266
|
-
copy_file "dataset_af_om.rb", "app/models/dataset.rb"
|
436
|
+
And a Solr index at:
|
267
437
|
|
268
|
-
|
269
|
-
You should be able to create new dataset objects and see them updated in Fedora.
|
270
|
-
}, Thor::Shell::Color::YELLOW
|
438
|
+
http://localhost:8983/solr/development/admin/\n}, STATEMENT
|
271
439
|
|
272
|
-
|
273
|
-
Hit ENTER when you're ready to continue.
|
274
|
-
}, Thor::Shell::Color::GREEN
|
275
|
-
end
|
440
|
+
continue_prompt
|
276
441
|
end
|
277
442
|
|
278
|
-
|
279
|
-
|
280
|
-
|
443
|
+
desc('remove_public_index: FIX', 'FIX')
|
444
|
+
def remove_public_index
|
445
|
+
remove_file 'public/index.html'
|
446
|
+
run_git('Removed the Rails index.html file')
|
447
|
+
end
|
281
448
|
|
282
|
-
|
283
|
-
|
284
|
-
|
449
|
+
desc('add_activefedora: FIX', 'FIX')
|
450
|
+
def add_activefedora
|
451
|
+
say %Q{
|
452
|
+
The active-fedora gem provides a way to model Fedora objects within Ruby.
|
453
|
+
It will help you create Ruby models for creating, updating and reading
|
454
|
+
objects from Fedora using a domain-specific language (DSL) similar
|
455
|
+
to the Rails' ActiveRecord.
|
456
|
+
|
457
|
+
The om gem provides mechanisms for mapping XML documents into Ruby.
|
458
|
+
|
459
|
+
We'll add both of these to the Gemfile.\n\n}, STATEMENT
|
460
|
+
gem 'active-fedora'
|
461
|
+
gem 'om'
|
462
|
+
run 'bundle install', :capture => false
|
463
|
+
run_git('Added gems: active-fedora and om')
|
464
|
+
end
|
285
465
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
466
|
+
desc('add_initial_model: FIX', 'FIX')
|
467
|
+
def add_initial_model
|
468
|
+
say %Q{
|
469
|
+
Now we'll add a basic ActiveFedora stub model for a 'Record'.\n\n}, STATEMENT
|
470
|
+
copy_file "basic_af_model.rb", "app/models/record.rb"
|
471
|
+
run_git('Created a minimal Record model')
|
472
|
+
end
|
291
473
|
|
292
|
-
|
293
|
-
|
294
|
-
|
474
|
+
desc('rails_console_tour: FIX', 'FIX')
|
475
|
+
def rails_console_tour
|
476
|
+
say %Q{
|
477
|
+
Now we'll give you a chance to look at the Record model. If you
|
478
|
+
launch the Rails interactive console (`rails c`), we can create
|
479
|
+
and manipulate our object:
|
480
|
+
|
481
|
+
## CREATE
|
482
|
+
> obj = Record.new
|
483
|
+
# => #<Record:1571331701243443635 @pid="__DO_NOT_USE__" >
|
484
|
+
> obj.descMetadata.content = e.g. '<my_xml_content />'
|
485
|
+
> obj.save
|
486
|
+
|
487
|
+
> obj.pid
|
488
|
+
# => e.g. 'changeme:1'
|
489
|
+
|
490
|
+
## RETRIEVE
|
491
|
+
> obj = Record.find('changeme:1')
|
492
|
+
> ds = obj.descMetadata
|
493
|
+
# => #<ActiveFedora::NokogiriDatastream:3283711306477137919 ...>
|
494
|
+
> ds.content
|
495
|
+
# => (should be the XML document you added before)
|
496
|
+
|
497
|
+
## UPDATE
|
498
|
+
# manipulating XML:
|
499
|
+
> ds.ng_xml.xpath('//my_xml_content')
|
500
|
+
|
501
|
+
## DELETE
|
502
|
+
> obj.delete\n}, STATEMENT
|
503
|
+
rails_console
|
504
|
+
end
|
295
505
|
|
296
|
-
|
297
|
-
|
298
|
-
|
506
|
+
desc('enhance_model_with_om_descmd: FIX', 'FIX')
|
507
|
+
def enhance_model_with_om_descmd
|
508
|
+
say %Q{
|
509
|
+
Instead of working with the Nokogiri XML document directly, we
|
510
|
+
can use OM to make querying an XML document easier. We'll replace the
|
511
|
+
previous Record with a OM-enabled document.\n\n}, STATEMENT
|
512
|
+
f = "app/models/record.rb"
|
513
|
+
remove_file f
|
514
|
+
copy_file "basic_om_model.rb", f
|
515
|
+
run_git('Set up basic OM descMetadata for Record model')
|
516
|
+
end
|
299
517
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
518
|
+
desc('experiment_with_om_descmd: FIX', 'FIX')
|
519
|
+
def experiment_with_om_descmd
|
520
|
+
say %Q{
|
521
|
+
If you launch the Rails interactive console, we can now create and
|
522
|
+
manipulate our object using methods provided by OM.
|
523
|
+
|
524
|
+
> obj = Record.new
|
525
|
+
> obj.descMetadata.title = "My object title"
|
526
|
+
> obj.save
|
527
|
+
> obj.descMetadata.content
|
528
|
+
# => An XML document with the title "My object title"\n}, STATEMENT
|
529
|
+
rails_console
|
530
|
+
end
|
304
531
|
|
305
|
-
|
306
|
-
|
307
|
-
|
532
|
+
desc('use_the_delegate_method: FIX', 'FIX')
|
533
|
+
def use_the_delegate_method
|
534
|
+
say %Q{
|
535
|
+
We can use the #delegate method to tell the model-object how
|
536
|
+
to access these attributes.
|
537
|
+
|
538
|
+
> obj = Record.new
|
539
|
+
> obj.title = "My object title"
|
540
|
+
> obj.save
|
541
|
+
> obj.descMetadata.content
|
542
|
+
# => An XML document with the title "My object title"\n\n}, STATEMENT
|
543
|
+
|
544
|
+
loc = 'has_metadata :name => "descMetadata", :type => DatastreamMetadata\n'
|
545
|
+
insert_into_file "app/models/record.rb", :after => loc do
|
546
|
+
"delegate :title, :to => 'descMetadata'\n"
|
308
547
|
end
|
548
|
+
run_git('Modify Record model to delegate title to descMetadata')
|
549
|
+
end
|
309
550
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
551
|
+
desc('add_mods_model_with_mods_descmd: FIX', 'FIX')
|
552
|
+
def add_mods_model_with_mods_descmd
|
553
|
+
say %Q{
|
554
|
+
We'll now replace the minimal XML metadata schema with a simple
|
555
|
+
MODS-based example, using an OM terminology we prepared earlier.
|
314
556
|
|
315
|
-
|
316
|
-
|
317
|
-
say %Q{
|
318
|
-
Fedora runs as a java servlet inside a container like Tomcat or Jetty. Hydra provides a bundled
|
319
|
-
version of Fedora and Solr for testing and development.
|
320
|
-
}, Thor::Shell::Color::YELLOW
|
557
|
+
We'll put the MODS datastream in a separate module and file, so that
|
558
|
+
it can be easily reused in other ActiveFedora-based objects.\n}, STATEMENT
|
321
559
|
|
322
|
-
|
323
|
-
|
324
|
-
|
560
|
+
f = "app/models/record.rb"
|
561
|
+
remove_file f
|
562
|
+
copy_file "basic_mods_model.rb", f
|
563
|
+
copy_file "mods_desc_metadata.rb", "app/models/mods_desc_metadata.rb"
|
564
|
+
run_git('Set up MODS descMetadata')
|
565
|
+
end
|
325
566
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
567
|
+
desc('experiment_with_mods_descmd: FIX', 'FIX')
|
568
|
+
def experiment_with_mods_descmd
|
569
|
+
say %Q{
|
570
|
+
If you launch the Rails interactive console, we can now create
|
571
|
+
and manipulate our object using methods provided by OM.
|
572
|
+
|
573
|
+
> obj = Record.new
|
574
|
+
> obj.title = "My object title"
|
575
|
+
> obj.save
|
576
|
+
> obj.descMetadata.content
|
577
|
+
# => A MODS XML document\n}, STATEMENT
|
578
|
+
rails_console
|
579
|
+
end
|
330
580
|
|
331
|
-
|
581
|
+
desc('record_generator: FIX', 'FIX')
|
582
|
+
def record_generator
|
583
|
+
say %Q{
|
584
|
+
Now that we've set up our model and successfully added content
|
585
|
+
into Fedora, now we want to connect the model to a Rails web application.
|
332
586
|
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
else
|
587
|
+
We'll start by using the standard Rails generators to create
|
588
|
+
a scaffold controller and views, which will give us a
|
589
|
+
place to start working.\n\n}, STATEMENT
|
337
590
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
end
|
591
|
+
generate "scaffold_controller Record --no-helper --skip-test-framework"
|
592
|
+
route "resources :records"
|
593
|
+
run_git('Used Rails generator to create controller and views for the Record model')
|
342
594
|
|
343
|
-
|
595
|
+
say %Q{
|
596
|
+
If you look in ./app/views/records, you can see a set of
|
597
|
+
Rails ERB templates.
|
344
598
|
|
345
|
-
|
346
|
-
|
347
|
-
|
599
|
+
./app/controlers/records_controller.rb contains the controller
|
600
|
+
that ties the model to the views.\n}, STATEMENT
|
601
|
+
|
602
|
+
continue_prompt
|
603
|
+
end
|
604
|
+
|
605
|
+
desc('add_new_form: FIX', 'FIX')
|
606
|
+
def add_new_form
|
607
|
+
say %Q{
|
608
|
+
The scaffold just provided the basic outline for an application, so
|
609
|
+
we need to provide the guts for the web form. Here's a simple one:\n\n}, STATEMENT
|
610
|
+
files = [
|
611
|
+
["_form.wiring_it_into_rails.html.erb", "app/views/records/_form.html.erb"],
|
612
|
+
["show.html.erb", "app/views/records/show.html.erb"],
|
613
|
+
]
|
614
|
+
files.each do |src, dst|
|
615
|
+
remove_file dst
|
616
|
+
copy_file src, dst
|
348
617
|
end
|
618
|
+
run_git('Fleshed out the edit form and show page')
|
619
|
+
end
|
349
620
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
621
|
+
desc('check_the_new_form: FIX', 'FIX')
|
622
|
+
def check_the_new_form
|
623
|
+
say %Q{
|
624
|
+
If we start the Rails server, we should now be able to visit the records
|
625
|
+
in the browser, create new records, and edit existing records.
|
355
626
|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
}, Thor::Shell::Color::YELLOW
|
627
|
+
Start by creating a new record:\n}, STATEMENT
|
628
|
+
rails_server '/records/new'
|
629
|
+
end
|
360
630
|
|
361
|
-
|
631
|
+
desc('add_hydra_gems: FIX', 'FIX')
|
632
|
+
def add_hydra_gems
|
633
|
+
say %Q{
|
634
|
+
Thus far, we've been using component parts of the Hydra framework, but
|
635
|
+
now we'll add in the whole framework so we can take advantage of common
|
636
|
+
patterns that have emerged in the Hydra community, including search,
|
637
|
+
gated discovery, etc.
|
362
638
|
|
363
|
-
|
364
|
-
" include Hydra::AssetsControllerHelper\n"
|
365
|
-
end
|
639
|
+
We'll add a few new gems:
|
366
640
|
|
367
|
-
|
368
|
-
" apply_depositor_metadata(@dataset)\n"
|
369
|
-
end
|
370
|
-
end
|
641
|
+
- blacklight provides a discovery interface on top of the Solr index
|
371
642
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
643
|
+
- hydra-head provides a number of common Hydra patterns
|
644
|
+
|
645
|
+
- devise is a standard Ruby gem for providing user-related
|
646
|
+
functions, like registration, sign-in, etc.\n\n}, STATEMENT
|
376
647
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
648
|
+
if @@conf.gems_from_git
|
649
|
+
gem 'blacklight', :git => "git://github.com/projectblacklight/blacklight.git"
|
650
|
+
gem 'hydra-head', :git => "git://github.com/projecthydra/hydra-head.git"
|
651
|
+
else
|
652
|
+
gem 'blacklight'
|
653
|
+
gem 'hydra-head', ">= 4.1.1"
|
381
654
|
end
|
655
|
+
gem 'devise'
|
656
|
+
run 'bundle install', :capture => false
|
657
|
+
run_git('Added gems: blacklight, hydra-head, devise')
|
658
|
+
end
|
382
659
|
|
660
|
+
desc('run_hydra_generators: FIX', 'FIX')
|
661
|
+
def run_hydra_generators
|
662
|
+
say %Q{
|
663
|
+
These gems provide generators for adding basic views, styles, and override
|
664
|
+
points into your application. We'll run these generators now.\n}, STATEMENT
|
665
|
+
f = 'config/solr.yml'
|
666
|
+
remove_file f
|
667
|
+
generate 'blacklight', '--devise'
|
668
|
+
remove_file f
|
669
|
+
remove_file 'app/controllers/catalog_controller.rb'
|
670
|
+
generate 'hydra:head', 'User'
|
671
|
+
run_git('Ran blacklight and hydra-head generators')
|
383
672
|
end
|
384
673
|
|
385
|
-
|
386
|
-
|
387
|
-
|
674
|
+
desc('db_migrate: FIX', 'FIX')
|
675
|
+
def db_migrate
|
676
|
+
say %Q{
|
677
|
+
Blacklight uses a SQL database for keeping track of user bookmarks,
|
678
|
+
searches, etc. We'll run the migrations next:\n\n}, STATEMENT
|
679
|
+
rake 'db:migrate'
|
680
|
+
rake 'db:test:prepare'
|
681
|
+
run_git('Ran db:migrate, which created db/schema.rb')
|
682
|
+
end
|
388
683
|
|
389
|
-
|
390
|
-
|
391
|
-
|
684
|
+
desc('hydra_jetty_config: FIX', 'FIX')
|
685
|
+
def hydra_jetty_config
|
686
|
+
say %Q{
|
687
|
+
Hydra provides some configuration for Solr and Fedora. Use them.\n}, STATEMENT
|
688
|
+
rake 'jetty:stop'
|
689
|
+
rake 'hydra:jetty:config'
|
690
|
+
rake 'jetty:start'
|
691
|
+
end
|
392
692
|
|
393
|
-
|
693
|
+
desc('add_access_rights: FIX', 'FIX')
|
694
|
+
def add_access_rights
|
695
|
+
say %Q{
|
696
|
+
We need to make a couple changes to our controller and model to make
|
697
|
+
them fully-compliant objects by teaching them about access rights.
|
394
698
|
|
395
|
-
|
699
|
+
We'll also update our controller to provide access controls on records.\n\n}, STATEMENT
|
396
700
|
|
701
|
+
inject_into_class "app/controllers/records_controller.rb", 'RecordsController' do
|
702
|
+
" include Hydra::AssetsControllerHelper\n"
|
397
703
|
end
|
398
704
|
|
399
|
-
|
705
|
+
insert_into_file "app/controllers/records_controller.rb", :after => "@record = Record.new(params[:record])\n" do
|
706
|
+
" apply_depositor_metadata(@record)\n"
|
707
|
+
end
|
400
708
|
|
709
|
+
inject_into_class "app/models/record.rb", "Record" do
|
710
|
+
"
|
711
|
+
include Hydra::ModelMixins::CommonMetadata
|
712
|
+
include Hydra::ModelMethods
|
713
|
+
"
|
401
714
|
end
|
402
715
|
|
716
|
+
insert_into_file "app/models/solr_document.rb", :after => "include Blacklight::Solr::Document\n" do
|
717
|
+
"
|
718
|
+
include Hydra::Solr::Document
|
719
|
+
"
|
720
|
+
end
|
403
721
|
|
404
|
-
|
722
|
+
insert_into_file "app/assets/javascripts/application.js", :after => "//= require_tree .\n" do
|
723
|
+
"Blacklight.do_search_context_behavior = function() { }\n"
|
724
|
+
end
|
405
725
|
|
726
|
+
inject_into_class "app/controllers/records_controller.rb", 'RecordsController' do
|
727
|
+
" include Hydra::AccessControlsEnforcement\n" +
|
728
|
+
" before_filter :enforce_access_controls\n"
|
406
729
|
end
|
407
730
|
|
731
|
+
run_git('Modify controller and model to include access rights')
|
408
732
|
end
|
409
733
|
|
410
|
-
|
411
|
-
|
412
|
-
|
734
|
+
desc('check_catalog: FIX', 'FIX')
|
735
|
+
def check_catalog
|
736
|
+
say %Q{
|
737
|
+
Blacklight and Hydra-Head have added some new functionality to the
|
738
|
+
application. We can now look at a search interface (provided
|
739
|
+
by Blacklight) and use gated discovery over our repository. By default,
|
740
|
+
objects are only visible to their creator.
|
413
741
|
|
414
|
-
|
742
|
+
Create some new objects, and then check out the search catalog at:
|
415
743
|
|
416
|
-
|
744
|
+
http://localhost:3000/catalog\n}, STATEMENT
|
417
745
|
|
418
|
-
|
419
|
-
|
420
|
-
|
746
|
+
# TODO: remove this monkey-patch fixing a bug in hydra-head.
|
747
|
+
f = `bundle show hydra-head`
|
748
|
+
f = "#{f.strip}/app/views/_user_util_links.html.erb"
|
749
|
+
gsub_file f, /.+folder_index_path.+/, ''
|
421
750
|
|
422
|
-
|
423
|
-
|
751
|
+
rails_server('/records/new')
|
752
|
+
end
|
424
753
|
|
754
|
+
desc('install_rspec: FIX', 'FIX')
|
755
|
+
def install_rspec
|
756
|
+
say %Q{
|
757
|
+
One of the great things about the Rails framework is the strong
|
758
|
+
testing ethic. We'll use rspec to write a couple tests for
|
759
|
+
this application.\n\n}, STATEMENT
|
760
|
+
gem_group :development, :test do
|
761
|
+
gem 'rspec'
|
762
|
+
gem 'rspec-rails'
|
425
763
|
end
|
764
|
+
run 'bundle install', :capture => false
|
765
|
+
generate 'rspec:install'
|
766
|
+
run_git('Added rspec to project')
|
767
|
+
end
|
426
768
|
|
427
|
-
|
428
|
-
|
769
|
+
# TODO: write the test.
|
770
|
+
desc('write_model_test: FIX', 'FIX')
|
771
|
+
def write_model_test
|
772
|
+
# copy_file 'record_test.rb', 'spec/models/record_test.rb'
|
773
|
+
# run_git('Added a model test')
|
774
|
+
run 'rspec'
|
775
|
+
end
|
429
776
|
|
430
|
-
|
777
|
+
# TODO: this test should do something.
|
778
|
+
desc('write_controller_test: FIX', 'FIX')
|
779
|
+
def write_controller_test
|
780
|
+
say %Q{
|
781
|
+
Here's a quick example of a test.\n\n}
|
782
|
+
copy_file 'records_controller_spec.rb', 'spec/controllers/records_controller_spec.rb'
|
783
|
+
run_git('Added a controller test')
|
784
|
+
run 'rspec'
|
431
785
|
end
|
432
786
|
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
def stop_jetty
|
441
|
-
rake 'jetty:stop'
|
787
|
+
desc('install_capybara: FIX', 'FIX')
|
788
|
+
def install_capybara
|
789
|
+
say %Q{
|
790
|
+
We also want to write integration tests to test the end-result that
|
791
|
+
a user may see. We'll add the capybara gem to do that.\n\n}, STATEMENT
|
792
|
+
gem_group :development, :test do
|
793
|
+
gem 'capybara'
|
442
794
|
end
|
795
|
+
run 'bundle install', :cature => true
|
796
|
+
run_git('Added capybara gem')
|
797
|
+
end
|
798
|
+
|
799
|
+
desc('write_integration_test: FIX', 'FIX')
|
800
|
+
def write_integration_test
|
801
|
+
say %Q{
|
802
|
+
Here's a quick integration test that proves deposit works.\n}, STATEMENT
|
803
|
+
copy_file 'integration_spec.rb', 'spec/integration/integration_spec.rb'
|
804
|
+
run_git('Added an integration test')
|
805
|
+
end
|
443
806
|
|
807
|
+
desc('run_integration_test_fail: FIX', 'FIX')
|
808
|
+
def run_integration_test_fail
|
809
|
+
say %Q{
|
810
|
+
Now that the integration spec is in place, when we try to run rspec,
|
811
|
+
we'll get a test failure because it can't connect to Fedora.\n}, STATEMENT
|
812
|
+
run 'rspec'
|
444
813
|
end
|
445
814
|
|
446
|
-
|
447
|
-
|
815
|
+
desc('add_jettywrapper_ci_task: FIX', 'FIX')
|
816
|
+
def add_jettywrapper_ci_task
|
817
|
+
say %Q{
|
818
|
+
Instead, we need to add a new Rake task that knows how to wrap the
|
819
|
+
test suite -- start jetty before running the tests and stop jetty
|
820
|
+
at the end. We can use a feature provided by jettywrapper to do this.\n\n}, STATEMENT
|
821
|
+
copy_file 'ci.rake', 'lib/tasks/ci.rake'
|
822
|
+
run_git('Added ci task')
|
823
|
+
rake 'jetty:stop'
|
824
|
+
rake 'ci'
|
825
|
+
rake 'jetty:start'
|
448
826
|
end
|
449
827
|
|
450
|
-
|
451
|
-
|
828
|
+
desc('add_coverage_stats: FIX', 'FIX')
|
829
|
+
def add_coverage_stats
|
830
|
+
say %Q{
|
831
|
+
Now that we have tests, we also want to have some coverage statistics.\n}, STATEMENT
|
452
832
|
|
453
|
-
|
454
|
-
|
833
|
+
gem_group :development, :test do
|
834
|
+
gem 'simplecov'
|
455
835
|
end
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
836
|
+
run 'bundle install', :capture => false
|
837
|
+
|
838
|
+
f = 'lib/tasks/ci.rake'
|
839
|
+
remove_file f
|
840
|
+
copy_file 'ci_with_coverage.rake', f
|
841
|
+
|
842
|
+
insert_into_file "spec/spec_helper.rb", :after => "ENV[\"RAILS_ENV\"] ||= 'test'\n"do
|
843
|
+
%Q{
|
844
|
+
if ENV['COVERAGE'] == "true"
|
845
|
+
require 'simplecov'
|
846
|
+
SimpleCov.start do
|
847
|
+
add_filter "config/"
|
848
|
+
add_filter "spec/"
|
849
|
+
end
|
850
|
+
end
|
851
|
+
}
|
461
852
|
end
|
462
|
-
end
|
463
853
|
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
854
|
+
append_to_file '.gitignore', "\ncoverage\n"
|
855
|
+
run_git('Added simplecov')
|
856
|
+
|
857
|
+
rake 'jetty:stop'
|
858
|
+
rake 'ci'
|
859
|
+
rake 'jetty:start'
|
860
|
+
|
861
|
+
say %Q{
|
862
|
+
Go take a look at the coverage report, open the file coverage/index.html
|
863
|
+
in your browser.\n}, STATEMENT
|
864
|
+
continue_prompt
|
469
865
|
end
|
470
866
|
|
471
|
-
|
472
|
-
|
473
|
-
|
867
|
+
desc('add_file_uploads: FIX', 'FIX')
|
868
|
+
def add_file_uploads
|
869
|
+
say %Q{
|
870
|
+
Now that we have a basic Hydra application working with metadata-only, we
|
871
|
+
want to enhance that with the ability to upload files. Let's add a new
|
872
|
+
datastream to our model.\n\n}, STATEMENT
|
873
|
+
inject_into_class 'app/models/record.rb', 'Record' do
|
874
|
+
"has_file_datastream :name => 'content', :type => ActiveFedora::Datastream\n"
|
474
875
|
end
|
876
|
+
run_git('Add file uploads to model')
|
475
877
|
end
|
476
878
|
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
879
|
+
# TODO: combine with previous task.
|
880
|
+
desc('add_file_upload_controller: FIX', 'FIX')
|
881
|
+
def add_file_upload_controller
|
882
|
+
say %Q{
|
883
|
+
And educate our controller for managing file objects.\n\n}, STATEMENT
|
884
|
+
inject_into_class "app/controllers/records_controller.rb", "RecordsController" do
|
885
|
+
" include Hydra::Controller::UploadBehavior\n"
|
481
886
|
end
|
887
|
+
insert_into_file "app/controllers/records_controller.rb", :after => "apply_depositor_metadata(@record)\n" do
|
888
|
+
" @record.label = params[:record][:title] # this is a bad hack to work around an AF bug\n" +
|
889
|
+
" add_posted_blob_to_asset(@record, params[:filedata]) if params.has_key?(:filedata)\n"
|
890
|
+
end
|
891
|
+
run_git('Add file uploads to controller')
|
482
892
|
end
|
483
893
|
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
894
|
+
# TODO: combine with previous task.
|
895
|
+
desc('add_file_upload_ui: FIX', 'FIX')
|
896
|
+
def add_file_upload_ui
|
897
|
+
say %Q{
|
898
|
+
And add a file upload field on the form.\n}, STATEMENT
|
899
|
+
f = "app/views/records/_form.html.erb"
|
900
|
+
remove_file f
|
901
|
+
copy_file "_form.add_file_upload.html.erb", f
|
902
|
+
run_git('Add file uploads to UI')
|
903
|
+
end
|
904
|
+
|
905
|
+
desc('fix_add_assets_links: FIX', 'FIX')
|
906
|
+
def fix_add_assets_links
|
907
|
+
say %Q{
|
908
|
+
We'll add a little styling to the Hydra app and add a link to add a new
|
909
|
+
Record in the header of the layout.\n\n}, STATEMENT
|
910
|
+
copy_file "_add_assets_links.html.erb", "app/views/_add_assets_links.html.erb"
|
911
|
+
run_git('Add asset links')
|
912
|
+
end
|
913
|
+
|
914
|
+
# # TODO
|
915
|
+
# desc('add_collection_model: FIX', 'FIX')
|
916
|
+
# def add_collection_model
|
917
|
+
# end
|
918
|
+
|
919
|
+
# # TODO
|
920
|
+
# desc('add_collection_controller: FIX', 'FIX')
|
921
|
+
# def add_collection_controller
|
922
|
+
# end
|
923
|
+
|
924
|
+
# # TODO
|
925
|
+
# desc('add_collection_reference_to_record: FIX', 'FIX')
|
926
|
+
# def add_collection_reference_to_record
|
927
|
+
# end
|
928
|
+
|
929
|
+
# # TODO
|
930
|
+
# desc('add_datastream_and_terminology: FIX', 'FIX')
|
931
|
+
# def add_datastream_and_terminology
|
932
|
+
# end
|
933
|
+
|
934
|
+
desc('start_everything: FIX', 'FIX')
|
935
|
+
def start_everything
|
936
|
+
say %Q{
|
937
|
+
Before the tutorial ends, we'll give you a final chance to look
|
938
|
+
at the web application.\n\n}, STATEMENT
|
939
|
+
rake 'jetty:stop'
|
940
|
+
rake 'jetty:start'
|
941
|
+
rails_server
|
942
|
+
end
|
943
|
+
|
944
|
+
desc('stop_jetty: FIX', 'FIX')
|
945
|
+
def stop_jetty
|
946
|
+
say %Q{
|
947
|
+
This is the end of the tutorial. We'll shut down the jetty server.\n}, STATEMENT
|
948
|
+
rake 'jetty:stop'
|
489
949
|
end
|
490
950
|
|
491
951
|
end
|
492
952
|
|
493
|
-
|
953
|
+
|
954
|
+
####
|
955
|
+
#
|
956
|
+
####
|
957
|
+
|
958
|
+
HydraTutorial.start
|