Skip to content

Commit

Permalink
Merge pull request #1364 from tvdeyen/migrate-to-gutentag
Browse files Browse the repository at this point in the history
Use Gutentag for tags
  • Loading branch information
tvdeyen authored Feb 28, 2018
2 parents 977df8a + daa312f commit c38690a
Show file tree
Hide file tree
Showing 32 changed files with 245 additions and 86 deletions.
2 changes: 1 addition & 1 deletion alchemy_cms.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ Gem::Specification.new do |gem|

gem.add_runtime_dependency 'active_model_serializers', ['~> 0.9.0']
gem.add_runtime_dependency 'acts_as_list', ['~> 0.3']
gem.add_runtime_dependency 'acts-as-taggable-on', ['~> 5.0']
gem.add_runtime_dependency 'awesome_nested_set', ['~> 3.1']
gem.add_runtime_dependency 'cancancan', ['~> 2.1']
gem.add_runtime_dependency 'coffee-rails', ['~> 4.0']
gem.add_runtime_dependency 'dragonfly', ['~> 1.0', '>= 1.0.7']
gem.add_runtime_dependency 'dragonfly_svg', ['~> 0.0.4']
gem.add_runtime_dependency 'gutentag', ['~> 2.1']
gem.add_runtime_dependency 'handlebars_assets', ['~> 0.23']
gem.add_runtime_dependency 'jquery-rails', ['~> 4.0']
gem.add_runtime_dependency 'jquery-ui-rails', ['~> 5.0.0']
Expand Down
14 changes: 7 additions & 7 deletions app/controllers/alchemy/admin/tags_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class TagsController < ResourcesController
before_action :load_tag, only: [:edit, :update, :destroy]

def index
@query = ActsAsTaggableOn::Tag.ransack(params[:q])
@query = Gutentag::Tag.ransack(params[:q])
@tags = @query
.result
.page(params[:page] || 1)
Expand All @@ -15,21 +15,21 @@ def index
end

def new
@tag = ActsAsTaggableOn::Tag.new
@tag = Gutentag::Tag.new
end

def create
@tag = ActsAsTaggableOn::Tag.create(tag_params)
@tag = Gutentag::Tag.create(tag_params)
render_errors_or_redirect @tag, admin_tags_path, Alchemy.t('New Tag Created')
end

def edit
@tags = ActsAsTaggableOn::Tag.order("name ASC").to_a - [@tag]
@tags = Gutentag::Tag.order("name ASC").to_a - [@tag]
end

def update
if tag_params[:merge_to]
@new_tag = ActsAsTaggableOn::Tag.find(tag_params[:merge_to])
@new_tag = Gutentag::Tag.find(tag_params[:merge_to])
Tag.replace(@tag, @new_tag)
operation_text = Alchemy.t('Replaced Tag') % {old_tag: @tag.name, new_tag: @new_tag.name}
@tag.destroy
Expand Down Expand Up @@ -57,7 +57,7 @@ def autocomplete
private

def load_tag
@tag = ActsAsTaggableOn::Tag.find(params[:id])
@tag = Gutentag::Tag.find(params[:id])
end

def tag_params
Expand All @@ -66,7 +66,7 @@ def tag_params

def tags_from_term(term)
return [] if term.blank?
ActsAsTaggableOn::Tag.where(['LOWER(name) LIKE ?', "#{term.downcase}%"])
Gutentag::Tag.where(['LOWER(name) LIKE ?', "#{term.downcase}%"])
end

