mkwebook 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91b2c6fce12ddd620f497fc5a902c000525d8581e34ede7107ac55b2771871e4
4
- data.tar.gz: 11ca2232b8c30848b352737eb9afebafbfda49e0a974b93586627390a524d977
3
+ metadata.gz: cac7d7fac942ec8612546dbb09f9a7063ef5370bb8760f925364d9c7105d707a
4
+ data.tar.gz: 522c06fa9782203daedfdb2d97ac1b1e820b9f9d079b746281c876c63672bc7f
5
5
  SHA512:
6
- metadata.gz: 7aaafd73130c773b6f2b5a942ab525ee95fb84a4a7b01e4ee890edabc1554563e9f3c6dc3fbd36b3321212a50969006e1a9bfd5efb0e0028a92b18bae4df319d
7
- data.tar.gz: c8578b37ba25133d81e487f5486c0eba9c16712d048b64e0bf2336ef28a0310ce5b93994bc43634c692e671d043a1b97a70124d0ddf616e9330ebf669e0c32ea
6
+ metadata.gz: 84fbb2098303f5a4781fb9c1940c90d292099705dbbee3481c5ec48f2bd43b1fa219ed66a53418a7b8103555864ca3b00e1e09339aa6e3f7ea50c92259269c6b
7
+ data.tar.gz: 03a676487e80b8bfb2daf1fe2680369c2fcb064d22cc22ca408682477adb13eca00b472bd7299c759a092cbde4551d495af5ba8c6294cf94801f14a4c11213f8
data/Gemfile.lock CHANGED
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mkwebook (0.1.0)
4
+ mkwebook (0.1.1)
5
5
  activesupport (>= 6.1.5)
6
6
  concurrent-ruby
7
7
  ferrum (>= 0.13)
8
+ sqlite3 (~> 1.5.4)
8
9
  thor (>= 1.2.1)
9
10
 
10
11
  GEM
@@ -40,6 +41,7 @@ GEM
40
41
  yard (~> 0.9.11)
41
42
  public_suffix (5.0.0)
42
43
  rake (12.3.3)
44
+ sqlite3 (1.5.4-x86_64-darwin)
43
45
  thor (1.2.1)
44
46
  tzinfo (2.0.5)
45
47
  concurrent-ruby (~> 1.0)
data/lib/mkwebook/app.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'fileutils'
2
+ require 'sqlite3'
2
3
  require 'Mkwebook/config'
3
4
  require 'ferrum'
4
5
  require 'pry-byebug'
@@ -14,7 +15,7 @@ module Mkwebook
14
15
  Dir.chdir(cli_options[:work_dir])
15
16
  end
16
17
  @cli_options = cli_options
17
- @config = Mkwebook::Config.new(@cli_options[:pause] || @cli_options[:pause_on_error] || @cli_options[:single_thread])
18
+ @config = Mkwebook::Config.new(@cli_options)
18
19
  end
19
20
 
20
21
  def create_config
@@ -25,17 +26,32 @@ module Mkwebook
25
26
  File.join(Mkwebook::GEM_ROOT, 'template', 'mkwebook.yml')
26
27
  end
27
28
 
28
- def make
29
- make_index
30
- make_pages
29
+ def download
30
+ download_index
31
+ download_pages
31
32
  end
32
33
 
33
34
  def prepare_browser
34
35
  @browser = Ferrum::Browser.new(browser_options)
35
36
  @browser_context = browser.contexts.create
37
+ set_auth_info if @config.authentication?
36
38
  end
37
39
 
38
- def make_index
40
+ def set_auth_info
41
+ page = @browser_context.create_page
42
+ page.go_to(@config[:authentication][:url])
43
+ if @config[:authentication][:cookies]
44
+ page.execute("document.cookie = '#{@config[:authentication][:cookies]}'")
45
+ end
46
+
47
+ if @config[:authentication][:local_storage]
48
+ @config[:authentication][:local_storage].each do |key, value|
49
+ page.execute("localStorage.setItem('#{key}', '#{value}')")
50
+ end
51
+ end
52
+ end
53
+
54
+ def download_index
39
55
  prepare_browser
