模型中的current_user

时间:2016-02-26 15:44:22

标签: ruby-on-rails ruby-on-rails-4 devise

我首先要说的是,我知道你应该在模型调用中访问当前用户。但我刚刚遇到了一个需要代码的情况。这就是我发布这个问题的原因 - 我需要知道如何做到这一点的最佳实践。

我的Nodes.rb中有一个方法,需要访问current_user才能生成正确的结果:

Node.rb

def tagged_users
  tag_list = self.user_tag_list
  email_tags = tag_list.select { |x| x.match("@") }
  id_tags = tag_list.select { |x| x.match(/^[^@]*$/) }
  users = User.where(email: email_tags, invitation_token: nil).where(id: current_user.memberships.pluck(:user_id).compact)
  members_email = Member.where(email: email_tags).where(id: current_user.memberships.pluck(:member_id).compact)
  members_id = Member.find_by_full_name(id_tags, current_user)
  users + members_email + members_id
end

我必须在一些部分和集合上访问此实例方法,如下所示:

_user_tag_list.html.erb

<% node.tagged_users.each do |tag| %>
  <div class="card-back__tagged-user">
    <div class="tagged-user__avatar">
        <img src="<%= avatar_url(tag) %>"  alt="" class="tagged-user__photo">
    </div>

    <div class="tagged-user__title">
        <h4 class="tagged-user__title-text"><%= tag.first_name %> <%= tag.last_name %></h4>
    </div>

    <%= link_to node_path(node, remove_tag: tag.first_name + ' ' + tag.last_name), class:'tagged-user__action', remote: true, method: :patch do %>
        <i class="icon-close"></i>
    <% end %>
  </div>
<% end %>

从另一个部分

调用
_node.html.erb    

<div class="tagged_users">
    <%= render partial: "nodes/user_tag_list", locals: {node: node} %>
</div>
在其他一些集合和js.erb中也会调用

tagged_users。我是否将其移至控制器,是否修改了模型中的方法等?您的答案表示赞赏。谢谢!

3 个答案:

答案 0 :(得分:2)

如果是我,我会将该方法转移到它自己的服务中,我倾向于放置像这些模型这样的方法,因为我倾向于Single-Responsibility原则。

class TaggedUsers
  def self.call(node, current_user) 
    tag_list = node.user_tag_list
    email_tags = tag_list.select { |x| x.match("@") }
    id_tags = tag_list.select { |x| x.match(/^[^@]*$/) }
    users = User.where(email: email_tags, invitation_token: nil).where(id: current_user.memberships.pluck(:user_id).compact)
    members_email = Member.where(email: email_tags).where(id: current_user.memberships.pluck(:member_id).compact)
    members_id = Member.find_by_full_name(id_tags, current_user)
    users + members_email + members_id
  end
end

然后,在我的控制器中,我可以做这样简单的事情:

# NodesController (well, my guess at it :)). 
def show 
  @node = Node.find(params[:id])
  @tagged_users = TaggedUsers.call(@node, current_user)
  # blah blah blah ... other code 
end

在视图中,它将像“简单”一样:

= render partial: 'nodes/user_tag_list', locals: ( node: @node, tagged_users: @tagged_users } 

或类似的东西......希望这会有所帮助!

答案 1 :(得分:2)

这很简单。传递current_user作为参数。

def tagged_users(current_user)
  # ...
end

并在视图中使用它。

 <% node.tagged_users(current_user)...

或者,您可以在attr_accessor中设置Node。但我会传递用户。

class Node
  attr_accessor :current_user
end

然后,只要你立刻就是一个节点:

@node.current_user = current_user

答案 2 :(得分:0)

理想情况下,您将行为移动到另一个对象,例如服务或命令对象。我认为craig.kaminsky的解决方案是一个非常好的开始。

但是,如果你真的想要在Node模型上保持这种行为,你也可以重新定义Node#tagged_users以接受current_user参数:Node#tagged_users(current_user)。然后在您看来,您可以:

<% node.tagged_users(current_user).each do |tag| %>

这样就可以了。