mkwebook 0.1.0 → 0.1.1

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 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