40
56
  index_page = @browser_context.create_page
41
57
  index_page.go_to(@config[:index_page][:url])
@@ -86,7 +102,9 @@ module Mkwebook
86
102
  binding.pry
87
103
  end
88
104
 
89
- def make_pages
105
+ def download_pages
106
+
107
+ append_extra_pages
90
108
 
91
109
  pool = Concurrent::FixedThreadPool.new(@config[:concurrency])
92
110
 
@@ -148,6 +166,24 @@ module Mkwebook
148
166
 
149
167
  pool.shutdown
150
168
  pool.wait_for_termination
169
+
170
+ post_process
171
+ end
172
+
173
+ def post_process
174
+ @config[:post_process].try do |script|
175
+ if File.file?(script)
176
+ system(script)
177
+ else
178
+ system('bash', '-c', script)
179
+ end
180
+ end
181
+ end
182
+
183
+ def append_extra_pages
184
+ @config[:extra_pages]&.each do |url|
185
+ @page_urls << url
186
+ end
151
187
  end
152
188
 
153
189
  def download_assets(page, assets_config, page_uri = nil)
@@ -170,6 +206,105 @@ module Mkwebook
170
206
  end
171
207
  end
172
208
 
209
+ def make_docset
210
+ docset_config = @config[:docset]
211
+ docset_name = "#{docset_config[:name]}.docset"
212
+ doc_path = "#{docset_name}/Contents/Resources/Documents"
213
+ dsidx_path = "#{docset_name}/Contents/Resources/docSet.dsidx"
214
+ icon_path = "#{docset_name}/icon.png"
215
+ info = "#{docset_name}/Contents/info.plist"
216
+
217
+ if Dir.exist?(docset_name)
218
+ puts 'Docset directory already exist!'
219
+ else
220
+ FileUtils.mkdir_p(doc_path)
221
+ puts "Create the docset directory!"
222
+ end
223
+
224
+ # Copy files
225
+ FileUtils.cp_r(Dir.glob("*") - [docset_name], doc_path)
226
+ puts 'Copy the HTML documentations!'
227
+
228
+ # Init SQLite
229
+
230
+ FileUtils.rm_f(dsidx_path)
231
+ db = SQLite3::Database.new(dsidx_path)
232
+ db.execute <<-SQL
233
+ CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT);
234
+ SQL
235
+ db.execute <<-SQL
236
+ CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path);
237
+ SQL
238
+ puts 'Create the SQLite Index'
239
+
240
+ pages = Dir.glob("#{doc_path}/**/*.html").select do |file|
241
+ docset_config[:pages].find { |page| file =~ Regexp.new(page[:url_pattern]) }
242
+ end
243
+
244
+ pages = pages[0, @cli_options[:limit]] if @cli_options[:limit]
245
+
246
+ prepare_browser
247
+
248
+ page = @browser_context.create_page
249
+
250
+ elements = pages.flat_map do |file|
251
+ begin
252
+ page.go_to("file://#{File.expand_path(file)}")
253
+ page_config = docset_config[:pages].find { |page| file =~ Regexp.new(page[:url_pattern]) }
254
+ page.evaluate(page_config[:extractor]) || []
255
+ rescue => e
256
+ puts e.message
257
+ puts e.backtrace
258
+ end
259
+ end
260
+
261
+ elements.uniq.compact.each do |element|
262
+ name = element['name']
263
+ type = element['type']
264
+ path = element['path'].sub(%r{.*\.docset/Contents/Resources/Documents}, '')
265
+ db.execute('INSERT OR IGNORE INTO searchIndex(name, type, path) VALUES (?, ?, ?);', [name, type, path])
266
+ end
267
+
268
+ plist_content = <<-PLIST
269
+ <?xml version="1.0" encoding="UTF-8"?>
270
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
271
+ <plist version="1.0">
272
+ <dict>
273
+ <key>CFBundleIdentifier</key>
274
+ <string>#{docset_name.sub(/.docset/, '')}</string>
275
+ <key>CFBundleName</key>
276
+ <string>#{docset_name.sub(/.docset/, '')}</string>
277
+ <key>DashDocSetFamily</key>
278
+ <string>#{docset_name.sub(/.docset/, '')}</string>
279
+ <key>DocSetPlatformFamily</key>
280
+ <string>#{docset_config[:keyword] || docset_name.downcaseload.sub(/.docset/, '')}</string>
281
+ <key>isDashDocset</key>
282
+ <true/>
283
+ <key>isJavaScriptEnabled</key>
284
+ <true/>
285
+ <key>dashIndexFilePath</key>
286
+ <string>#{docset_config[:index]}</string>
287
+ </dict>
288
+ </plist>
289
+ PLIST
290
+ File.open(info, 'w') { |f| f.write(plist_content)}
291
+
292
+ # Add icon
293
+ if docset_config[:icon]
294
+ if docset_config[:icon].end_with?('.png')
295
+ FileUtils.cp(docset_config[:icon], icon_path)
296
+ puts 'Create the icon for docset!'
297
+ else
298
+ puts '**Error**: icon file should be a valid PNG image!'
299
+ exit(2)
300
+ end
301
+ end
302
+ end
303
+
304
+ def list_entry_types
305
+ puts IO.read("#{__dir__}/entry_types.txt")
306
+ end
307
+
173
308
  private
