pfaffman
(Jay Pfaffman)
2019 年8 月 1 日 19:14
1
我正在开发一个插件,用于为在特定分类中创建的新主题分配默认标签。
下面的代码在输入用“|”分隔的标签名称时“可以工作”,例如“tag1|tag2”就能用。(我简直不敢相信!不过先不说这个。)
<h3>{{i18n 'topic_default_tag.title'}}</h3>
<section class='field default-tag'>
<div class="default-tag">
<label>
{{input type="list" value=category.custom_fields.default_tag }}
{{popup-input-tip validation=tagValidation}}
{{i18n 'topic_default_tag.default_tag'}}
</label>
</div>
</section>
现在我希望使用一个真正的标签选择器,而不是未经验证的字符串。看起来下面的代码应该可以工作:
<h3>{{i18n 'topic_default_tag.title'}}</h3>
<section class='field default-tag'>
<div class="default-tag">
<label>
{{tag-chooser tags=category.custom_fields.default_tag tabindex="4" categoryId=category.id}}
{{popup-input-tip validation=tagValidation}}
{{i18n 'topic_default_tag.default_tag'}}
</label>
</div>
</section>
但实际并不行。我的问题根源在于,我对 Handlebars 的那些“魔法”几乎一无所知。比如,我猜第一部分之所以能工作,是因为它“神奇地”从 <section class='field default-tag'> 中的 default-tag 获取了字段名,但这纯属运气。
当我使用 tag-chooser 时,标签会以数组形式传递给 Rails,而 Rails 在我将它们转换为用 | 分隔的字符串并写入 CategoryCustomField 之前就丢弃了它们。使用 {{input type=list...}} 时,我可以手动输入用 | 分隔的字符串,一切正常。我是否需要在 Ember 端使用某种“魔法”将数组转换为字符串?
也许我需要参考类似 What's the best approach to access category specific settings? 的做法?
编辑:若要在 webhook 被调用之前添加标签,请使用 after_create 而不是 DiscourseEvent.on(:post_created)。Rails 现在对我来说基本说得通了,但 Ember、JavaScript 和 CSS 就另当别论了。
fzngagan
(Faizaan Gagan)
2019 年8 月 1 日 20:29
2
你可以通过使用 {{log variable_name}} 并检查控制台,来确认所使用的变量是否包含所需的值。如果未将正确的值传递给组件,则无法显示正确的输出。
你也可以在核心代码中进行同样的操作以验证,确认这些值是否正确传递。
如果我的说法听起来有些天真,请见谅。
pfaffman
(Jay Pfaffman)
2019 年8 月 1 日 20:43
3
fzngagan:
如果听起来很天真,请见谅。
不!我只是个原始人。
这非常有帮助,因为我之前不知道该如何操作。事实证明,这些字段中确实 有数据。而且 ,标签名称数据确实 位于 category.custom_fields.default_tag 中,并已被传递给 mini-tag-chooser。category.id 确实包含类别的 ID,但选择器没有提供任何标签。
我无法判断如果数据存在,是否会被推送到该字段中。
编辑:噢!但使用 tag-chooser 而不是 mini-tag-chooser 可以正常工作(我会相应地修改上面的代码)。唯一的问题是,当我点击保存时,数据并没有被保存。
fzngagan
(Faizaan Gagan)
2019 年8 月 1 日 20:51
4
这一行让我起了疑心。我认为 tags 参数可能期望接收一个数组,而据我看来,你传入的是单个值(这一点需要确认)。如果确实传入的是单个值,请将其改为数组后再试。
pfaffman
(Jay Pfaffman)
2019 年8 月 1 日 21:00
5
好吧,在 Rails 这边,它是一个由 | 分隔的字符串。提交后我看到我输入的内容确实被提交了,例如:"custom_fields"=>{"default_tag"=>["error", "high-availability", "best-practices"]}, 和 "custom_fields"=>{"default_tag"=>["health-checks"]},。
以下是完整内容:
Started PUT "/categories/2" for 127.0.0.1 at 2019-08-01 13:56:13 -0700
Processing by CategoriesController#update as */*
Parameters: {"name"=>"Lounge", "slug"=>"lounge", "color"=>"EEEEEE", "text_color"=>"652D90", "permissions"=>{"trust_level_3"=>"1"}, "auto_close_hours"=>"", "auto_close_based_on_last_post"=>"false", "position"=>"3", "email_in"=>"", "email_in_allow_strangers"=>"false", "mailinglist_mirror"=>"false", "allow_badges"=>"true", "custom_fields"=>{"default_tag"=>["error", "high-availability", "best-practices"]}, "topic_template"=>"", "suppress_from_latest"=>"false", "all_topics_wiki"=>"false", "allow_global_tags"=>"false", "sort_order"=>"", "sort_ascending"=>"", "topic_featured_link_allowed"=>"true", "show_subcategory_list"=>"false", "num_featured_topics"=>"3", "default_view"=>"", "subcategory_list_style"=>"rows_with_featured_topics", "default_top_period"=>"all", "minimum_required_tags"=>"0", "navigate_to_first_post_after_read"=>"false", "search_priority"=>"0", "id"=>"2"}
看起来神秘的那一端确实发生了正确的事情,但 Rails 并没有更新 Category Custom Field。我将回去对比我现有的代码和另一个处理 CategoryCustomField 的插件。
非常感谢,@fzngagan !
编辑:嗯。我想问题在于:
Unpermitted parameter: :default_tag
fzngagan
(Faizaan Gagan)
2019 年8 月 1 日 21:10
6
你一定会很享受找到答案的过程。不过,如果你需要帮助,我非常乐意提供。
fzngagan
(Faizaan Gagan)
2019 年8 月 1 日 21:36
7
pfaffman:
未授权的参数::default_tag
是的。Rails 目前还不知道如何处理这个新字段。你需要使用 add_to_serializer 将该新字段添加进去。你可以在添加自定义字段的插件中看到相关示例。
pfaffman
(Jay Pfaffman)
2019 年8 月 1 日 21:43
8
好吧,plugin.rb 包含以下内容:
Category.register_custom_field_type('default_tag', :list)
Site.preloaded_category_custom_fields << 'default_tag' if Site.respond_to? :preloaded_category_custom_fields
add_to_serializer(:basic_category, :default_tag) { object.custom_fields["default_tag"] }
如果你愿意查看,代码位于 https://github.com/pfaffman/discourse-topic-default-tag。
我感到困惑,因为以下代码:
{{input type="list" value=category.custom_fields.default_tag }}
可以正常工作,但
{{tag-chooser tags=category.custom_fields.default_tag tabindex="4" categoryId=category.id}}
却无法运行。
编辑:看起来使用 tag-chooser 时,我的自定义字段会被作为数组发送到 Rails,然后在处理前被丢弃;而使用 text field 并创建一个以 | 分隔的字符串时,则一切正常。(我曾以为可以在 Rails 端通过 before_validation 来修复这个问题,但并未成功。)
所以我想我需要在 Ember 端做一些“魔法”操作,在数据发送回服务器之前将数组转换为字符串?
fzngagan
(Faizaan Gagan)
2019 年8 月 3 日 14:07
9
我也曾不带参数使用 tag-chooser,它获取了所有可用的标签。
此外,我认为我找到了在使用 tag-chooser 时这些标签未被保存(甚至未到达)Rails 端的原因。当你使用 input type=list 并添加 value 字段时,它会自动成为表单的一部分。
但 tag-chooser 生成的标记是一个 div。这就是为什么它未被包含在表单提交中的原因。
我正在尝试为其提供一个变通方案。一旦实现,我将提交一个 PR。
pfaffman
(Jay Pfaffman)
2019 年8 月 3 日 19:46
10
我昨天和 @j.jaffeux 谈过,他正在着手进行一项更改。
fzngagan
(Faizaan Gagan)
2019 年8 月 3 日 20:05
11
这正是我正在做的。
太好了。作为一名新手,我正努力不断学习,这对我帮助很大
fzngagan
(Faizaan Gagan)
2019 年8 月 4 日 19:21
12
你好 @pfaffman 。
我成功整理出了一个修复方案。由于 tag-chooser 功能过于出色,我不愿从 Ember 端舍弃它,因此我选择在 Rails 端进行修复。
我在 CategoriesController 中编写了一个简单的函数,并将其设置为 :before_action。在该函数中,我将 default_tag 数组转换为以 | 分隔的字符串。
其次,我将 before_update 改为 before_commit,因为 custom_fields 似乎是在该执行阶段才被设置的。
pfaffman
(Jay Pfaffman)
2019 年8 月 4 日 21:56
13
嗯,我以为我已经试过了,不过到了办公室我会再检查一下。谢谢!
pfaffman
(Jay Pfaffman)
2019 年8 月 5 日 22:06
14
啊哈!这正是我不知道如何做到的。你是把它放在 plugin.rb 里吗?
fzngagan
(Faizaan Gagan)
2019 年8 月 6 日 03:34
15
是的。这对我起作用了。
class ::ApplicationController
def convert_default_tag
return unless :topic_default_tag_enabled
puts 'request'
# 只需检查字段是否存在,以避免出错
request.params["custom_fields"]["default_tag"] = request.params["custom_fields"]["default_tag"].join('|')
p request.params["custom_fields"]["default_tag"]
end
end
require 'categories_controller'
class ::CategoriesController
before_action :convert_default_tag , only: [:create]
end
我认为完全可以在控制器本身定义 default_tag 方法,但我无法让这种方式生效。由于每个 Discourse 控制器都继承自 ApplicationController,该方法在扩展自 ApplicationController 时就会被加载,从而达到了目的。
@merefield
是否可以在控制器本身定义一个名为 :before_action 的方法来调用?
fzngagan
(Faizaan Gagan)
2019 年8 月 6 日 03:39
17
谢谢。我原以为是单反引号,但卡住了。所以我用了普通的 HTML <pre></pre> 标签来让它生效。
pfaffman
(Jay Pfaffman)
2019 年8 月 6 日 20:27
19
这真是帮了大忙。现在我有了这段代码:
class ::CategoriesController
before_action :default_tag_to_string, only: [:create, :update]
def default_tag_to_string
puts "CDT: #{params}"
return unless :topic_default_tag_enabled
# 只需检查字段是否存在,以避免报错
request.params["custom_fields"]["default_tag"] = request.params["custom_fields"]["default_tag"].join('|')
p request.params["custom_fields"]["default_tag"]
end
end
现在,在 Rails 尝试更新记录之前,选中的标签会被转换为字符串,并且按预期工作。
现在 的问题是,我需要弄清楚在 Rails 站点上应该在哪里将这个字符串转换回我们在 JavaScript/Ember 端所需的数组。@j.jaffeux ,我不记得(或者更可能的是,我当时没理解)你当时试图解决的问题是在 JavaScript 到 Rails 这一侧重写该值(已解决!),还是在 Rails 到 JavaScript 这一侧(目前仍感到困惑)。
fzngagan
(Faizaan Gagan)
2019 年8 月 7 日 02:03
20
对我有效的方法是:在将标签分配给主题时,将代码中的 :before_update 改为 :before_commit。
其次,当你打开编辑分类页面时,默认标签设置字段需要在其 tags 参数中传入一个数组,才能正确显示已选中的标签。