better_model 2.0.0 → 2.1.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.
@@ -1,129 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators"
4
- require "rails/generators/migration"
5
-
6
- module BetterModel
7
- module Generators
8
- class TaggableGenerator < Rails::Generators::NamedBase
9
- include Rails::Generators::Migration
10
-
11
- source_root File.expand_path("templates", __dir__)
12
-
13
- class_option :column_name, type: :string, default: "tags",
14
- desc: "Name of the tags column (default: tags)"
15
- class_option :skip_index, type: :boolean, default: false,
16
- desc: "Skip adding GIN index (PostgreSQL only)"
17
-
18
- def self.next_migration_number(dirname)
19
- next_migration_number = current_migration_number(dirname) + 1
20
- ActiveRecord::Migration.next_migration_number(next_migration_number)
21
- end
22
-
23
- def create_migration_file
24
- migration_template "migration.rb.tt",
25
- "db/migrate/add_#{column_name}_to_#{table_name}.rb"
26
- end
27
-
28
- def show_readme
29
- # Display README as template to interpolate variables
30
- if behavior == :invoke
31
- say "=" * 79, :green
32
- say ""
33
- say "Taggable column has been added to your model!"
34
- say ""
35
- say "Next steps:"
36
- say ""
37
- say "1. Run the migration:"
38
- say " $ bin/rails db:migrate"
39
- say ""
40
- say "2. Add Taggable configuration to your model:"
41
- say ""
42
- say " class #{model_name} < ApplicationRecord"
43
- say " include BetterModel"
44
- say ""
45
- if postgresql?
46
- say " # PostgreSQL: No additional configuration needed"
47
- else
48
- say " # SQLite/MySQL: Add serialization for the tags column"
49
- say " serialize :#{column_name}, coder: JSON, type: Array"
50
- say ""
51
- end
52
- say " taggable do"
53
- say " tag_field :#{column_name} # Column name (default: :tags)"
54
- say " normalize true # Convert to lowercase"
55
- say " strip true # Remove whitespace (default)"
56
- say " min_length 2 # Minimum tag length"
57
- say " max_length 30 # Maximum tag length"
58
- say " validates_tags minimum: 1, maximum: 10"
59
- say " end"
60
- say " end"
61
- say ""
62
- say "3. Usage examples:"
63
- say ""
64
- say " # Add tags"
65
- say " #{name.underscore}.tag_with(\"ruby\", \"rails\", \"web\")"
66
- say ""
67
- say " # Remove tags"
68
- say " #{name.underscore}.untag(\"web\")"
69
- say ""
70
- say " # Replace all tags"
71
- say " #{name.underscore}.retag(\"ruby\", \"api\")"
72
- say ""
73
- say " # Check for tag"
74
- say " #{name.underscore}.tagged_with?(\"ruby\") # => true"
75
- say ""
76
- say " # CSV interface"
77
- say " #{name.underscore}.tag_list = \"ruby, rails, tutorial\""
78
- say " #{name.underscore}.tag_list # => \"ruby, rails, tutorial\""
79
- say ""
80
- say " # Search with tags (Predicable integration)"
81
- say " #{model_name}.#{column_name}_contains(\"ruby\")"
82
- say " #{model_name}.#{column_name}_overlaps([\"ruby\", \"python\"])"
83
- say " #{model_name}.#{column_name}_contains_all([\"ruby\", \"rails\"])"
84
- say ""
85
- say " # Statistics"
86
- say " #{model_name}.tag_counts # => {\"ruby\" => 45, \"rails\" => 38}"
87
- say " #{model_name}.popular_tags(limit: 10) # => [[\"ruby\", 45], [\"rails\", 38]]"
88
- say " #{model_name}.related_tags(\"ruby\", limit: 5) # => [\"rails\", \"gem\", \"tutorial\"]"
89
- say ""
90
- say "For more information, see: docs/taggable.md"
91
- say ""
92
- say "=" * 79, :green
93
- end
94
- end
95
-
96
- private
97
-
98
- def table_name
99
- name.tableize
100
- end
101
-
102
- def model_name
103
- name.camelize
104
- end
105
-
106
- def migration_class_name
107
- "Add#{column_name.camelize}To#{name.camelize.pluralize}"
108
- end
109
-
110
- def column_name
111
- options[:column_name]
112
- end
113
-
114
- def add_index?
115
- !options[:skip_index]
116
- end
117
-
118
- def postgresql?
119
- # Check if PostgreSQL adapter is being used
120
- # Note: This checks the current adapter, which may not reflect production
121
- # The migration template includes runtime detection as well
122
- return false unless defined?(ActiveRecord::Base)
123
-
124
- adapter_name = ActiveRecord::Base.connection.adapter_name rescue nil
125
- adapter_name == "PostgreSQL"
126
- end
127
- end
128
- end
129
- end
@@ -1,62 +0,0 @@
1
- ===============================================================================
2
-
3
- Taggable column has been added to your model!
4
-
5
- Next steps:
6
-
7
- 1. Run the migration:
8
- $ bin/rails db:migrate
9
-
10
- 2. Add Taggable configuration to your model:
11
-
12
- class <%= model_name %> < ApplicationRecord
13
- include BetterModel
14
-
15
- <% if postgresql? -%>
16
- # PostgreSQL: No additional configuration needed
17
- <% else -%>
18
- # SQLite/MySQL: Add serialization for the tags column
19
- serialize :<%= column_name %>, coder: JSON, type: Array
20
-
21
- <% end -%>
22
- taggable do
23
- tag_field :<%= column_name %> # Column name (default: :tags)
24
- normalize true # Convert to lowercase
25
- strip true # Remove whitespace (default)
26
- min_length 2 # Minimum tag length
27
- max_length 30 # Maximum tag length
28
- validates_tags minimum: 1, maximum: 10
29
- end
30
- end
31
-
32
- 3. Usage examples:
33
-
34
- # Add tags
35
- product.tag_with("ruby", "rails", "web")
36
-
37
- # Remove tags
38
- product.untag("web")
39
-
40
- # Replace all tags
41
- product.retag("ruby", "api")
42
-
43
- # Check for tag
44
- product.tagged_with?("ruby") # => true
45
-
46
- # CSV interface
47
- product.tag_list = "ruby, rails, tutorial"
48
- product.tag_list # => "ruby, rails, tutorial"
49
-
50
- # Search with tags (Predicable integration)
51
- <%= model_name %>.<%= column_name %>_contains("ruby")
52
- <%= model_name %>.<%= column_name %>_overlaps(["ruby", "python"])
53
- <%= model_name %>.<%= column_name %>_contains_all(["ruby", "rails"])
54
-
55
- # Statistics
56
- <%= model_name %>.tag_counts # => {"ruby" => 45, "rails" => 38}
57
- <%= model_name %>.popular_tags(limit: 10) # => [["ruby", 45], ["rails", 38]]
58
- <%= model_name %>.related_tags("ruby", limit: 5) # => ["rails", "gem", "tutorial"]
59
-
60
- For more information, see: docs/taggable.md
61
-
62
- ===============================================================================
@@ -1,21 +0,0 @@
1
- class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
- def change
3
- change_table :<%= table_name %> do |t|
4
- # Tags column - database-specific implementation
5
- if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
6
- # PostgreSQL: Use native array with default empty array
7
- t.string :<%= column_name %>, array: true, default: []
8
- else
9
- # SQLite/MySQL: Use text column (requires serialization in model)
10
- t.text :<%= column_name %>
11
- end
12
- end
13
- <% if add_index? -%>
14
-
15
- # Add index for PostgreSQL array searches (GIN index for better performance)
16
- if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
17
- add_index :<%= table_name %>, :<%= column_name %>, using: 'gin'
18
- end
19
- <% end -%>
20
- end
21
- end