2011-12-22 14 views
5

Githubに問題があり、問題31を参照してください。そして、この問題を書いている間、あなたは@hohnmettaが彼が取り組んでいるいくつかの可能な解決策を示唆していることに気づきました。その後、 "Submit New Issue"を押すと、 "#31"と "@johnmetta"がリンクになり、@hohnmettaに通知され、#31のissueにはそれが参照されたという通知があります。Railsでテキスト提出でオブジェクトに自動的にリンクする方法

ここには、複数の技術があることが分かりましたが(Javascriptなど)、私が探しているのは、Railsの世界でこのようなことをする方法の例です。それは興味深いことに難しい検索対象です。

私は概念的を作ってみたことはある:

  1. 適切な属性でその識別子の検索
  2. すると、#またはその@が提出されると
  3. を予約されているなど、いくつかの識別子を持っていますそれに続くフィールドに一致するフィールドを持つ適切なモデルを検索する
  4. 見つかったら、そのテキスト文字列をリンクで置き換えます。
  5. オプションで、rそれは超簡単ですように言っeferencedオブジェクト

、それはは(明示的にコード化され、friendly_idを想定)ようです。

def prettify_user_links(str, source): 
    result = str 
    str.scan(/(@\S+)+/).each do |mtch| 
    # Strip off whatever identifier we're using 
    search_string = mtch[0].gsub('@','') 
    # Search for the matching model in the appropriate table 
    user = User.find(search_string) 
    if user 
     # If we find a matching model, create some link text and link it 
     link_txt = "<a href=>'#{user.url}'>#{mtch}</a>" 
     result.gsub!(search_string, link_txt) 
     # Notification. Not sure how/where, maybe with a message bus, or something more brute-force like 
     Comment.create :user_id => user.id, :body => "You have been mentioned in #{link_to comment.excerpt, comment} by #{link_to comment.owner, owner}" 
    return result 

これは私の最初のカットになりますが、はるかに洗練されたソリューションが必要だと感じています。

この質問に対する追加の側面:周囲のテキストのスニッピットをどのように捉えますか?ブルートフォースの方法は、その文字列の前にn個の単語を検索してからm個の単語を検索し、そのすべてを取得し、その結果からそのサブ文字列を取得して検索することです。それでも、より洗練されたソリューションがあるようです。

答えて

2

説明したことが基本的な方法です。他の何かがひどく優雅ではない。それは2つの部分と見なすことが役に立ちます.1つはコメントを受け取ったとき(通知を行うべきとき)であり、もう1つはコメントを表示しているときです。

元のコメントをそのまま元の形式に保持することができます。 (通知は、すべての編集に送信されないようにする)

おそらくコメントモデル(「body」フィールドが含まコメントモデルを仮定)にafter_createを置く:

を[編集:追加のコンテキスト情報]

after_create :notify_mentions 

def notify_mentions 
    body.scan %r{(.{0,40})@(\w+)(.{0,20})} do |match| 
    username = match[1] 
    context = [match.first, match.last] 
    Notification.send(match, context, self) if User.exists?(:login => username) 
    end 
end 

人々はしばしばのようなものを言うので、私は\S+の代わりに\w+を使用しますねえ

を@ジョンメッタ、元気?

および\S+は、間違っている可能性があります,をキャプチャします。キャプチャグループから@を引き出すと、通知中に無視されます。

上記の一致グループのcontextは、スニペットの一致するユーザー名の前の40文字と20文字で構成されています。味に合わせて調整する。メッセージを表示する場合次に、あなたは基本的にあなたが持っていたもののようなヘルパー何か作成

:それはブロックを取り、内容に置き換えることで

def linkify(body) 
    body.gsub %r{@\w+} do |match| 
    link_to match, :controller => :users, :action => :show, :id => match 
    end 
end 

#gsubは、そのような素晴らしいです。

これはあなたが持っていたものよりもはるかにエレガントではありませんが、それはかなりまともな結果を与えるはずです。

+0

これは私が思っていたものにかなり近いですが、after_createメソッドの通知で2つの非常に個別のステップに分割することは考えていませんでした。そして、私は前と後の試合からテキストを正規表現したり引っ張ったりすることについて知らなかった。驚くばかり。本当にありがとう。 – JohnMetta

関連する問題