Skip to content

Commit

Permalink
Merge pull request #7347 from vishalzambre/tagging
Browse files Browse the repository at this point in the history
Adds Tagging module
  • Loading branch information
damianlegawiec committed May 21, 2016
2 parents 733e1af + dcae29b commit 1c9b5a6
Show file tree
Hide file tree
Showing 19 changed files with 192 additions and 0 deletions.
2 changes: 2 additions & 0 deletions backend/app/assets/javascripts/spree/backend.js
Expand Up @@ -44,6 +44,7 @@
//= require spree/backend/taxonomy
//= require spree/backend/taxons
//= require spree/backend/user_picker
//= require spree/backend/tag_picker
//= require spree/backend/variant_autocomplete
//= require spree/backend/variant_management
//= require spree/backend/zone
Expand All @@ -62,6 +63,7 @@ Spree.routes.stock_locations_api = Spree.pathFor('api/v1/stock_locations')
Spree.routes.taxon_products_api = Spree.pathFor('api/v1/taxons/products')
Spree.routes.taxons_search = Spree.pathFor('api/v1/taxons')
Spree.routes.user_search = Spree.adminPathFor('search/users')
Spree.routes.tags_search = Spree.adminPathFor('search/tags')
Spree.routes.variants_api = Spree.pathFor('api/v1/variants')

