在Rails中使用逗号分隔的数组及文本字段

12

我有一些用户,这些用户可以拥有许多帖子,每个帖子都可以有许多标签。我使用has_and_belongs_to_many关系在帖子和标签之间实现了这一点。

当创建新帖子时,用户可以使用逗号分隔的值列表对其进行标记(就像在SO上发布新问题时一样)。如果任何一个标签不存在,则应自动创建。这是帖子的_fields.html.erb部分:

<%= form_for @post do |f| %>
  <%= render 'shared/error_messages', :object => f.object %>

  <h1 class="post"><%= t(:new_post_message) %></h1>

  <div class="field">
    <%= f.label t(:title) %>
    <br />
    <%= f.text_field :title %>
  </div>

  <div class="field">
    <%= f.label t(:tag).pluralize %>
    <br />
    <%= f.text_field :tags %>
  </div>

  <div class="field">
    <%= f.label t(:text) %>
    <br />
    <%= f.text_area :content %>
  </div>

  <div class="actions">
    <%= f.submit t(:post_verb) %>
  </div>
<% end %>

使用 f.text_field :tags 目前会生成一个带有文本 [] 的输入元素。

我现在还没有在 posts_controller.rb 中使用标签,因为我不确定该如何获取和拆分参数中的字符串值:

def create
  @post = current_user.posts.build(params[:post])
  if @post.save
    redirect_to root_path
  else
    @stream = []
    render 'pages/home'
  end
end

有人之前解决过这个问题吗?非常感谢。
1个回答

27

我希望在post.model上创建一个属性来读取标签,例如:

app/models/post.rb

def tag_list
  self.tags.map { |t| t.name }.join(", ")
end

def tag_list=(new_value)
  tag_names = new_value.split(/,\s+/)
  self.tags = tag_names.map { |name| Tag.where('name = ?', name).first or Tag.create(:name => name) }
end

然后,您可以执行以下操作:

<%= f.text_field :tag_list %>

不使用 :tags

帖子模型将接受标签列表,将其拆分为标签名称,查找标签是否存在,如果不存在则创建。无需控制器逻辑。

编辑 当然,此代码依赖于您的标签模型具有一个名为 name 的属性(如果没有,请用您存储标签名称的任何属性替换它),并且在数据库中是唯一的(即您的标签模型中使用了类似于 validates_uniqueness_of :name 的东西)。


谢谢!你的解决方案完美地解决了我的问题,我只需要在 app/models/post.rb 中的 attr_accessible 添加 :tag_list,像这样:attr_accessible :title, :content, :tag_list - Vlad Sabev
不用客气!关于 attr_accessible 的观点很好。再提一个小风格问题,我在重新阅读我的代码时注意到,将范围添加到标签中可能是值得的,例如 scope :called,lambda { |n| where('tags.name = ?',n) },然后使用它来替换 where(...) 方法。 - Chris Bailey
我可以建议使用以下代码行来分配新标签:Tag.where('name=?', name.strip).first or Tag.create(:name => name.strip) - Rafael Vega
这个非常好的解决方案真是太棒了,点赞! - deadroxy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接