2

I have established a Twitter-like @replies that allows users to contact one another through user dailyposts...similar to stackoverflow's.

Using this as a guide https://github.com/kltcalamay/sample_app/compare/original-version...master

How can I parse/scan a post & then replace the @usernames with the link to that users page

EXAMPLE of a post.

Kevins Post:
 @Pzpcreations @john @steve hey everyone lets all hang out today

I want scan/parse the post and then link the users @Pzpcreations @john @steve to their profile

I tried creating a method in my Dailypost Model, that stores the usernames in an array....but IDK how to replace and link them to the appropriate users page

def username_link
  str = self.content_html
  recipient = str.scan(USERNAME_REGEX)
end

This gives me ["@Pzpcreations", "@john", "@steve"]

Please help me out....new to rails :)

MODELS

class Recipient < ActiveRecord::Base
  attr_accessible :dailypost_id, :user_id

  belongs_to :user
  belongs_to :dailypost

end

class User < ActiveRecord::Base
  attr_accessible :name, :email, username

  has_many :dailyposts, dependent: :destroy

  has_many :replies, :class_name => 'Recipient', :dependent => :destroy
  has_many :received_replies, :through => :replies, :source => 'dailypost'

end

class Dailypost < ActiveRecord::Base  
  attr_accessible :content, :recipients
  belongs_to :user

  ###What is the Correct REGEX for Rails 4?
  USERNAME_REGEX = /@\w+/i

  has_many :recipients, dependent: :destroy
  has_many :replied_users, :through => :recipients, :source => "user"

  after_save :save_recipients

  **private**

    def save_recipients
      return unless reply?

      people_replied.each do |user|
        Recipient.create!(:dailypost_id => self.id, :user_id => user.id)
      end
    end

    def reply?
      self.content.match( USERNAME_REGEX )
    end

    def people_replied
      users = []
      self.content.clone.gsub!( USERNAME_REGEX ).each do |username|
        user = User.find_by_username(username[1..-1])
        users << user if user
      end
      users.uniq
    end
end

SCHEMA

create_table "recipients", :force => true do |t|
  t.string   "user_id"
  t.string   "dailypost_id"
  t.datetime "created_at",   :null => false
  t.datetime "updated_at",   :null => false
end

[#<Recipient id: 7, **user_id: "103"**, dailypost_id: "316", created_at: "2013-06-18 
10:31:16", updated_at: "2013-06-18 10:31:16">]

User_ID in recipients are the users that are mentioned in the Dailypost.

VIEWS

<%= link_to dailypost.username_link %>
Serge Pedroza
  • 2,140
  • 2
  • 24
  • 38

2 Answers2

2

You can pass each match through to a block. In this block you return the link required, something like

def username_link
  str = self.content_html
  str.gsub!(USERNAME_REGEX).each do |recipient|
    if User.find_by_name(recipient) 
      "[link to #{recipient}]"
     else 
       recipient
     end
  end
end

Edit

Create a helper function in app/helpers/posts_helper.rb

def post_with_links(post)
  post.content_html.gsub(/@\w+/).each do |username|
    user = User.find_by_username(username[1..-1])
    if user
      link_to username, user
    else
      username
    end
end

use this in your view

<%= post_with_links(post) %>
Ian Kenney
  • 5,661
  • 1
  • 21
  • 39
  • Thanks! :), i think you have extra syntax. i got a couple of errors along the way @Ian Kenney – Serge Pedroza Jun 20 '13 at 20:46
  • Think you can help me out....I am still having routing problems. :/ @Ian Kenney http://stackoverflow.com/questions/17229034/href-to-users-profile-is-redirecting-me-to-user-index/17230150?noredirect=1#17230150 – Serge Pedroza Jun 21 '13 at 07:53
1

You're looking to do a find and replace on each user name, and also generating the link to the user's profile. It would look something like this:

def username_link
  new_content_html = self.content_html  
  recipients = new_content_html.scan(USERNAME_REGEX)

  recipients.each do |recipient|
    user = User.find_by_username(recipient) # strip off the @ if required
    new_content_html.gsub!(recipient, "<a href='#{users_path(user)}'>#{user.username}</a>")
  end

  new_content_html
end

This assumes you've got a route for users in your route file which generates the users_path method.

There's a whole rabbit hole of additional things to talk about as it regards a twitter like reply system and discovering those on your own is going to be half the fun! ;)

Gavin Miller
  • 40,636
  • 19
  • 113
  • 178
  • this may have problems with partial matches - e.g. \@jo \@joe \@jon lets hang out ... – Ian Kenney Jun 20 '13 at 20:19
  • You should probably do a single query to find all the names in the database at once, instead of a query per name found. Also what happens if the name isn't found? – Sirupsen Jun 20 '13 at 20:20
  • I have updated my routes and controllers...Any idea why i keep getting Undefined method `users_path' for # @Gavin Miller – Serge Pedroza Jun 20 '13 at 20:59
  • http://stackoverflow.com/questions/341143/can-rails-routing-helpers-i-e-mymodel-pathmodel-be-used-in-models has details on how to access routing helpers from models – Ian Kenney Jun 20 '13 at 21:02