ebook_generator 0.0.5 → 1.0.2
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.
- checksums.yaml +4 -4
- data/{LICENSE.txt → MIT-LICENSE} +1 -3
- data/README.md +10 -17
- data/Rakefile +17 -1
- data/lib/ebook_generator.rb +75 -72
- data/lib/ebook_generator/version.rb +1 -1
- data/lib/generators/ebook_generator/ebook_generator_generator.rb +16 -0
- data/lib/generators/ebook_generator/templates/create_ebooks.rb +18 -0
- data/lib/generators/ebook_generator/templates/create_sections.rb +13 -0
- data/lib/generators/ebook_generator/templates/ebook.rb +8 -0
- data/lib/generators/ebook_generator/templates/section.rb +6 -0
- data/lib/tasks/ebook_generator_tasks.rake +4 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/ebook.rb +4 -0
- data/spec/dummy/app/models/section.rb +7 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +34 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +82 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/assets.rb +8 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20140416030807_ebooks.rb +17 -0
- data/spec/dummy/db/migrate/20140416032844_sections.rb +12 -0
- data/spec/dummy/db/migrate/20140416033000_add_index_to_sections_ebook_id_position.rb +6 -0
- data/spec/dummy/db/migrate/20140416033315_add_column_slug_to_ebooks.rb +6 -0
- data/spec/dummy/db/schema.rb +44 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +549 -0
- data/spec/dummy/log/test.log +4812 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/tmp/Qui-voluptates-consequuntur-aliquam-iste-numquam..epub +0 -0
- data/spec/dummy/tmp/Ratione-soluta-magni-consectetur-delectus-sequi-necessitatibus..epub +0 -0
- data/spec/ebook_generator_spec.rb +56 -0
- data/spec/factories/factories.rb +35 -0
- data/spec/helpers/unzip.rb +13 -0
- data/spec/models/ebook_spec.rb +5 -0
- data/spec/models/section_spec.rb +5 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/factory_girl.rb +3 -0
- metadata +176 -43
- data/.gitignore +0 -22
- data/Changelog.md +0 -23
- data/Gemfile +0 -3
- data/ebook_generator.gemspec +0 -28
- data/lib/ebook_generator/initializer.rb +0 -5
- data/lib/ebook_generator/migration.rb +0 -30
- data/lib/generators/ebook_generator_generator.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48d8c90867c3202845223f9a32ddfa97355c91c2
|
4
|
+
data.tar.gz: 6bc9b510a69a4408fd05edcb4222a9e4e0b0cd0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f5ce5e4a77897bd07833cb2f3a3267cd69a7e51810153e81f4ee04011a620b4e1d85957c6cb3d427ed1e22353526df6adc8dd6d63550985ed8c5260f809d0ee
|
7
|
+
data.tar.gz: b3b7e0fb42a30ca9346fae2b4725c90e34281a5114195c0f9fa846db273349ce945b45d545238bbdff0b2e7c7becb0041de28e8d45a48a06d4e120524bb3df8c
|
data/{LICENSE.txt → MIT-LICENSE}
RENAMED
data/README.md
CHANGED
@@ -5,10 +5,9 @@ Rails gem to generate eBooks using the Markdown syntax to format content for sec
|
|
5
5
|
An example of this gem being used can be found at: [ebook-generator.affinity-tech.com](http://ebook-generator.affinity-tech.com)
|
6
6
|
|
7
7
|
Requires:
|
8
|
-
-
|
8
|
+
- Rails 4
|
9
9
|
- Rubyzip (to generate the .epub)
|
10
10
|
- Redcarpet (to render Markdown into HTML)
|
11
|
-
- Friendly_id (for nice slugs and for naming of generated ebook file)
|
12
11
|
|
13
12
|
## Installation
|
14
13
|
|
@@ -32,35 +31,29 @@ Generate the tables needed to process the ebooks:
|
|
32
31
|
Migrate the database:
|
33
32
|
`rake db:migrate`
|
34
33
|
|
35
|
-
Pass the
|
36
|
-
`EbookGenerator.generate_ebook(
|
34
|
+
Pass the ebook object you want to generate:
|
35
|
+
`EbookGenerator.generate_ebook(ebook_object)`
|
37
36
|
|
38
37
|
This will then generate an ePub based on the values in the db and output to the /tmp folder.
|
39
38
|
|
40
|
-
|
39
|
+
For a Kindle mobi file then pass in `true` as the second argument:
|
40
|
+
`EbookGenerator.generate_ebook(ebook_object, true)`
|
41
41
|
|
42
|
-
|
43
|
-
- Kindle support
|
44
|
-
- Tests
|
42
|
+
## Feature roadmap
|
45
43
|
|
46
|
-
###
|
44
|
+
### 1.1.0
|
47
45
|
- Style editing
|
48
46
|
|
49
|
-
###
|
47
|
+
### 1.2.0
|
50
48
|
- PDF out
|
51
49
|
|
52
|
-
###
|
50
|
+
### 1.3.0
|
53
51
|
- HTML out
|
54
52
|
- Image support for the front cover
|
55
53
|
|
56
|
-
###
|
54
|
+
### 1.4.0
|
57
55
|
- HTML to eBook conversion
|
58
56
|
|
59
|
-
### 0.6.0
|
60
|
-
- User membership to manage books
|
61
|
-
|
62
|
-
Publishing support?
|
63
|
-
|
64
57
|
## Contributing
|
65
58
|
|
66
59
|
1. Fork it ( https://github.com/[my-github-username]/ebook_generator/fork )
|
data/Rakefile
CHANGED
@@ -1,2 +1,18 @@
|
|
1
|
-
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
|
8
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
9
|
+
|
2
10
|
Bundler::GemHelper.install_tasks
|
11
|
+
|
12
|
+
require 'rspec/core'
|
13
|
+
require 'rspec/core/rake_task'
|
14
|
+
|
15
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
16
|
+
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
17
|
+
|
18
|
+
task :default => :spec
|
data/lib/ebook_generator.rb
CHANGED
@@ -1,14 +1,57 @@
|
|
1
1
|
require "ebook_generator/version"
|
2
2
|
require "ebook_generator/zip_file_processor"
|
3
3
|
require "builder"
|
4
|
+
require "redcarpet"
|
4
5
|
|
5
6
|
module EbookGenerator
|
6
7
|
|
7
|
-
def self.included(model_class)
|
8
|
-
|
8
|
+
# def self.included(model_class)
|
9
|
+
# model_class.extend self
|
10
|
+
# end
|
11
|
+
|
12
|
+
def self.generate_ebook(ebook_object, generate_kindle_file = false)
|
13
|
+
# Set the root path of the ebook
|
14
|
+
path = Rails.root.to_s + "/tmp/#{ebook_object.id}"
|
15
|
+
|
16
|
+
# Make all required dirs
|
17
|
+
dirs = [path, path + "/META-INF", path + "/OEBPS", path + "/OEBPS/Text", path + "/OEBPS/Styles"]
|
18
|
+
make_dirs(dirs)
|
19
|
+
|
20
|
+
# Create container.xml
|
21
|
+
generate_container(path + "/META-INF")
|
22
|
+
|
23
|
+
# Create mimetype
|
24
|
+
generate_mimetype(path + "/mimetype")
|
25
|
+
|
26
|
+
# Move default stylesheet into styles folder
|
27
|
+
copy_style(path + "/OEBPS/Styles")
|
28
|
+
|
29
|
+
# loop through each section loading the reference header and saving as it's own section
|
30
|
+
generate_sections(path + "/OEBPS/Text", ebook_object)
|
31
|
+
|
32
|
+
# generate toc based on the number of sections generated
|
33
|
+
generate_content_opf(path + "/OEBPS", ebook_object)
|
34
|
+
generate_toc_ncx(path + "/OEBPS", ebook_object)
|
35
|
+
|
36
|
+
# change permissions for files that need to be executable
|
37
|
+
files = [path + "/OEBPS/toc.ncx", path + "/OEBPS/content.opf", path + "/mimetype"]
|
38
|
+
change_perms(files)
|
39
|
+
|
40
|
+
# zip all files
|
41
|
+
zipfile_name = Rails.root.to_s + "/tmp/" + ebook_object.slug + ".epub"
|
42
|
+
zf = ZipFileProcessor.new(path, zipfile_name)
|
43
|
+
zf.write
|
44
|
+
|
45
|
+
# Clean up the tmp dir
|
46
|
+
remove_tmp_dir(path + "/")
|
47
|
+
|
48
|
+
# return the file path
|
49
|
+
zipfile_name = generate_mobi(zipfile_name, ebook_object.slug) if generate_kindle_file
|
50
|
+
zipfile_name
|
9
51
|
end
|
10
52
|
|
11
|
-
|
53
|
+
private
|
54
|
+
|
12
55
|
def self.make_dirs(paths)
|
13
56
|
paths.each do |path|
|
14
57
|
Dir.mkdir(path, 0777) unless File.exists?(path)
|
@@ -16,7 +59,6 @@ module EbookGenerator
|
|
16
59
|
end
|
17
60
|
|
18
61
|
def self.generate_container(path)
|
19
|
-
|
20
62
|
file = File.new(path + "/container.xml", "wb")
|
21
63
|
xm = Builder::XmlMarkup.new(:target => file, :indent => 2)
|
22
64
|
xm.instruct!
|
@@ -27,15 +69,12 @@ module EbookGenerator
|
|
27
69
|
}
|
28
70
|
|
29
71
|
file.close
|
30
|
-
|
31
72
|
end
|
32
73
|
|
33
74
|
def self.generate_mimetype(path)
|
34
|
-
|
35
75
|
File.open(path, "w+") do |f|
|
36
76
|
f.write("application/epub+zip")
|
37
77
|
end
|
38
|
-
|
39
78
|
end
|
40
79
|
|
41
80
|
def self.copy_style(path)
|
@@ -43,10 +82,13 @@ module EbookGenerator
|
|
43
82
|
#FileUtils.cp Rails.root.to_s + "/app/ebook/style.css", path
|
44
83
|
end
|
45
84
|
|
46
|
-
def self.
|
85
|
+
def self.convert_to_html(content)
|
47
86
|
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, autolink: true, tables: true)
|
87
|
+
markdown.render(content)
|
88
|
+
end
|
48
89
|
|
49
|
-
|
90
|
+
def self.generate_sections(path, ebook_object)
|
91
|
+
ebook_object.sections.each do |section|
|
50
92
|
file = File.new(path + "/Section#{section.position}.html", "wb")
|
51
93
|
|
52
94
|
xm = Builder::XmlMarkup.new(:target => file, :indent => 2)
|
@@ -54,45 +96,45 @@ module EbookGenerator
|
|
54
96
|
xm.declare! :DOCTYPE, :html, :PUBLIC, "-//W3C//DTD XHTML 1.1//EN", "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
|
55
97
|
xm.html("xmlns" => "http://www.w3.org/1999/xhtml"){
|
56
98
|
xm.head {
|
57
|
-
xm.title {
|
58
|
-
xm.meta("content" =>
|
59
|
-
xm.meta("content" =>
|
99
|
+
xm.title { ebook_object.title }
|
100
|
+
xm.meta("content" => ebook_object.title, "name" => "Title")
|
101
|
+
xm.meta("content" => ebook_object.creator, "name" => "Author")
|
60
102
|
xm.link("href" => "../Styles/style.css", "rel" => "stylesheet", "type" => "text/css")
|
61
103
|
}
|
62
|
-
xm.body { |b| b << "<div id=\"#{section.title}\">" +
|
104
|
+
xm.body { |b| b << "<div id=\"#{section.title}\">" + convert_to_html(section.content) + "</div>" }
|
63
105
|
}
|
64
106
|
|
65
107
|
file.close
|
66
108
|
end
|
67
109
|
end
|
68
110
|
|
69
|
-
def self.generate_content_opf(path,
|
111
|
+
def self.generate_content_opf(path, ebook_object)
|
70
112
|
file = File.new(path + "/content.opf", "wb")
|
71
113
|
|
72
114
|
xm = Builder::XmlMarkup.new(:target => file, :indent => 2)
|
73
115
|
xm.instruct!
|
74
116
|
xm.package("xmlns" => "http://www.idpf.org/2007/opf", "unique-identifier" => "BookId", "version" => "2.0") {
|
75
117
|
xm.metadata("xmlns:dc" => "http://purl.org/dc/elements/1.1/", "xmlns:opf" => "http://www.idpf.org/2007/opf") {
|
76
|
-
xm.tag!("dc:identifier",
|
77
|
-
xm.tag!("dc:title",
|
78
|
-
xm.tag!("dc:creator",
|
79
|
-
xm.tag!("dc:language",
|
80
|
-
xm.tag!("dc:date",
|
81
|
-
xm.tag!("dc:description",
|
82
|
-
xm.tag!("dc:publisher",
|
83
|
-
xm.tag!("dc:rights",
|
84
|
-
xm.tag!("dc:subject",
|
85
|
-
xm.tag!("dc:contributor",
|
118
|
+
xm.tag!("dc:identifier", ebook_object.id, "id" => "BookId", "opf:scheme" => "UUID")
|
119
|
+
xm.tag!("dc:title", ebook_object.title)
|
120
|
+
xm.tag!("dc:creator", ebook_object.creator, "opf:role" => "aut")
|
121
|
+
xm.tag!("dc:language", ebook_object.language)
|
122
|
+
xm.tag!("dc:date", ebook_object.updated_at, "opf:event" => "modification")
|
123
|
+
xm.tag!("dc:description", ebook_object.description)
|
124
|
+
xm.tag!("dc:publisher", ebook_object.publisher)
|
125
|
+
xm.tag!("dc:rights", ebook_object.rights)
|
126
|
+
xm.tag!("dc:subject", ebook_object.subject)
|
127
|
+
xm.tag!("dc:contributor", ebook_object.contributor, "opf:role" => "cov")
|
86
128
|
}
|
87
129
|
xm.manifest {
|
88
130
|
xm.item("href" => "toc.ncx", "id" => "ncx", "media-type" => "application/x-dtbncx+xml")
|
89
131
|
xm.item("href" => "Styles/style.css", "media-type" => "text/css")
|
90
|
-
|
132
|
+
ebook_object.sections.each do |section|
|
91
133
|
xm.item("href" => "Text/Section#{section.position}.html", "id" => "Section#{section.position}.html", "media-type" => "application/xhtml+xml")
|
92
134
|
end
|
93
135
|
}
|
94
136
|
xm.spine("toc" => "ncx") {
|
95
|
-
|
137
|
+
ebook_object.sections.each do |section|
|
96
138
|
xm.itemref("idref" => "Section#{section.position}.html")
|
97
139
|
end
|
98
140
|
}
|
@@ -100,11 +142,9 @@ module EbookGenerator
|
|
100
142
|
}
|
101
143
|
|
102
144
|
file.close
|
103
|
-
|
104
145
|
end
|
105
146
|
|
106
|
-
def self.generate_toc_ncx(path,
|
107
|
-
|
147
|
+
def self.generate_toc_ncx(path, ebook_object)
|
108
148
|
file = File.new(path + "/toc.ncx", "wb")
|
109
149
|
|
110
150
|
xm = Builder::XmlMarkup.new(:target => file, :indent => 2)
|
@@ -112,16 +152,16 @@ module EbookGenerator
|
|
112
152
|
xm.declare! :DOCTYPE, :ncx, :PUBLIC, "-//NISO//DTD ncx 2005-1//EN", "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd"
|
113
153
|
xm.ncx("xmlns" => "http://www.daisy.org/z3986/2005/ncx/", "version" => "2005-1") {
|
114
154
|
xm.head {
|
115
|
-
xm.meta("content" => "urn:uuid:${
|
155
|
+
xm.meta("content" => "urn:uuid:${ebook_object.id}", "name" => "dtb:uid")
|
116
156
|
xm.meta("content" => "2", "name" => "dtb:depth")
|
117
157
|
xm.meta("content" => "0", "name" => "dtb:totalPageCount")
|
118
158
|
xm.meta("content" => "0", "name" => "dtb:maxPageNumber")
|
119
159
|
}
|
120
160
|
xm.docTitle {
|
121
|
-
xm.text(
|
161
|
+
xm.text(ebook_object.title)
|
122
162
|
}
|
123
163
|
xm.navMap {
|
124
|
-
|
164
|
+
ebook_object.sections.each do |section|
|
125
165
|
xm.navPoint("id" => "navPoint-#{section.position}", "playOrder" => "#{section.position}") {
|
126
166
|
xm.navLabel {
|
127
167
|
xm.text(section.title)
|
@@ -133,7 +173,6 @@ module EbookGenerator
|
|
133
173
|
}
|
134
174
|
|
135
175
|
file.close
|
136
|
-
|
137
176
|
end
|
138
177
|
|
139
178
|
def self.change_perms(files)
|
@@ -146,44 +185,8 @@ module EbookGenerator
|
|
146
185
|
FileUtils.remove_dir(directory, true)
|
147
186
|
end
|
148
187
|
|
149
|
-
def self.
|
150
|
-
|
151
|
-
#
|
152
|
-
path = Rails.root.to_s + "/tmp/#{ebook_id}"
|
153
|
-
|
154
|
-
# Make all required dirs
|
155
|
-
dirs = [path, path + "/META-INF", path + "/OEBPS", path + "/OEBPS/Text", path + "/OEBPS/Styles"]
|
156
|
-
make_dirs(dirs)
|
157
|
-
|
158
|
-
# Create container.xml
|
159
|
-
generate_container(path + "/META-INF")
|
160
|
-
|
161
|
-
# Create mimetype
|
162
|
-
generate_mimetype(path + "/mimetype")
|
163
|
-
|
164
|
-
# Move default stylesheet into styles folder
|
165
|
-
copy_style(path + "/OEBPS/Styles")
|
166
|
-
|
167
|
-
# loop through each section loading the reference header and saving as it's own section
|
168
|
-
attrs = Ebook.find(ebook_id)
|
169
|
-
generate_sections(path + "/OEBPS/Text", attrs)
|
170
|
-
|
171
|
-
# generate toc based on the number of sections generated
|
172
|
-
generate_content_opf(path + "/OEBPS", attrs)
|
173
|
-
generate_toc_ncx(path + "/OEBPS", attrs)
|
174
|
-
|
175
|
-
# change permissions for files that need to be executable
|
176
|
-
files = [path + "/OEBPS/toc.ncx", path + "/OEBPS/content.opf", path + "/mimetype"]
|
177
|
-
change_perms(files)
|
178
|
-
|
179
|
-
# zip all files
|
180
|
-
zipfile_name = Rails.root.to_s + "/tmp/" + attrs.slug + ".epub"
|
181
|
-
zf = ZipFileProcessor.new(path, zipfile_name)
|
182
|
-
zf.write
|
183
|
-
|
184
|
-
# Clean up the tmp dir
|
185
|
-
remove_tmp_dir(path + "/")
|
186
|
-
|
188
|
+
def self.generate_mobi(path, slug)
|
189
|
+
`#{Rails.root.to_s}/bin/kindlegen #{path} -o #{slug}.mobi`
|
190
|
+
"#{Rails.root.to_s}/tmp/#{slug}.mobi"
|
187
191
|
end
|
188
|
-
|
189
192
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
require 'rails/generators/active_record'
|
4
|
+
|
5
|
+
class EbookGeneratorGenerator < ActiveRecord::Generators::Base
|
6
|
+
argument :name, type: :string, default: 'random_name'
|
7
|
+
|
8
|
+
source_root File.expand_path('../templates', __FILE__)
|
9
|
+
|
10
|
+
def create_model_files
|
11
|
+
template "ebook.rb", "app/models/ebook.rb"
|
12
|
+
template "section.rb", "app/models/section.rb"
|
13
|
+
migration_template "create_ebooks.rb", "db/migrate/create_ebooks.rb"
|
14
|
+
migration_template "create_sections.rb", "db/migrate/create_sections.rb"
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateEbooks < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :ebooks, force: true do |t|
|
4
|
+
t.string :title, null: false
|
5
|
+
t.string :creator
|
6
|
+
t.string :language, limit: 2, null: false
|
7
|
+
t.string :contributor
|
8
|
+
t.text :description
|
9
|
+
t.string :publisher
|
10
|
+
t.text :rights
|
11
|
+
t.string :subject
|
12
|
+
t.string :slug, null: false
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :ebooks, :slug, unique: true
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateSections < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :sections, force: true do |t|
|
4
|
+
t.belongs_to :ebook
|
5
|
+
t.string :title, null: false
|
6
|
+
t.text :content, null: false
|
7
|
+
t.integer :position, null: false
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :sections, ["position"], name: "index_sections_on_position", using: :btree
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|