在创建时返回关联的模型

时间:2014-09-26 18:13:52

标签: ruby-on-rails activerecord

我有一个Comment对象,在Tag关联中可以有许多has_and_belongs_to_many个与之关联的对象。在创建时,我希望注释包含与其关联的标记,希望无需进行单独的查询。怎么办呢?

修改

为了帮助澄清我的问题,这是我的评论创建控制器方法:

def create
  @comment = @current_user.comment!(@post, comment_params[:content])

  render :show, status: :created
end

这是我的comment!方法:

def comment!(yum, content)
  comment = comments.create!(yum_id: yum.id, content: content)
  comment.create_activity :create, owner: self, recipient: yum.user

  mentions = content.scan(/\@\w+/)
  for mention in mentions
    if mentioned_user = User.find_by_username(mention.sub("@", ""))
      mention!(mentioned_user, comment) 
    end
  end

  comment
end

这是检查保存前执行的标签文本的方法:

def create_tags
  tags = content.scan(/\#[[:alnum:]]+/)
  for tag in tags
    tag = tag.sub("#", "")
    if found_tag = Tag.find_by_content(tag.downcase)
      self.tags << found_tag
    else
      self.tags.build(content: tag)
    end
  end
end

这是我的jbuilder评论观点:

json.extract! comment, :id, :content, :created_at, :updated_at

json.tags comment.tags do |tag| 
  json.partial! 'api/v1/shared/tag', tag: tag
end

json.user do |json|
  json.partial! 'api/v1/shared/user', user: comment.user
end

我想要的是在创建评论时要包含的标签(并且提到了它,但是解决一个解决了另一个)。当我只是显示那些已经包含的评论时,它在创建时只返回评论。

3 个答案:

答案 0 :(得分:0)

如果我正确理解了这个问题,可以通过覆盖Comment对象的as_json方法来解决这个问题。

# in Comment.rb

def as_json(options = nil) 
  super( (options || {}).merge({
    include: :tags       
  })
end

这应该确保当注释呈现为JSON时,哈希还包含tags关联。当您在ActiveRecord对象上调用as_json时,会调用to_json方法 - 有关更详细的说明,请参阅this出色的答案或as_json方法的文档{ {1}} here

如果我误解了你的问题,请告诉我! : - )

答案 1 :(得分:0)

试试这个:

def create
  @comment = @current_user.comment!(@post, comment_params[:content])

  render json: @comment.to_json( include: :tags ), status: :created, location: @comment
end

答案 2 :(得分:0)

您需要使用where子句过滤Tag对象:

替换:

  tags = content.scan(/\#[[:alnum:]]+/)
  for tag in tags
    tag = tag.sub("#", "")
    if found_tag = Tag.find_by_content(tag.downcase)
      self.tags << found_tag
    else
      self.tags.build(content: tag)
    end
  end

使用:

  sent_tags = content.scan(/#([[:alnum:]]+)/).flatten.map &:downcase
  self.tags = Tag.where(content: tags) # This is the line that saves multiple queries

  new_tags  = sent_tags - tags.map(&:content)
  new_tags.each do |new_tag|
    self.tags.build(content: new_tag)
  end

注意:

2.1.2 :016 > "some #Thing #qwe".scan(/#([[:alnum:]]+)/).flatten.map &:downcase
 => ["thing", "qwe"] 

sent_tags会根据您的需要存储代码。