Rails [求助] Rails 怎么在评论中 @ 用户时,只显示当前页面的全部用户,并通过后台获取用户的其他信息?

Sylor-huang · September 30, 2018 · Last by Sylor-huang replied at October 01, 2018 · 1275 hits

如题,我的是 Rails 5.2,并调用的时 @ichord 大神的 at.js。 现在,我能获取全部的当前用户,但是我不能通过后台获取用户的一些信息,并显示出来。

相关代码如下:

Rails 代码

## users_controller.rb
 def mentions
    respond_to do |format|
      format.json { render :json => Mention.all(params[:q]) }
    end
  end


## routes.rb

get 'mentions', to: 'users#mentions'


## mentions.rb 

class Mention
  attr_reader :mentionable
  include Rails.application.routes.url_helpers

  def self.all(letters)
    return Mention.none unless letters.present?
    users = User.limit(5).where('name LIKE ?', "#{letters}%").compact
    users.map do |user|
      { name: user.name, img: user.picture.nil? ? "images/default_member.png" : user.picture.url, name_before: user.name_before ? user.name_before : "" }
    end
  end

  def self.create_from_text(post)
    potential_matches = post.content.scan(/@\w+/i)
    potential_matches.uniq.map do |match|
      mention = Mention.create_from_match(match)
      next unless mention
      post.update_attributes(content: mention.markdown_string(post.content))
      # You could fire an email to the user here with ActionMailer
      mention
    end.compact
  end

  def self.create_from_match(match)
    user = User.find_by(name: match.delete('@'))
    UserMention.new(user) if user.present?
  end

  def initialize(mentionable)
    @mentionable = mentionable
  end

  class UserMention < Mention
    def markdown_string(text)
      host = Rails.env.development? ? 'localhost:3000' : '' # add your app's host here!
      text.gsub(/@#{mentionable.name}/i,
                "[**@#{mentionable.name}**]("")")
    end
  end
end


##  comments_controller.rb

def new
    @comment = Comment.new
    Mention.create_from_text(self)
  end

js 代码


## markdown.js


## 获取当前页面的全部用户并去重
function logins(){
        let uName = [];
        $("a.username").each(function () {
            uName.push($(this).text());
        });
        return $.unique(uName);
    }


### 调用atwho功能
    function mentionable(logins){
        if(logins.length > 0){
            $("textarea").atwho({
                at: '@',
                limit: 8,
                callbacks:{
                    remoteFilter: function (query,callback) {
                        if(query.length < 1){
                            return false;
                        }else{
                            $.getJSON('/mentions',{q:query},function(data){
                                console.log(data)
                                callback(data);
                            });
                        }
                    }
                },
                'data':'/mentions',
                displayTpl: "<li data-value='@${name}'><img src='${img}' height='20' width='20' style='border-radius: 20px'/><span class='mlr5'>${name}</span> <small>${name_before}</small></li>",
            });
        }else{
            console.log("无内容");
        }
    }

    mentionable(logins());

请问下路过的各位大神,我按上述代码,当我在评论框,输入@时,提示错误信息如下,并且没有用户下拉框,但是在@后,输入字符,可以查询的到用户信息。

Completed 500 Internal Server Error in 9ms (ActiveRecord: 1.1ms)
NoMethodError - undefined method `none' for Mention:Class:
  app/models/mention.rb:6:in `all'
  app/controllers/users_controller.rb:73:in `block (2 levels) in mentions'
  app/controllers/users_controller.rb:72:in `mentions'

你可以读读 Ruby China 的实现,原理是用户名的 DOM 有标记,@ 的时候取出来去重即可

@huacnlee 好的,谢谢李哥。我的用户名也有 DOM 标记,我看了下 homeland 的代码。好像当前页面(本地)的用户,您好像是直接获取用户名、用户图片等信息的。

代码:

Homeland 的 app.coffee

scanMentionableLogins: (query) ->
  result = []
  logins = []
  for e in query
    $e = $(e)
    item =
      login: $e.find(".user-name").first().text()
      name: $e.find(".user-name").first().attr('data-name')
      avatar_url: $e.find(".avatar img").first().attr("src")
    continue if not item.login
    continue if not item.name
    continue if logins.indexOf(item.login) != -1

    logins.push(item.login)
    result.push(item)

  console.log result
  _.uniq(result)

mentionable : (el, logins) ->
  logins = [] if !logins
  $(el).atwho
    at : "@"
    limit: 8
    searchKey: 'login'
    callbacks:
      filter: (query, data, searchKey) ->
        return data
      sorter: (query, items, searchKey) ->
        return items
      remoteFilter: (query, callback) ->
        r = new RegExp("^#{query}")
        # 过滤出本地匹配的数据
        localMatches = _.filter logins, (u) ->
          return r.test(u.login) || r.test(u.name)
        # Remote 匹配
        $.getJSON '/search/users.json', { q: query }, (data) ->
          # 本地的排前面
          for u in localMatches
            data.unshift(u)
          # 去重复
          data = _.uniq data, false, (item) ->
            return item.login;
          # 限制数量
          data = _.first(data, 8)

          callback(data)
    displayTpl : "<li data-value='${login}'><img src='${avatar_url}' height='20' width='20'/> ${login} <small>${name}</small></li>"
    insertTpl : "@${login}"
  .atwho
    at : ":"
    limit: 8
    searchKey: 'code'
    data : window.EMOJI_LIST
    displayTpl : "<li data-value='${code}'><img src='#{App.twemoji_url}/svg/${url}.svg' class='twemoji' /> ${code} </li>"
    insertTpl: "${code}"
  true

我希望的是:用 DOM 标记获取当前用户的名称,然后通过mentionable() 函数,把当前页面 用户名的数组传到users_controller中的mentions动作,再通过查询用户数据库,返回用户的其他相关的信息。但是实际上,我现在获取到的用户名数组,不能传到 mentions动作,但是我不知道,我现在的问题时出现在哪里了?

非常感谢您的帮助~

You need to Sign in before reply, if you don't have an account, please Sign up first.