Spree.routes.edit_product = function(product_id) {
Expand Down
51 changes: 51 additions & 0 deletions backend/app/assets/javascripts/spree/backend/tag_picker.js
@@ -0,0 +1,51 @@
$.fn.tagAutocomplete = function () {
'use strict';

function formatTag(tag) {
return Select2.util.escapeMarkup(tag.name);
}

this.select2({
placeholder: Spree.translations.tags_placeholder,
minimumInputLength: 1,
tokenSeparators: [','],
multiple: true,
tags: true,
initSelection: function (element, callback) {
var data = $(element.val().split(',')).map(function() {
return { name: this, id: this };
});
callback(data);
},
ajax: {
url: Spree.routes.tags_search,
datatype: 'json',
data: function (term) {
return {
q: term,
token: Spree.api_key
};
},
results: function (data) {
return {
results: data.tags.map(function(tag) {
return { name: tag.name, id: tag.name };
})
};
}
},
createSearchChoice: function(term, data) {
if ($(data).filter(function() {
return this.name.localeCompare(term)===0;
}).length===0) {
return { id: term, name: term };
}
},
formatResult: formatTag,
formatSelection: formatTag
});
};

$(document).ready(function () {
$('.tag_picker').tagAutocomplete();
});
9 changes: 9 additions & 0 deletions backend/app/controllers/spree/admin/search_controller.rb
Expand Up @@ -35,6 +35,15 @@ def products
expires_in 15.minutes, public: true
headers['Surrogate-Control'] = "max-age=#{15.minutes}"
end

def tags
@tags =
if params[:ids]
Tag.where(id: params[:ids].split(",").flatten)
else
Tag.ransack(params[:q]).result
end
end
end
end
end
Expand Down
6 changes: 6 additions & 0 deletions backend/app/views/spree/admin/products/_form.html.erb
Expand Up @@ -195,6 +195,12 @@
<% end %>
</div>

<div data-hook="admin_product_form_tag_list">
<%= f.field_container :tag_list, class: ['form-group'] do %>
<%= f.label :tag_list, Spree.t(:tags) %>
<%= f.hidden_field :tag_list, value: @product.tag_list.join(','), class: 'tag_picker' %>
<% end %>
</div>

<div data-hook="admin_product_form_meta">
<div data-hook="admin_product_form_meta_title">
Expand Down
2 changes: 2 additions & 0 deletions backend/app/views/spree/admin/search/tags.rabl
@@ -0,0 +1,2 @@
collection(@tags => :tags)
attributes :name, :id
Expand Up @@ -35,6 +35,7 @@
:sku => Spree.t(:sku),
:type_to_search => Spree.t(:type_to_search),
:taxon_placeholder => Spree.t(:taxon_placeholder),
:tags_placeholder => Spree.t(:tags_placeholder),
:variant_placeholder => Spree.t(:variant_placeholder),
:value => Spree.t(:value),
:currency_separator => I18n.t('number.currency.format.separator'),
Expand Down
1 change: 1 addition & 0 deletions backend/config/routes.rb
Expand Up @@ -2,6 +2,7 @@
namespace :admin, path: Spree.admin_path do
get '/search/users', to: "search#users", as: :search_users
get '/search/products', to: "search#products", as: :search_products
get "/search/tags", to: "search#tags", as: :search_tags

resources :promotions do
resources :promotion_rules
Expand Down
Expand Up @@ -53,4 +53,12 @@
end
end

describe "tags" do
let(:tag) { create(:tag, name: "Awesome Product") }

it "can find a tag by its name" do
spree_xhr_get :tags, q: tag.name
expect(assigns[:tags]).to include(tag)
end
end
end
11 changes: 11 additions & 0 deletions core/app/models/concerns/spree/acts_as_taggable.rb
@@ -0,0 +1,11 @@
module Spree
module ActsAsTaggable
extend ActiveSupport::Concern

included do
acts_as_taggable
Spree::PermittedAttributes.send("#{model_name.param_key}_attributes") <<
[:tag_list]
end
end
end
1 change: 1 addition & 0 deletions core/app/models/spree/product.rb
Expand Up @@ -21,6 +21,7 @@
module Spree
class Product < Spree::Base
extend FriendlyId
include ActsAsTaggable
friendly_id :slug_candidates, use: :history

acts_as_paranoid
Expand Down
4 changes: 4 additions & 0 deletions core/app/models/spree/tag.rb
@@ -0,0 +1,4 @@
module Spree
class Tag < ActsAsTaggableOn::Tag
end
end
12 changes: 12 additions & 0 deletions core/config/initializers/acts_as_taggable_on.rb
@@ -0,0 +1,12 @@
require "acts-as-taggable-on"
if ActsAsTaggableOn::Utils.using_mysql?
ActsAsTaggableOn.force_binary_collation = true
end

ActsAsTaggableOn::Tag.class_eval do
self.table_name_prefix = "spree_"
end

ActsAsTaggableOn::Tagging.class_eval do
self.table_name_prefix = "spree_"
end
1 change: 1 addition & 0 deletions core/config/locales/en.yml
Expand Up @@ -1393,6 +1393,7 @@ en:
taxon: Taxon
taxon_edit: Edit Taxon
taxon_placeholder: Add a Taxon
tags_placeholder: Add Tags
taxon_rule:
choose_taxons: Choose taxons
label: Order must contain x amount of these taxons
Expand Down
40 changes: 40 additions & 0 deletions core/db/migrate/20160511071954_acts_as_taggable_on_migration.rb
@@ -0,0 +1,40 @@
class ActsAsTaggableOnMigration < ActiveRecord::Migration
def self.up
create_table :spree_tags do |t|
t.string :name
t.integer :taggings_count, default: 0
end

create_table :spree_taggings do |t|
t.references :tag

# You should make sure that the column created is
# long enough to store the required class names.
t.references :taggable, polymorphic: true
t.references :tagger, polymorphic: true

# Limit is created to prevent MySQL error on index
# length for MyISAM table type: http://bit.ly/vgW2Ql
t.string :context, limit: 128

t.datetime :created_at
end

add_index :spree_tags, :name, unique: true
add_index :spree_taggings,
[
:tag_id,
:taggable_id,
:taggable_type,
:context,
:tagger_id,
:tagger_type
],
unique: true, name: "spree_taggings_idx"
end

def self.down
drop_table :spree_taggings
drop_table :spree_tags
end
end
@@ -0,0 +1,9 @@
# This migration is added to circumvent issue #623 and have special characters
# work properly
class ChangeCollationForTagNames < ActiveRecord::Migration
def up
if ActsAsTaggableOn::Utils.using_mysql?
execute("ALTER TABLE spree_tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;")
end
end
end
14 changes: 14 additions & 0 deletions core/db/migrate/20160511072335_add_missing_indexes.rb
@@ -0,0 +1,14 @@
class AddMissingIndexes < ActiveRecord::Migration
def change
add_index :spree_taggings, :tag_id
add_index :spree_taggings, :taggable_id
add_index :spree_taggings, :taggable_type
add_index :spree_taggings, :tagger_id
add_index :spree_taggings, :context

add_index :spree_taggings, [:tagger_id, :tagger_type]
add_index :spree_taggings,
[:taggable_id, :taggable_type, :tagger_id, :context],
name: "spree_taggings_idy"
end
end
5 changes: 5 additions & 0 deletions core/lib/spree/testing_support/factories/tag_factory.rb
@@ -0,0 +1,5 @@
FactoryGirl.define do
factory :tag, class: Spree::Tag do
name "awesome"
end
end
14 changes: 14 additions & 0 deletions core/spec/models/spree/product_spec.rb
Expand Up @@ -548,4 +548,18 @@ def build_option_type_with_values(name, values)
expect(product_discontinued.discontinued?).to be(true)
end
end

context "acts_as_taggable" do
let(:product) { create(:product) }

it "should add tags" do
product.tag_list.add("awesome")
expect(product.tag_list).to include("awesome")
end

it "should remove tags" do
product.tag_list.remove("awesome")
expect(product.tag_list).to_not include("awesome")
end
end
end
1 change: 1 addition & 0 deletions core/spree_core.gemspec
Expand Up @@ -34,6 +34,7 @@ Gem::Specification.new do |s|
s.add_dependency 'paperclip', '~> 4.3.0'
s.add_dependency 'paranoia', '~> 2.1.0'
s.add_dependency 'premailer-rails'
s.add_dependency 'acts-as-taggable-on', '~> 3.4'
s.add_dependency 'rails', '~> 4.2.6'
s.add_dependency 'ransack', '~> 1.7.0'
s.add_dependency 'responders'
Expand Down

0 comments on commit 1c9b5a6

Please sign in to comment.