如何向 Rails 中的现有模型添加自动完成标记?
我正在尝试将“标签”添加到 Rails 3 应用程序中的 Article
模型中。
我想知道是否有一个 gem 或插件在模型中添加了“标记”功能以及视图的自动完成帮助程序。
我找到了 acts_as_taggable
但我不确定这是否是我应该使用的。有更新的东西吗?当我用 google 搜索 acts_as_taggable 时,我得到了 2007 年的结果
I'm trying to add "tags" to an Article
model in a Rails 3 application.
I'm wondering if there is a gem or plugin that has adds both the "tagging" functionality in the model and also the auto-complete helpers for the views.
I've found acts_as_taggable
but I'm not sure if that's what I should be using. Is there something newer? I'm getting results from 2007 when I google acts_as_taggable
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
acts_as_taggable_on 和 rails3-jquery-autocomplete 可以很好地协同工作,以创建类似标记系统的 SO,请参见下面的示例。我认为 Rails 尚不存在合适的多合一选项。
按照以下步骤完成全部安装:
1 .备份您的 Rails 应用程序!
2.安装 jquery-rails
注意:您可以使用
jquery-rails
但我选择不这样做。3.下载并安装 jQuery UI
选择一个与您的网页设计相得益彰的主题(请务必使用该主题测试自动完成演示你选择,默认主题不适合我)。下载自定义 zip 并将
[zipfile]/js/jquery-ui-#.#.#.custom.min.js
文件放入应用的/public/javascripts/
文件夹。将[zipfile]/css/custom-theme/
文件夹和所有文件放入应用的public/stylesheets/custom-theme/
文件夹中。4.将以下内容添加到您的 Gemfile 中,然后运行“bundle install”
5 。从控制台运行以下命令:
在您的应用程序中进行这些更改
在应用程序布局中包含必要的javascript和css文件:
控制器示例
编辑:根据Seth Pellegrino的进行更改评论。
模型示例
Route.rb
查看示例
注意:此示例假设您仅在整个应用程序中标记一个模型,并且您仅使用默认标签类型:tags。基本上,上面的代码将搜索所有标签,而不是将它们限制为“文章”标签。
acts_as_taggable_on and rails3-jquery-autocomplete work nicely together to make a SO like tagging system see example below. I don't think a suitable all in one option exists yet for rails.
Follow these steps to get this all installed:
1 . Backup your rails app!
2 . Install jquery-rails
Note: You can install jQuery UI with
jquery-rails
but I chose not to.3 . Download and install jQuery UI
Choose a theme that will compliment your web design (be sure to test the autocomplete demo with the theme you choose, the default theme did not work for me). Download the custom zip and place the
[zipfile]/js/jquery-ui-#.#.#.custom.min.js
file into your app's/public/javascripts/
folder. place the[zipfile]/css/custom-theme/
folder and all files into your app'spublic/stylesheets/custom-theme/
folder.4 . Add the following to your Gemfile and then run "bundle install"
5 . From the console run the following commands:
Make these changes in your app
Include the necessary javascript and css files in your application layout:
Controller Example
EDIT: Made changes based on Seth Pellegrino's comments.
Model Example
Route.rb
View Example
Note: This example assumes that you are only tagging one model in your entire app and you are only using the default tag type :tags. Basically the code above will search all tags and not limit them to "Article" tags.
acts_as_taggable_on_steroids 宝石可能是您最好的选择。我发现许多标记宝石更像是一个“良好的起点”,但随后需要大量的自定义才能获得您想要的结果。
The acts_as_taggable_on_steroids gem is probably your best bet. I've found that many of the tagging gems are more of a "good place to start" but then require a fair amount of customization to get the result you want.
我最近写了一篇关于此的博客文章;为了简洁起见,我的方法允许您拥有(可选)上下文过滤的标签(例如按模型和模型上的属性),而@Tim Santeford的解决方案将为您提供所有标签模型(未按字段过滤)。以下是逐字帖。
我尝试了 Tim Santeford 的解决方案,但问题出在标签结果上。在他的解决方案中,您将获得通过自动完成返回的所有现有标签,并且范围不限于您的模型和可标记字段!因此,我想出了一个在我看来更好的解决方案;它可以自动扩展到您想要标记的任何模型,它非常高效,而且最重要的是它非常简单。它使用 acts-as-taggable-on gem 和 select2 JavaScript 库。
安装 Acts-As-Taggable-On gem
gem 'acts-as-taggable-on', '~>; 3.5'
bundle install
来安装它rakeacts_as_taggable_on_engine:install:migrations
rake db:migrate
运行迁移代码>完成!
在 MVC 中设置正常标记
假设我们有一个
Film
模型(因为我有)。只需将以下两行添加到您的模型中:模型就这样了。现在到控制器上。您需要接受参数中的标签列表。因此,我的
FilmsController
中有以下内容:请注意,该参数不是我们在模型中指定的
genres
。不要问我为什么,但acts-as-taggable-on需要singular + _list,而这正是视图中所需要的。进入视图层!我使用 SimpleForm gem 和 Slim 视图模板引擎,因此如果您不使用 gem,我的表单可能看起来与您的表单略有不同。但是,它只是一个普通的文本输入字段:
您需要设置了该值的
input_html
属性,以便将其呈现为逗号分隔的字符串(这就是作用- as-taggable-on 期望在控制器中)。现在,当您提交表单时,标记应该可以使用!如果它不起作用,我建议观看(令人惊叹的)Ryan Bates 的 Railscast 关于标记的剧集。将 select2 集成到您的表单中
首先,我们需要包含 select2 库;您可以手动包含它,或者使用(我的偏好)打包的 select2-rails gem select2 作为 Rails 资产管道。
将 gem 添加到 Gemfile 中:
gem 'select2-rails', '~>; 4.0'
,然后运行bundle install
。在您的资源管道中包含 JavaScript 和 CSS:
在 application.js 中:
//= require select2-full
。在application.css中:*= require select2
。现在您需要稍微修改一下表单以包含 select2 期望的标记内容。这看起来有点令人困惑,但我会解释一切。将之前的表单输入更改
为:
我们添加一个隐藏输入,它将充当发送到控制器的实际值。 Select2 返回一个数组,其中acts-as-taggable-on 需要一个逗号分隔的字符串。当其值发生变化时,select2 表单输入将转换为该字符串,并设置到隐藏字段中。我们很快就会谈到这一点。
f.input
的id
和name
属性实际上并不重要。它们只是不能与您的隐藏
输入重叠。data
哈希在这里非常重要。taggable
字段允许我们使用 JavaScript 一次性初始化所有 select2 输入,而不是通过 id 手动初始化每个输入。taggable_type
字段用于过滤特定模型的标签,context
字段用于过滤该字段中之前使用过的标签。最后,collection
字段只是在输入中设置适当的值。下一部分是 JavaScript。我们需要初始化整个应用程序中的所有 select2 元素。为此,我只需将以下函数添加到我的
application.js
文件中,以便它适用于每个路由:这可能看起来很复杂,但并不太困难。基本上,
$("*[data-taggable='true']")
选择器只是获取数据中设置了taggable: true
的每个 HTML 元素。我们刚刚将其添加到表单中,这就是为什么 - 我们希望能够为所有可标记字段初始化 select2。剩下的只是AJAX相关的代码。本质上,我们使用参数
name
、taggable_type
和context
对/tags
进行 AJAX 调用。听起来很熟悉吗?这些是我们在表单输入中设置的数据属性。当结果返回时,我们只需为 select2 提供标签的名称即可。现在您可能会想:我没有
/tags
路线!。你说得对!但您即将:)添加 /tags 路由
进入
routes.rb
文件并添加以下内容:resources :tags
。您不必为标签添加所有路由,但我这样做是为了可以轻松地使用 CRUD 标签。您也可以简单地执行以下操作:get '/tags' => 'tags#index'
这确实是我们目前需要的唯一路线。现在我们有了路由,我们必须创建一个名为
TagsController
的控制器:这相当简单。我们可以向
/tags
发送请求,参数为name
(标签文本)、tags_chosen
(现有选定的标签)、taggable_type
(标记的模型)和可选的上下文
(标记的字段)。如果我们有“喜剧”和“阴谋”的流派标签,然后在表单中输入 co,呈现的 JSON 应该如下所示:现在,在 select2 输入中,您应该看到“喜剧”和“阴谋”作为自动完成的标签选项!
我的标签无法保存!
还有最后一步。我们需要将 select2 值设置到我们之前创建的
hidden
字段中。根据您构建表单的方式,此代码可能会有所不同,但您本质上想要获取 select2 输入,将字符串数组转换为 CSV 字符串(例如
["comedy", "conspiracy"] -->
"comedy, conspiracy"
),并将该 CSV 字符串设置到隐藏字段中。幸运的是,这并不是太难。您可以捕获 select2 输入更改事件,或任何其他适合您的事件。这是您的选择,但必须执行此步骤以确保 Rails 控制器正确接收值。同样,在 application.js 中:
成功转换值后,您应该在控制器操作中看到以下内容:
"genre_list"=>"comedy,conspiracy"
并且这就是您使用acts-as-taggable-on 和select2 在Rails 中执行自动完成标记所需的全部内容!
I wrote a blog post about this recently; for the sake of brevity, my method allows you to have (optional) context-filtered tags (e.g. by model and by attribute on the model), whereas @Tim Santeford's solution will get you all tags for a model (not filtered by field). Below is the verbatim post.
I tried out Tim Santeford's solution, but the problem was with the tag results. In his solution, you get all existing tags returned through autocomplete, and not scoped to your models and taggable fields! So, I came up with a solution which is in my opinion much much better; it's automatically extensible to any model you want to tag, it's efficient, and above all else it's very simple. It uses the acts-as-taggable-on gem and the select2 JavaScript library.
Install the Acts-As-Taggable-On gem
gem 'acts-as-taggable-on', '~> 3.5'
bundle install
to install itrake acts_as_taggable_on_engine:install:migrations
rake db:migrate
Done!
Set up normal tagging in your MVC
Let's say we have a
Film
model (because I do). Simply add the following two lines to your model:That's it for the model. Now onto the controller. You need to accept the tag lists in your parameters. So I have the following in my
FilmsController
:Notice that the parameter isn't
genres
like we specified in the model. Don't ask me why, but acts-as-taggable-on expects singular + _list, and this is what is required in the views.Onto the view layer! I use the SimpleForm gem and the Slim template engine for views, so my form might look a little different than yours if you don't use the gem. But, it's just a normal text input field:
You need this
input_html
attribute with that value set in order to render it as a comma-separated string (which is what acts-as-taggable-on expects in the controller). Tagging should now work when you submit the form! If it doesn't work, I recommend watching (the amazing) Ryan Bates' Railscast episode on tagging.Integrating select2 into your forms
First off, we need to include the select2 library; you can either include it manually, or use (my preference) the select2-rails gem which packages select2 for the Rails asset pipeline.
Add the gem to your Gemfile:
gem 'select2-rails', '~> 4.0'
, then runbundle install
.Include the JavaScript and CSS in your asset pipeline:
In application.js:
//= require select2-full
. In application.css:*= require select2
.Now you need to modify your forms a bit to include what select2 expects for tagging. This can seem a bit confusing, but I'll explain everything. Change your previous form input:
to:
We add a hidden input which will act as the real value sent to the controller. Select2 returns an array, where acts-as-taggable-on expects a comma-separated string. The select2 form input is converted to that string when its value changes, and set into the hidden field. We'll get to that soon.
The
id
andname
attributes for thef.input
actually don't matter. They just can't overlap with yourhidden
input. Thedata
hash is really important here. Thetaggable
field allows us to use JavaScript to initialize all select2 inputs in one go, instead of manually initializing by id for each one. Thetaggable_type
field is used to filter tags for your particular model, and thecontext
field is to filter on tags that have been used before in that field. Finally, thecollection
field simply sets the values appropriately in the input.The next part is JavaScript. We need to initialize all select2 elements throughout the application. To do this, I simply added the following function to my
application.js
file, so that it works for every route:This may look complex, but it's not too difficult. Basically, the
$("*[data-taggable='true']")
selector just gets every HTML element where we havetaggable: true
set in the data. We just added that to the form, and this is why - we want to be able to initialize select2 for all taggable fields.The rest is just AJAX-related code. Essentially, we make an AJAX call to
/tags
with the parametersname
,taggable_type
andcontext
. Sound familiar? Those are the data attributes that we set in our form input. When the results are returned, we simply give select2 the name of the tag.Now you're probably thinking: I dont have a
/tags
route!. You're right! But you're about to :)Adding the /tags route
Go into your
routes.rb
file and add the following:resources :tags
. You don't have to add all the routes for tags, but I did so that I could have an easy way to CRUD tags. You could also simply do:get '/tags' => 'tags#index'
That's really the only route we need at the moment. Now that we have the route, we have to create a controller called
TagsController
:This is fairly simple. We can send a request to
/tags
, with the parametersname
(the tag text),tags_chosen
(the existing selected tags),taggable_type
(the model that is tagged), and optionalcontext
(the field that is tagged). If we have genre tags for "comedy" and "conspiracy", then type co in our form, the JSON rendered should look something like this:Now in the select2 input, you should see "comedy" and "conspiracy" as auto-completed tag options!
My tags won't save!
There's one last step. We need to set the select2 values into our
hidden
field that we created earlier.This code may be different for you depending on how you structure your form, but you essentially want to get the select2 input, convert the array of strings to a CSV string (e.g.
["comedy", "conspiracy"]
-->"comedy, conspiracy"
), and set that CSV string into the hidden field. That's not too difficult, fortunately.You can catch the select2 input changed event, or anything else that suits you. It's your choice, but this step must be done to ensure that the Rails controller receives the value correctly. Again, in application.js:
You should see the following in your controller action once you have successfully converted your values:
"genre_list"=>"comedy,conspiracy"
And that's all you need to do autocomplete tags in Rails using acts-as-taggable-on and select2!