174
309
 
175
310
  def browser_options
data/lib/mkwebook/cli.rb CHANGED
@@ -9,6 +9,7 @@ module Mkwebook
9
9
  end
10
10
 
11
11
  class_option :work_dir, :type => :string, :aliases => '-d', :default => '.', :desc => 'Working directory'
12
+ class_option :headmode, :type => :boolean, :aliases => '-H', :default => nil, :desc => "Headful mode, this option will override the config file's headless setting"
12
13
  class_option :pause_on_error, :type => :boolean, :aliases => '-e', :default => false, :desc => 'Pause on error, this option will force concurrency off'
13
14
  desc 'init', 'Create config file in current directory'
14
15
  def init
@@ -16,18 +17,29 @@ module Mkwebook
16
17
  end
17
18
 
18
19
  option :pause, :type => :boolean, :aliases => '-p', :desc => 'Pause after processing index page'
19
- desc 'make_index', 'Download and process index page'
20
- def make_index
21
- Mkwebook::App.new(options).make_index
20
+ desc 'download_index', 'Download and process index page'
21
+ def download_index
22
+ Mkwebook::App.new(options).download_index
22
23
  end
23
24
 
24
25
  option :limit, :type => :numeric, :aliases => '-l', :desc => 'Limit number of pages, specially for debugging'
25
26
  option :pause, :type => :boolean, :aliases => '-P', :desc => 'Pause before quit, this option will force concurrency off'
26
27
  option :pause_on_index, :type => :boolean, :aliases => '-p', :desc => 'Pause after processing index page'
27
28
  option :single_thread, :type => :boolean, :aliases => '-s', :desc => 'Force conccurency off'
28
- desc 'make', 'Download and process html files'
29
- def make
30
- Mkwebook::App.new(options).make
29
+ desc 'download', 'Download and process html files'
30
+ def download
31
+ Mkwebook::App.new(options).download
32
+ end
33
+
34
+ option :limit, :type => :numeric, :aliases => '-l', :desc => 'Limit number of pages, specially for debugging'
35
+ option :list, :type => :boolean, :aliases => '-L', :desc => 'List all available Dash.app entry types'
36
+ desc 'docset', 'Create docset'
37
+ def docset
38
+ if options[:list]
39
+ Mkwebook::App.new(options).list_entry_types
40
+ else
41
+ Mkwebook::App.new(options).make_docset
42
+ end
31
43
  end
32
44
 
33
45
  desc 'version', 'Print version'
@@ -1 +0,0 @@
1
- require 'mkwebook/concerns/global_data_definition'
@@ -3,29 +3,31 @@ require 'etc'
3
3
 
4
4
  module Mkwebook
5
5
  class Config < SimpleDelegator
