Class: Knitsearch::InstallGenerator

Inherits:
Rails::Generators::Base
  • Object
show all
Includes:
Rails::Generators::Migration
Defined in:
lib/generators/knitsearch/install/install_generator.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.next_migration_number(dirname) ⇒ Object



27
28
29
# File 'lib/generators/knitsearch/install/install_generator.rb', line 27

def self.next_migration_number(dirname)
  ::ActiveRecord::Generators::Base.next_migration_number(dirname)
end

Instance Method Details

#create_migrationObject



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/generators/knitsearch/install/install_generator.rb', line 75

def create_migration
  timestamp = self.class.next_migration_number("db/migrate")
  migration_filename = "#{timestamp}_create_#{fts_table_name}.rb"
  migration_path = File.join(destination_root, "db/migrate", migration_filename)

  if options[:tokenizer].present?
    puts "WARNING: --tokenizer is deprecated. Use --dictionary instead."
  end

  rich_text_cols = detect_rich_text_columns
  dictionary = options[:dictionary] || "simple"
  associated = parse_associated_against

  associated_clause = associated.any? ? ",\n        associated_against: #{associated.inspect}" : ""

  migration_content = <<~RUBY
    class Create#{fts_table_name.camelize} < ActiveRecord::Migration#{migration_version}
      include Knitsearch::Migration

      def up
        create_searchable_table #{source_table_name.inspect},
          columns: #{columns.inspect},
          dictionary: #{dictionary.inspect},
          rich_text_columns: #{rich_text_cols.inspect}#{associated_clause}
      end

      def down
        drop_searchable_table #{source_table_name.inspect}
      end
    end
  RUBY

  create_file migration_path, migration_content

  puts "\nMigration created: #{migration_path}"
  puts "\nNext steps:"
  puts "  1. bin/rails db:migrate"
  if associated.any?
    puts "  2. Add to #{model_name} model:"
    puts "       searchable_by("
    puts "         against: { #{columns.map { |c| "#{c}: \"A\"" }.join(", ")} },"
    puts "         associated_against: #{associated.inspect}"
    puts "       )"
    puts "  3. bin/rails knitsearch:backfill[#{model_name}]"
  else
    puts "  2. Add to #{model_name} model:"
    puts "       searchable_by(against: { #{columns.map { |c| "#{c}: \"A\"" }.join(", ")} })"
    puts "  3. bin/rails knitsearch:backfill[#{model_name}]"
  end
end

#verify_column_namesObject

Raises:

  • (::Thor::Error)


56
57
58
59
60
61
62
63
# File 'lib/generators/knitsearch/install/install_generator.rb', line 56

def verify_column_names
  invalid = columns.reject { |c| c.match?(/\A[a-z_][a-z0-9_]*\z/) }
  return if invalid.empty?

  raise ::Thor::Error,
        "Column names must be lowercase identifiers (letters, digits, underscores). " \
        "Invalid: #{invalid.inspect}"
end

#verify_columns_providedObject

Raises:

  • (::Thor::Error)


40
41
42
43
44
45
46
# File 'lib/generators/knitsearch/install/install_generator.rb', line 40

def verify_columns_provided
  return unless columns.empty?

  raise ::Thor::Error,
        "knitsearch:install requires at least one column to index. " \
        "Example: bin/rails generate knitsearch:install Article title body"
end

#verify_migration_not_existsObject

Raises:

  • (::Thor::Error)


65
66
67
68
69
70
71
72
73
# File 'lib/generators/knitsearch/install/install_generator.rb', line 65

def verify_migration_not_exists
  pattern = File.join(destination_root, "db/migrate/*_create_#{fts_table_name}.rb")
  existing = Dir.glob(pattern)
  return if existing.empty?

  raise ::Thor::Error,
        "A migration for #{fts_table_name} already exists: #{File.basename(existing.first)}. " \
        "Delete it first if you want to regenerate."
end

#verify_sqlite_adapterObject

Raises:

  • (::Thor::Error)


31
32
33
34
35
36
37
38
# File 'lib/generators/knitsearch/install/install_generator.rb', line 31

def verify_sqlite_adapter
  adapter = primary_adapter_from_configuration
  return if adapter == "sqlite3"

  raise ::Thor::Error,
        "knitsearch requires SQLite. Detected adapter: #{adapter.inspect}. " \
        "Use pg_search or your database's native FTS instead."
end

#verify_table_existsObject

Raises:

  • (::Thor::Error)


48
49
50
51
52
53
54
# File 'lib/generators/knitsearch/install/install_generator.rb', line 48

def verify_table_exists
  return if table_exists?(source_table_name)

  raise ::Thor::Error,
        "Table `#{source_table_name}` does not exist. " \
        "Run `bin/rails db:migrate` first to create the #{model_name} table."
end