Article
Rails3アプリケーションのモデルに「タグ」を追加しようとしています。
モデルに「タグ付け」機能とビューのオートコンプリートヘルパーの両方を追加したgemまたはプラグインがあるかどうか疑問に思います。
私は見つけましacts_as_taggable
たが、それが私が使用すべきものであるかどうかはわかりません。新しいものはありますか?私がacts_as_taggableをグーグルで検索した2007年から結果を得ています
Article
Rails3アプリケーションのモデルに「タグ」を追加しようとしています。
モデルに「タグ付け」機能とビューのオートコンプリートヘルパーの両方を追加したgemまたはプラグインがあるかどうか疑問に思います。
私は見つけましacts_as_taggable
たが、それが私が使用すべきものであるかどうかはわかりません。新しいものはありますか?私がacts_as_taggableをグーグルで検索した2007年から結果を得ています
Acts_as_taggable_onとrails3-jquery-autocompleteはうまく連携して、SOのようなタグ付けシステムを作成します。以下の例を参照してください。レールに適したオールインワンオプションはまだ存在しないと思います。
これをすべてインストールするには、次の手順に従います。
1。Railsアプリをバックアップしてください!
2。jquery-railsをインストールします
注:jQuery UIはでインストールできますが、インストールしjquery-rails
ないことを選択しました。
3。jQueryUIをダウンロードしてインストールします
Webデザインを補完するテーマを選択してください(オートコンプリートデモを選択したテーマでテストしてください。デフォルトのテーマは機能しませんでした)。カスタムzipをダウンロードし、[zipfile]/js/jquery-ui-#.#.#.custom.min.js
ファイルをアプリの/public/javascripts/
フォルダーに配置します。[zipfile]/css/custom-theme/
フォルダとすべてのファイルをアプリのフォルダに配置しpublic/stylesheets/custom-theme/
ます。
4。以下をGemfileに追加してから、「バンドルインストール」を実行します
gem'acts-as-taggable-on'
gem'rails3-jquery-autocomplete'
5。コンソールから次のコマンドを実行します。
rails generateacts_as_taggable_on:migration
rake db:migrate
rails generate autocomplete:install
アプリでこれらの変更を行います
アプリケーションのレイアウトに必要なjavascriptファイルとcssファイルを含めます。
<%= stylesheet_link_tag "application", "custom-theme/jquery-ui-1.8.9.custom" %>
<%= javascript_include_tag :defaults, "jquery-ui-#.#.#.custom.min", "autocomplete-rails" %>
コントローラの例
編集:SethPellegrinoのコメントに基づいて変更を加えました。
class ArticlesController < Admin::BaseController
#autocomplete :tag, :name <- Old
autocomplete :tag, :name, :class_name => 'ActsAsTaggableOn::Tag' # <- New
end
モデル例
class Article < ActiveRecord::Base
acts_as_taggable_on :tags
end
Route.rb
resources :articles do
get :autocomplete_tag_name, :on => :collection
end
例を見る
<%= form_for(@article) do |f| %>
<%= f.autocomplete_field :tag_list, autocomplete_tag_name_articles_path, :"data-delimiter" => ', ' %>
# note tag_list above is a virtual column created by acts_as_taggable_on
<% end %>
注:この例では、アプリ全体で1つのモデルのみにタグを付け、デフォルトのタグタイプ:tagsのみを使用していることを前提としています。基本的に、上記のコードはすべてのタグを検索し、それらを「Article」タグに限定しません。
Acts_as_taggable_on_steroidsgemはおそらくあなたの最善の策です。タグ付けの宝石の多くは「開始するのに適した場所」であることがわかりましたが、希望する結果を得るにはかなりの量のカスタマイズが必要です。
最近、これについてブログに投稿しました。簡潔にするために、私のメソッドでは(オプションの)コンテキストフィルター処理されたタグ(たとえば、モデル別およびモデルの属性別)を使用できますが、@ Tim Santefordのソリューションでは、モデルのすべてのタグを取得できます(フィールドでフィルター処理されません)。 。以下は逐語的な投稿です。
Tim Santefordのソリューションを試しましたが、問題はタグの結果にありました。彼のソリューションでは、既存のすべてのタグがオートコンプリートによって返され、モデルやタグ付け可能なフィールドにスコープされません。それで、私は私の意見でははるかに優れた解決策を思いつきました。タグ付けしたいモデルに自動的に拡張可能で、効率的で、何よりも非常にシンプルです。これは、acts-as-taggable-ongemとselect2JavaScriptライブラリを使用します。
gem 'acts-as-taggable-on', '~> 3.5'
bundle install
してインストールしますrake acts_as_taggable_on_engine:install:migrations
rake db:migrate
終わり!
Film
モデルがあるとしましょう(私が持っているからです)。モデルに次の2行を追加するだけです。
class Film < ActiveRecord::Base
acts_as_taggable
acts_as_taggable_on :genres
end
モデルは以上です。今度はコントローラーに移ります。パラメータでタグリストを受け入れる必要があります。だから私は私の中に次のものを持っていますFilmsController
:
class FilmsController < ApplicationController
def index
...
end
...
private
def films_params
params[:film].permit(..., :genre_list)
end
end
パラメータがgenres
モデルで指定したものとは異なることに注意してください。理由は聞かないでください。ただし、タグ付け可能として機能する場合は、単数形の+ _listが必要です。これは、ビューで必要なものです。
ビューレイヤーに!ビューにはSimpleFormgemとSlimテンプレートエンジンを使用しているため、gemを使用しない場合、フォームは実際のフォームとは少し異なる場合があります。ただし、これは通常のテキスト入力フィールドです。
= f.input :genre_list, input_html: {value: @film.genre_list.to_s}
カンマ区切りの文字列としてレンダリングするには、この属性にその値を設定する必要がありinput_html
ます(これは、コントローラーでタグ付け可能として機能するものです)。フォームを送信するときにタグ付けが機能するようになりました。それが機能しない場合は、タグ付けに関する(驚くべき)ライアンベイツのRailscastエピソードを視聴することをお勧めします。
まず、select2ライブラリを含める必要があります。手動で含めるか、(私の好みで)Railsアセットパイプライン用にselect2をパッケージ化するselect2-railsgemを使用できます。
gemをGemfile:に追加してからgem 'select2-rails', '~> 4.0'
、を実行しbundle install
ます。
アセットパイプラインにJavaScriptとCSSを含めます。
application.js//= require select2-full
の場合:。application.css*= require select2
内:。
次に、フォームを少し変更して、select2がタグ付けに期待するものを含める必要があります。これは少し紛らわしいように思えるかもしれませんが、すべてを説明します。以前のフォーム入力を変更します。
= f.input :genre_list, input_html: {value: @film.genre_list.to_s}
に:
= f.hidden_field :genre_list, value: @film.genre_list.to_s
= f.input :genre_list,
input_html: { id: "genre_list_select2",
name: "genre_list_select2",
multiple: true,
data: { taggable: true, taggable_type: "Film", context: "genres" } },
collection: @film.genre_list
コントローラに送信される実際の値として機能する非表示の入力を追加します。Select2は配列を返します。ここで、acts-as-taggable-onは、コンマ区切りの文字列を想定しています。select2フォーム入力は、値が変更されるとその文字列に変換され、非表示フィールドに設定されます。すぐにそれを取得します。
実際の属性id
とname
属性f.input
は重要ではありません。それらはあなたのhidden
入力とオーバーラップすることはできません。ここdata
ではハッシュが非常に重要です。このtaggable
フィールドでは、JavaScriptを使用して、各入力をIDで手動で初期化する代わりに、すべてのselect2入力を一度に初期化できます。このtaggable_type
フィールドは、特定のモデルのタグをフィルタリングするために使用され、このcontext
フィールドは、そのフィールドで以前に使用されたタグをフィルタリングするために使用されます。最後に、collection
フィールドは入力に値を適切に設定するだけです。
次の部分はJavaScriptです。アプリケーション全体ですべてのselect2要素を初期化する必要があります。これを行うには、次の関数をapplication.js
ファイルに追加するだけで、すべてのルートで機能するようになります。
// Initialize all acts-as-taggable-on + select2 tag inputs
$("*[data-taggable='true']").each(function() {
console.log("Taggable: " + $(this).attr('id') + "; initializing select2");
$(this).select2({
tags: true,
theme: "bootstrap",
width: "100%",
tokenSeparators: [','],
minimumInputLength: 2,
ajax: {
url: "/tags",
dataType: 'json',
delay: 100,
data: function (params) {
console.log("Using AJAX to get tags...");
console.log("Tag name: " + params.term);
console.log("Existing tags: " + $(this).val());
console.log("Taggable type: " + $(this).data("taggable-type"));
console.log("Tag context: " + $(this).data("context"));
return {
name: params.term,
tags_chosen: $(this).val(),
taggable_type: $(this).data("taggable-type"),
context: $(this).data("context"),
page: params.page
}
},
processResults: function (data, params) {
console.log("Got tags from AJAX: " + JSON.stringify(data, null, '\t'));
params.page = params.page || 1;
return {
results: $.map(data, function (item) {
return {
text: item.name,
// id has to be the tag name, because acts_as_taggable expects it!
id: item.name
}
})
};
},
cache: true
}
});
});
これは複雑に見えるかもしれませんが、それほど難しくはありません。基本的に、セレクターは、データ$("*[data-taggable='true']")
に設定したすべてのHTML要素を取得するだけです。これをフォームに追加したところです。これが理由です。タグ付け可能なすべてのフィールドに対してselect2taggable: true
を初期化できるようにする必要があります。
残りはAJAX関連のコードです。/tags
基本的に、パラメータとを使用してname
AJAX呼び出しをtaggable_type
行いますcontext
。おなじみですか?これらは、フォーム入力で設定したデータ属性です。結果が返されるとき、select2にタグの名前を付けるだけです。
今、あなたはおそらく考えているでしょう:私には/tags
ルートがありません!。あなたが正しい!しかし、あなたはもうすぐです:)
ファイルに移動しroutes.rb
、以下を追加しますresources :tags
。タグのすべてのルートを追加する必要はありませんが、タグをCRUDする簡単な方法を用意するために追加しました。簡単に行うこともできます。get '/tags' => 'tags#index'
現時点で必要なルートはこれだけです。ルートができたので、次のコントローラーを作成する必要がありますTagsController
。
class TagsController < ApplicationController
def index
@tags = ActsAsTaggableOn::Tag
.where("name ILIKE ?", "%#{params[:name]}%")
.where.not(name: params[:tags_chosen])
.includes(:taggings)
.where(taggings: {taggable_type: params[:taggable_type]})
@tags = @tags.where(taggings: {context: params[:context] }) if params[:context]
@tags.order!(name: :asc)
render json: @tags
end
end
これはかなり簡単です。/tags
パラメータname
(タグテキスト)、tags_chosen
(既存の選択されたタグ)、taggable_type
(タグ付けされたモデル)、およびオプションcontext
(タグ付けされたフィールド)を使用して、にリクエストを送信できます。「comedy」と「conspiracy」のジャンルタグがある場合、フォームにcoと入力すると、レンダリングされるJSONは次のようになります。
[
{
"id": 12,
"name": "comedy",
"taggings_count": 1
},
{
"id": 11,
"name": "conspiracy",
"taggings_count": 1
}
]
select2入力では、自動入力されたタグオプションとして「コメディ」と「陰謀」が表示されます。
最後のステップが1つあります。hidden
以前に作成したフィールドにselect2値を設定する必要があります。
このコードは、フォームの構造によって異なる場合がありますが、基本的にはselect2入力を取得し、文字列の配列をCSV文字列に変換して(例:["comedy", "conspiracy"]
-> "comedy, conspiracy"
)、そのCSV文字列を非表示フィールドに設定する必要があります。 。幸いなことに、それはそれほど難しいことではありません。
select2入力変更イベント、またはその他の適切なイベントをキャッチできます。これはあなたの選択ですが、Railsコントローラーが値を正しく受け取るようにするには、この手順を実行する必要があります。繰り返しますが、application.jsでは:
/*
* When any taggable input changes, get the value from the select2 input and
* convert it to a comma-separated string. Assign this value to the nearest hidden
* input, which is the input for the acts-on-taggable field. Select2 submits an array,
* but acts-as-taggable-on expects a CSV string; it is why this conversion exists.
*/
$(document).on('select2:select select2:unselect', "*[data-taggable='true']", function() {
var taggable_id = $(this).attr('id')
// genre_list_select2 --> genre_list
var hidden_id = taggable_id.replace("_select2", "");
// film_*genre_list* ($= jQuery selectors ends with)
var hidden = $("[id$=" + hidden_id + "]")
// Select2 either has elements selected or it doesn't, in which case use []
var joined = ($(this).val() || []).join(",");
hidden.val(joined);
});
値を正常に変換すると、コントローラーのアクションに次のように表示されます。"genre_list"=>"comedy,conspiracy"
そして、acts-as-taggable-onとselect2を使用してRailsでオートコンプリートタグを実行するために必要なのはこれだけです。