6
- attr_accessor :file, :config
6
+ attr_accessor :file, :config, :cli_options
7
7
 
8
- def initialize(force_concurrency_off)
8
+ def initialize(cli_options = {})
9
9
  super(nil)
10
+ @cli_options = cli_options
10
11
  @file = find_mkwebook_yaml
11
12
  if @file && File.exist?(@file)
12
- @config = load(@file, force_concurrency_off)
13
+ @config = load(@file)
13
14
  __setobj__(@config)
14
15
  else
15
16
  __setobj__(self)
16
17
  end
17
18
  end
18
19
 
19
- def load(config_file, force_concurrency_off)
20
+ def load(config_file)
20
21
  default_config = {
21
22
  'browser' => {
22
- 'headless' => true
23
+ 'headless' => true,
23
24
  },
24
25
  'concurrency': 1
25
26
  }
26
27
  config = YAML.load_file(config_file)
27
28
  config = default_config.deep_merge(config).deep_transform_keys! { |k| k.to_s.underscore.to_sym }
28
- config[:concurrency] = 1 if force_concurrency_off
29
+ config[:concurrency] = 1 if force_single_threaded?
30
+ config[:browser][:headless] = false if @cli_options[:headmode]
29
31
  config
30
32
  end
31
33
 
@@ -33,6 +35,10 @@ module Mkwebook
33
35
  config[:concurrency].present?
34
36
  end
35
37
 
38
+ def authentication?
39
+ config.dig(:authentication, :cookies).present? || config.dig(:authentication, :local_storage).present?
40
+ end
41
+
36
42
  def find_mkwebook_yaml
37
43
  dir = Dir.pwd
38
44
  while dir != '/'
@@ -45,5 +51,9 @@ module Mkwebook
45
51
  dir = File.dirname(dir)
46
52
  end
47
53
  end
54
+
55
+ def force_single_threaded?
56
+ @cli_options[:pause] || @cli_options[:pause_on_error] || @cli_options[:single_thread]
57
+ end
48
58
  end
49
59
  end
@@ -0,0 +1,75 @@
1
+ Annotation
2
+ Attribute
3
+ Binding
4
+ Builtin
5
+ Callback
6
+ Category
7
+ Class
8
+ Command
9
+ Component
10
+ Constant
11
+ Constructor
12
+ Define
13
+ Delegate
14
+ Diagram
15
+ Directive
16
+ Element
17
+ Entry
18
+ Enum
19
+ Environment
20
+ Error
21
+ Event
22
+ Exception
23
+ Extension
24
+ Field
25
+ File
26
+ Filter
27
+ Framework
28
+ Function
29
+ Global
30
+ Guide
31
+ Hook
32
+ Instance
33
+ Instruction
34
+ Interface
35
+ Keyword
36
+ Library
37
+ Literal
38
+ Macro
39
+ Method
40
+ Mixin
41
+ Modifier
42
+ Module
43
+ Namespace
44
+ Notation
45
+ Object
46
+ Operator
47
+ Option
48
+ Package
49
+ Parameter
50
+ Plugin
51
+ Procedure
52
+ Property
53
+ Protocol
54
+ Provider
55
+ Provisioner
56
+ Query
57
+ Record
58
+ Resource
59
+ Sample
60
+ Section
61
+ Service
62
+ Setting
63
+ Shortcut
64
+ Statement
65
+ Struct
66
+ Style
67
+ Subroutine
68
+ Tag
69
+ Test
70
+ Trait
71
+ Type
72
+ Union
73
+ Value
74
+ Variable
75
+ Word
@@ -1,3 +1,3 @@
1
1
  module Mkwebook
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -6,6 +6,13 @@ browser: # browser settings
6
6
 
7
7
  concurrency: 16 # number of concurrent threads, default is no conccurency
8
8
 
9
+ authentication: # authentication settings
10
+ url: https://example.com/login # any page url which for inject cookie and local storage
11
+ cookies: "auth_cookie_id=demo" # cookie string to be injected
12
+ local-storage: # local storage to be injected
13
+ username: demo # key and value
14
+ auth_token: demo # key and value
15
+
9
16
  index-page: # index page settings