def json_for_autocomplete(items, attribute)
Expand Down
4 changes: 2 additions & 2 deletions app/helpers/alchemy/admin/tags_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def render_tag_list(class_name)
sorted_tags_from(class_name: class_name).map do |tag|
content_tag('li', name: tag.name, class: filtered_by_tag?(tag) ? 'active' : nil) do
link_to(
"#{tag.name} (#{tag.count})",
"#{tag.name} (#{tag.taggings_count})",
url_for(
search_filter_params.except(:page, :tagged_with).merge(
tagged_with: tags_for_filter(current: tag).presence
Expand All @@ -36,7 +36,7 @@ def filtered_by_tag?(tag)

# Returns the tags from params suitable for the tags filter.
#
# @param current [ActsAsTaggableOn::Tag] - The current tag that will be added or removed if already present
# @param current [Gutentag::Tag] - The current tag that will be added or removed if already present
# @returns [String]
def tags_for_filter(current:)
if filtered_by_tag?(current)
Expand Down
3 changes: 1 addition & 2 deletions app/models/alchemy/attachment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ module Alchemy
class Attachment < BaseRecord
include Alchemy::Filetypes
include Alchemy::NameConversions
include Alchemy::Taggable
include Alchemy::Touching

acts_as_taggable

dragonfly_accessor :file, app: :alchemy_attachments do
after_assign { |f| write_attribute(:file_mime_type, f.mime_type) }
end
Expand Down
3 changes: 1 addition & 2 deletions app/models/alchemy/element.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
module Alchemy
class Element < BaseRecord
include Alchemy::Logger
include Alchemy::Taggable
include Alchemy::Touching
include Alchemy::Hints

Expand All @@ -46,8 +47,6 @@ class Element < BaseRecord
"updater_id"
].freeze

acts_as_taggable

# All Elements that share the same page id, cell id and parent element id are considered a list.
#
# If cell id and parent element id are nil (typical case for a simple page),
Expand Down
2 changes: 1 addition & 1 deletion app/models/alchemy/page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ module Alchemy
class Page < BaseRecord
include Alchemy::Hints
include Alchemy::Logger
include Alchemy::Taggable
include Alchemy::Touching

DEFAULT_ATTRIBUTES_FOR_COPY = {
Expand Down Expand Up @@ -82,7 +83,6 @@ class Page < BaseRecord
:layoutpage
]

acts_as_taggable
acts_as_nested_set(dependent: :destroy)

stampable stamper_class_name: Alchemy.user_class_name
Expand Down
5 changes: 2 additions & 3 deletions app/models/alchemy/picture.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Picture < BaseRecord
CONVERTIBLE_FILE_FORMATS = %w(gif jpg jpeg png).freeze

include Alchemy::NameConversions
include Alchemy::Taggable
include Alchemy::Touching
include Alchemy::Picture::Transformations
include Alchemy::Picture::Url
Expand Down Expand Up @@ -69,8 +70,6 @@ def allowed_filetypes
case_sensitive: false,
message: Alchemy.t("not a valid image")

acts_as_taggable

stampable stamper_class_name: Alchemy.user_class_name

scope :named, ->(name) {
Expand All @@ -86,7 +85,7 @@ def allowed_filetypes
}

scope :without_tag, -> {
where("#{table_name}.cached_tag_list IS NULL OR #{table_name}.cached_tag_list = ''")
left_outer_joins(:taggings).where(gutentag_taggings: {id: nil})
}

after_update :touch_contents
Expand Down
6 changes: 3 additions & 3 deletions app/models/alchemy/tag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

# == Schema Information
#
# Table name: tags
# Table name: gutentag_tags
#
# id :integer not null, primary key
# name :string
# taggings_count :integer default(0)
#

# Just holds some useful tag methods.
# The original Tag model is ActsAsTaggableOn::Tag
# The original Tag model is Gutentag::Tag
module Alchemy
class Tag < ActsAsTaggableOn::Tag
class Tag < Gutentag::Tag
# Replaces tag with new tag on all models tagged with tag.
def self.replace(tag, new_tag)
tag.taggings.collect(&:taggable).each do |taggable|
Expand Down
4 changes: 2 additions & 2 deletions app/views/alchemy/admin/tags/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<div id="archive_all" class="resources-table-wrapper">
<h1 class="resources-header">
<%= @tags.total_count %>
<%= ActsAsTaggableOn::Tag.model_name.human(count: @tags.total_count) %>
<%= Gutentag::Tag.model_name.human(count: @tags.total_count) %>
</h1>
<% if @tags.any? %>

Expand All @@ -27,7 +27,7 @@
<tr>
<th class="icon"></th>
<th class="name"><%= sort_link(@query, :name, hide_indicator: true) %></th>
<th class="count"><%= ActsAsTaggableOn::Tag.human_attribute_name(:taggings_types) %></th>
<th class="count"><%= Gutentag::Tag.human_attribute_name(:taggings_types) %></th>
<th class="count"><%= sort_link(@query, :taggings_count, hide_indicator: true) %></th>
<th class="tools"></th>
</tr>
Expand Down
4 changes: 2 additions & 2 deletions config/locales/alchemy.de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ de:
activerecord:

models:
acts_as_taggable_on/tag:
gutentag/tag:
one: Tag
other: Tags

Expand Down Expand Up @@ -832,7 +832,7 @@ de:

attributes:

acts_as_taggable_on/tag:
gutentag/tag:
taggings_types: Verwendet an
taggings_count: Anzahl Verwendung

Expand Down
4 changes: 2 additions & 2 deletions config/locales/alchemy.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ en:
activerecord:

models:
acts_as_taggable_on/tag:
gutentag/tag:
one: Tag
other: Tags

Expand Down Expand Up @@ -810,7 +810,7 @@ en:

attributes:

acts_as_taggable_on/tag:
gutentag/tag:
taggings_types: Used for
taggings_count: Usage count

Expand Down
4 changes: 2 additions & 2 deletions config/locales/alchemy.es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ es:
activerecord:

models:
acts_as_taggable_on/tag:
gutentag/tag:
one: Etiqueta
other: Etiquetas

Expand Down Expand Up @@ -861,7 +861,7 @@ es:

attributes:

acts_as_taggable_on/tag:
gutentag/tag:
taggings_types: Usado por
taggings_count: Contador de uso
name: Nombre
Expand Down
4 changes: 2 additions & 2 deletions config/locales/alchemy.fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ fr:
activerecord:

models:
acts_as_taggable_on/tag:
gutentag/tag:
one: Tag
other: Tags

Expand Down Expand Up @@ -845,7 +845,7 @@ fr:

attributes:

acts_as_taggable_on/tag:
gutentag/tag:
taggings_types: Posté le
taggings_count: Nombres d´utilisations

Expand Down
4 changes: 2 additions & 2 deletions config/locales/alchemy.it.yml
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ it:
activerecord:

models:
acts_as_taggable_on/tag:
gutentag/tag:
one: Tag
other: Tag

Expand Down Expand Up @@ -841,7 +841,7 @@ it:

attributes:

acts_as_taggable_on/tag:
gutentag/tag:
taggings_types: Usato per
taggings_count: Numero utilizzi

Expand Down
4 changes: 2 additions & 2 deletions config/locales/alchemy.nl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,7 @@ nl:
activerecord:

models:
acts_as_taggable_on/tag:
gutentag/tag:
one: Tag
other: Tags

Expand Down Expand Up @@ -822,7 +822,7 @@ nl:

attributes:

acts_as_taggable_on/tag:
gutentag/tag:
taggings_types: Gebruikt voor
taggings_count: Aantal in gebruik

Expand Down
4 changes: 2 additions & 2 deletions config/locales/alchemy.ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ ru:
activerecord:

models:
acts_as_taggable_on/tag:
gutentag/tag:
one: "Метка"
few: "Метки"
many: "Меток"
Expand Down Expand Up @@ -733,7 +733,7 @@ ru:

attributes:

acts_as_taggable_on/tag:
gutentag/tag:
name: "Название"
taggings_types: Используется для
taggings_count: Количество использований
Expand Down
37 changes: 37 additions & 0 deletions db/migrate/20180227224537_migrate_tags_to_gutentag.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
class MigrateTagsToGutentag < ActiveRecord::Migration[5.0]
def change
remove_index :taggings, :taggable_id
remove_column :taggings, :tagger_id, :integer
remove_index :taggings, :taggable_type
remove_column :taggings, :tagger_type, :string
remove_index :taggings, column: [:taggable_id, :taggable_type, :context], name: 'index_taggings_on_taggable_id_and_taggable_type_and_context'
remove_column :taggings, :context, :string, limit: 128
if index_exists? :taggings, [:tag_id, :taggable_id, :taggable_type], unique: true, name: 'taggings_idx'
rename_index :taggings, 'taggings_idx', 'unique_taggings'

This comment has been minimized.

Copy link
@radixhound

radixhound Mar 1, 2018

This is breaking for me on a brand new app. I got it all installed and working a couple days ago but today I can't do it. This migration breaks.

SQLite3::SQLException: index unique_taggings already exists: CREATE UNIQUE INDEX "unique_taggings" ON "taggings" ("tag_id", "taggable_id", "taggable_type")
else
add_index :taggings, [:taggable_type, :taggable_id, :tag_id], unique: true, name: 'unique_taggings'
end
if index_exists? :taggings, [:taggable_id, :taggable_type], name: 'taggings_idy'
rename_index :taggings, 'taggings_idy', 'index_gutentag_taggings_on_taggable_id_and_taggable_type'
else
add_index :taggings, [:taggable_type, :taggable_id]
end
add_column :taggings, :updated_at, :datetime
change_column_null :taggings, :tag_id, false
change_column_null :taggings, :taggable_id, false
change_column_null :taggings, :taggable_type, false
change_column_null :taggings, :created_at, false, Time.current
change_column_null :taggings, :updated_at, false, Time.current
rename_table :taggings, :gutentag_taggings

change_column_null :tags, :name, false
add_index :tags, :taggings_count
rename_table :tags, :gutentag_tags

%i(alchemy_attachments alchemy_elements alchemy_pages alchemy_pictures).each do |table|
if column_exists? table, :cached_tag_list
remove_column table, :cached_tag_list
end
end
end
end
7 changes: 7 additions & 0 deletions lib/alchemy/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ class Engine < Rails::Engine
NonStupidDigestAssets.whitelist += [/^tinymce\//]
end

# Gutentag downcases all tgas before save.
# We support having tags with uppercase characters.
# The Gutentag search is case insensitive.
initializer 'alchemy.gutentag_normalizer' do
Gutentag.normaliser = ->(value) { value.to_s }
end

# We need to reload each essence class in development mode on every request,
# so it can register itself as essence relation on Page and Element models
#
Expand Down
2 changes: 1 addition & 1 deletion lib/alchemy/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ module Alchemy
# If you don't want to stick with these conventions you can separate model and controller by providing
# a model class (for example used by Alchemy's Tags admin interface):
#
# resource = Resource.new('/admin/tags', {"engine_name"=>"alchemy"}, ActsAsTaggableOn::Tag)
# resource = Resource.new('/admin/tags', {"engine_name"=>"alchemy"}, Gutentag::Tag)
#
class Resource
attr_accessor :resource_relations, :model_associations
Expand Down
Loading

0 comments on commit c38690a

Please sign in to comment.