10
17
  url: https://clojure.org/guides/repl/introduction # URL of index page
11
18
  title: Clojure Guides # title for the book, use page's title if not set
@@ -41,4 +48,36 @@ pages: # settings for content pages
41
48
  attr: href
42
49
  - selector: "script[src]"
43
50
  attr: src
51
+
52
+ extra-pages: # settings for extra pages
53
+ - https://www.example.com/extra-page-1
54
+
55
+ post-process: | # Shell script to be executed after the book is downloaded
56
+ find . -name '*.html' -exec sed -i 's/https:\/\/clojure.org\/guides\/repl\/introduction/..\/index.html/g' {} \;
44
57
 
58
+ docset: # config for generate docset
59
+ name: "Clojure Guides" # docset name
60
+ keyword: "clojure" # docset keyword
61
+ icon: "clojure.png" # docset icon
62
+ index: "/index.html" # docset index page
63
+ pages: # docset pages config
64
+ - url-pattern: 'index.html' # URL pattern for docset page, will match against local downloaded pages
65
+ extractor: | # JavaScript code to extract the content for docset page
66
+ (function() {
67
+ var links = [...document.querySelectorAll('a.data-url')];
68
+ return links.map(link => {
69
+ var name = link.innerText;
70
+ var tag = link;
71
+ while (tag.tagName != 'BODY') {
72
+ tag = tag.parentElement;
73
+ if (tag.previousElementSibling && tag.previousElementSibling.tagName == 'H1') {
74
+ name = tag.previousElementSibling.innerText + ' - ' + name;
75
+ }
76
+ }
77
+ return { # Should return an array of objects with name, path, type attributes
78
+ path: link.href, # path of the page, should be relative to DEMO.docset/Contents/Resources/Documents (starts with /)
79
+ name: name, # name of extracted element
80
+ type: 'Guide' # type of extracted element
81
+ };
82
+ });
83
+ })();
data/mkwebook.gemspec CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.add_dependency 'activesupport', '>= 6.1.5'
25
25
  spec.add_dependency 'concurrent-ruby'
26
26
  spec.add_dependency 'ferrum', '>= 0.13'
27
+ spec.add_dependency 'sqlite3', '~> 1.5.4'
27
28
  spec.add_dependency 'thor', '>= 1.2.1'
28
29
 
29
30
  spec.add_development_dependency 'pry'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mkwebook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liu Xiang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-12-09 00:00:00.000000000 Z
11
+ date: 2022-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.13'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.5.4
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.5.4
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: thor
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -132,8 +146,8 @@ files:
132
146
  - lib/mkwebook/cli.rb
133
147
  - lib/mkwebook/commands.rb
134
148
  - lib/mkwebook/concerns.rb
135
- - lib/mkwebook/concerns/global_data_definition.rb
136
149
  - lib/mkwebook/config.rb
150
+ - lib/mkwebook/entry_types.txt
137
151
  - lib/mkwebook/ext.rb
138
152
  - lib/mkwebook/ext/string.rb
139
153
  - lib/mkwebook/version.rb
@@ -1,244 +0,0 @@
1
- require 'active_support/concern'
2
-
3
- module Mkwebook
4
- module Concerns
5
- module GlobalDataDefinition
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
-
10
- # Example:
11
- #
12
- # create_table :post, id: false, primary_key: :id do |t|
13
- # t.column :id, :bigint, precison: 19, comment: 'ID'
14
- # t.column :name, :string, comment: '名称'
15
- # t.column :gmt_created, :datetime, comment: '创建时间'
16
- # t.column :gmt_modified, :datetime, comment: '最后修改时间'
17
- # end
18
- #
19
- # Creates a new table with the name +table_name+. +table_name+ may either
20
- # be a String or a Symbol.
21
- #
22
- # There are two ways to work with #create_table. You can use the block
23
- # form or the regular form, like this:
24
- #
25
- # === Block form
26
- #
27
- # # create_table() passes a TableDefinition object to the block.
28
- # # This form will not only create the table, but also columns for the
29
- # # table.
30
- #
31
- # create_table(:suppliers) do |t|
32
- # t.column :name, :string, limit: 60
33
- # # Other fields here
34
- # end
35
- #
36
- # === Block form, with shorthand
37
- #
38
- # # You can also use the column types as method calls, rather than calling the column method.
39
- # create_table(:suppliers) do |t|
40
- # t.string :name, limit: 60
41
- # # Other fields here
42
- # end
43
- #
44
- # === Regular form
45
- #
46
- # # Creates a table called 'suppliers' with no columns.
47
- # create_table(:suppliers)
48
- # # Add a column to 'suppliers'.
49
- # add_column(:suppliers, :name, :string, {limit: 60})
50
- #
51
- # The +options+ hash can include the following keys:
52
- # [<tt>:id</tt>]
53
- # Whether to automatically add a primary key column. Defaults to true.
54
- # Join tables for {ActiveRecord::Base.has_and_belongs_to_many}[rdoc-ref:Associations::ClassMethods#has_and_belongs_to_many] should set it to false.
55
- #
56
- # A Symbol can be used to specify the type of the generated primary key column.
57
- # [<tt>:primary_key</tt>]
58
- # The name of the primary key, if one is to be added automatically.
59
- # Defaults to +id+. If <tt>:id</tt> is false, then this option is ignored.
60
- #
61
- # If an array is passed, a composite primary key will be created.
62
- #
63
- # Note that Active Record models will automatically detect their
64
- # primary key. This can be avoided by using
65
- # {self.primary_key=}[rdoc-ref:AttributeMethods::PrimaryKey::ClassMethods#primary_key=] on the model
66
- # to define the key explicitly.
67
- #
68
- # [<tt>:options</tt>]
69
- # Any extra options you want appended to the table definition.
70
- # [<tt>:temporary</tt>]
71
- # Make a temporary table.
72
- # [<tt>:force</tt>]
73
- # Set to true to drop the table before creating it.
74
- # Set to +:cascade+ to drop dependent objects as well.
75
- # Defaults to false.
76
- # [<tt>:if_not_exists</tt>]
77
- # Set to true to avoid raising an error when the table already exists.
78
- # Defaults to false.
79
- # [<tt>:as</tt>]
80
- # SQL to use to generate the table. When this option is used, the block is
81
- # ignored, as are the <tt>:id</tt> and <tt>:primary_key</tt> options.
82
- #
83
- # ====== Add a backend specific option to the generated SQL (MySQL)
84
- #
85
- # create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4')
86
- #
87
- # generates:
88
- #
89
- # CREATE TABLE suppliers (
90
- # id bigint auto_increment PRIMARY KEY
91
- # ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
92
- #
93
- # ====== Rename the primary key column
94
- #
95
- # create_table(:objects, primary_key: 'guid') do |t|
96
- # t.column :name, :string, limit: 80
97
- # end
98
- #
99
- # generates:
100
- #
101
- # CREATE TABLE objects (
102
- # guid bigint auto_increment PRIMARY KEY,
103
- # name varchar(80)
104
- # )
105
- #
106
- # ====== Change the primary key column type
107
- #
108
- # create_table(:tags, id: :string) do |t|
109
- # t.column :label, :string
110
- # end
111
- #
112
- # generates:
113
- #
114
- # CREATE TABLE tags (
115
- # id varchar PRIMARY KEY,
116
- # label varchar
117
- # )
118
- #
119
- # ====== Create a composite primary key
120
- #
121
- # create_table(:orders, primary_key: [:product_id, :client_id]) do |t|
122
- # t.belongs_to :product
123
- # t.belongs_to :client
124
- # end
125
- #
126
- # generates:
127
- #
128
- # CREATE TABLE order (
129
- # product_id bigint NOT NULL,
130
- # client_id bigint NOT NULL
131
- # );
132
- #
133
- # ALTER TABLE ONLY "orders"
134
- # ADD CONSTRAINT orders_pkey PRIMARY KEY (product_id, client_id);
135
- #
136
- # ====== Do not add a primary key column
137
- #
138
- # create_table(:categories_suppliers, id: false) do |t|
139
- # t.column :category_id, :bigint
140
- # t.column :supplier_id, :bigint
141
- # end
142
- #
143
- # generates:
144
- #
145
- # CREATE TABLE categories_suppliers (
146
- # category_id bigint,
147
- # supplier_id bigint
148
- # )
149
- #
150
- # ====== Create a temporary table based on a query
151
- #
152
- # create_table(:long_query, temporary: true,
153
- # as: "SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id")
154
- #
155
- # generates:
156
- #
157
- # CREATE TEMPORARY TABLE long_query AS
158
- # SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id
159
- #
160
- # See also TableDefinition#column for details on how to create columns.
161
- def create_table(table_name, **options, &blk)
162
- ActiveRecord::Base.connection.create_table(table_name, **options, &blk)
163
- end
164
-
165
- # Creates a new join table with the name created using the lexical order of the first two
166
- # arguments. These arguments can be a String or a Symbol.
167
- #
168
- # # Creates a table called 'assemblies_parts' with no id.
169
- # create_join_table(:assemblies, :parts)
170
- #
171
- # You can pass an +options+ hash which can include the following keys:
172
- # [<tt>:table_name</tt>]
173
- # Sets the table name, overriding the default.
174
- # [<tt>:column_options</tt>]
175
- # Any extra options you want appended to the columns definition.
176
- # [<tt>:options</tt>]
177
- # Any extra options you want appended to the table definition.
178
- # [<tt>:temporary</tt>]
179
- # Make a temporary table.
180
- # [<tt>:force</tt>]
181
- # Set to true to drop the table before creating it.
182
- # Defaults to false.
183
- #
184
- # Note that #create_join_table does not create any indices by default; you can use
185
- # its block form to do so yourself:
186
- #
187
- # create_join_table :products, :categories do |t|
188
- # t.index :product_id
189
- # t.index :category_id
190
- # end
191
- #
192
- # ====== Add a backend specific option to the generated SQL (MySQL)
193
- #
194
- # create_join_table(:assemblies, :parts, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
195
- #
196
- # generates:
197
- #
198
- # CREATE TABLE assemblies_parts (
199
- # assembly_id bigint NOT NULL,
200
- # part_id bigint NOT NULL,
201
- # ) ENGINE=InnoDB DEFAULT CHARSET=utf8
202
- #
203
- def create_join_table(table_1, table_2, column_options: {}, **options)
204
- ActiveRecord::Base.connection.create_join_table(table_1, table_2, column_options, **options)
205
- end
206
-
207
- # Drops a table from the database.
208
- #
209
- # [<tt>:force</tt>]
210
- # Set to +:cascade+ to drop dependent objects as well.
211
- # Defaults to false.
212
- # [<tt>:if_exists</tt>]
213
- # Set to +true+ to only drop the table if it exists.
214
- # Defaults to false.
215
- #
216
- # Although this command ignores most +options+ and the block if one is given,
217
- # it can be helpful to provide these in a migration's +change+ method so it can be reverted.
218
- # In that case, +options+ and the block will be used by #create_table.
219
- def drop_table(table_name, **options)
220
- ActiveRecord::Base.connection.drop_table(table_name, **options)
221
- end
222
-
223
- # Drops the join table specified by the given arguments.
224
- # See #create_join_table for details.
225
- #
226
- # Although this command ignores the block if one is given, it can be helpful
227
- # to provide one in a migration's +change+ method so it can be reverted.
228
- # In that case, the block will be used by #create_join_table.
229
- def drop_join_table(table_1, table_2, **options)
230
- ActiveRecord::Base.connection.drop_join_table(table_1, table_2, **options)
231
- end
232
-
233
- # Renames a table.
234
- #
235
- # rename_table('octopuses', 'octopi')
236
- #
237
- def rename_table(table_name, new_name)
238
- ActiveRecord::Base.connection.rename_table(table_name, new_name)
239
- end
240
-
241
- end
242
- end
243
- end
244
- end