Implementing twitter-like hashtag on rails - ruby-on-rails

I'm want to implement twitter-like hashtag on my app.
Let's say I have user input to a text area "I'm coming to #london from #paris" then I want to build tag cloud of the hashtags.
I'm thinking of using acts-as-taggable-on. So I find all of my hashtags from the text in the backend, then save it to tag field.
Anyone has experience on this they would like to share? Thanks.

Yes, ActsAsTaggableOn should be fine. As #etang alluded to, it's a heavy gem, but it gets the job done. If you're looking for a simple way to extract tags from text, you may want to look at https://github.com/twitter/twitter-text-rb. It has some nice regexps that may save you some time.
Twitter::Extractor.extract_hashtags("my #favorite #site is http://foo.com/home#boo")
That would return "favorite" and "site" but not "boo" (as would be expected).

For late-comers…
I have written a simple gem for precisely for this:
https://github.com/ralovely/simple_hashtag
Give feedback or contribute if you feel like it.

ActsAsTaggableOn should work fine if you are not too worried about scaling. It keeps track of your actual tags by ActsAsTaggableOn::Tag, and keeps track of the many-to-many relationship to your posts by ActsAsTaggableOn::Tagging. It also uses polymorphic association in ActsAsTaggableOn::Tagging so you can tag in different namespaces.

Related

Generate random human understandable ID for users in rails

I want to generate a unique (human recognisable) id for each user that changes when they comment on different posts in my app. (so doesn't need to be stored in db as is constantly changing). The ID only needs to be used within the scope of a thread.
What I mean by this is identical to what YikYak does. In YikYak, anonymity is essential, so in each thread, users are assigned a randomly generated avatar which is the only way they and other people recognise which posts are posted from the same user.
I'm building an app where I too need anonymity, but I need users to be able to recognise when other people are commenting more than once.
What is the best thing to generate? A string of 2 random words like "Brocolli umbrella"? Or is there a way to randomly generate a simple avatar?
Any advice much appreciated
You might try ffaker gem and use
FFaker::Name.name
#=> "Christophe Bartell"

acts_as_taggable_on find existing tags to suggest from content

We're using the (brilliant) acts_as_taggable_on Rails gem, allowing users to add tags to content they write (e.g. blog comment). We auto-suggest on as they type, but would also like to identify tags that we can suggest based on the user's content.
So if the user typed "We really loved the aquarium in Boston" and we had existing tags for "boston" and "aquarium" we might suggest those.
I think this is simple conceptually (iterate words, check the tags list, order by frequency of use), but there are little nuances, performance implications, and well, you know -- always harder than it looks.
Any suggestions for existing code or examples that might help me avoid recreating a wheel?
Thanks!
Well, I don't really know acts_as_taggable... But I think you can use something like :
Tag.find(:all, :conditions => { :name => title.split(' ').map(&:downcase) })

Replace twitter-like usernames in a model's attribute automatically in Ruby on Rails

I'm having a very hard time trying to figure out how to do this the MVC way. I have a Comment model which holds a body attribute. This attribute may contain mentions such as the following:
Hi! This is me mentioning #someone.
Everytime someone posts a comment, an accessor method in the model converts all #mention to something like #user:231# where 231 would be the user's id. This way, if the mentioned user changes their username, I can still link & mention him without problems on older comments.
Now, I want to be able to access the body attribute and get the mentions already converted to links. It appears that doing this the MVC way, from within the model is not possible from what I have investigated.
Is there any easy way to do this? I don't wanna have to convert all the mentions on the controller because I think it could lead to repeated code and non-testable code.
Could anyone give me some advice on this?
Thanks!
Parsing the message into a particular format and then re-saving it in the database where it can then be edited at a later date is silly. I'm sorry to be so blunt, but doing it this way is fundamentally broken for one major reason: when a user goes to edit the message later on, they'll see the formatted text unless you format it back. Do you really want to be responsible for doing this?
I would hope not. Because you're a programmer, you're naturally lazy and would like to do things in as few steps as possible.
What I would recommend doing to solve this problem is to parse the message when you display it on the page. Before you go screaming at me that this is computationally intensive if you've got a large amount of hits, hear me out. When it's displayed on the page, you can then cache it like this:
<% cache comment do %>
# code goes here
<% end %>
This will store the final output in whatever cache you've set up with Rails, possibly Memcached or Redis, using a cache key which includes the comment's updated_at timestamp. Pay attention to this, it'll be useful later.
Retrieval from this cache will be faster than parsing it, and will be easier for you than to convert the message back and forth between its versions.
When a comment is updated, the updated_at timestamp will be different and so the new comment will be rendered first, then cached. In Memcached (so I'm told) it will clear the oldest cache key that hasn't been referenced if it needs more memory, thereby cleaning out the older comments.
Wouldn't you end up mangling the original message? Let's say I originally posted:
"Hi! This is me mentioning #bob."
From what I understand, you want to store this as:
"Hi! This is me mentioning #user:1#"
Now, if bob were to change his username to "fred", my message would now look like this:
"Hi! This is me mentioning #fred"
It may be easier to simply store a many-to-many relation between messages and users it mentions. That way, you still can easily see which messages mention a specific user, but you don't need to mangle the original message to do so.
If you need to convert each mention into a link, you could order the entries in the relationship table in the same order that they appear in the message.
maybe this gem help you https://github.com/twitter/twitter-text-rb
First, include Twitter::Autolink module from your class or helper
module ApplicationHelper
include Twitter::Autolink
end
From views, you can call it by :
<%= auto_link("Hi #john_doe, welcome to #ruby") %>
it will generate link to twitter john_doe username and ruby hashtag

Rails app, and need to add tags to a model

I have this quiz rails app linked to an IRC bot who asks questions (yes, on IRC), where I have this Question model which contains, well, questions, answers, hints, and a few more things.
I started with Quiz model (like, say, the special Halloween or Christmas quiz) with a quiz_id in the questions table, then, I told myself, that it would be nice to be able to categorize the questions, so I added a Category model (like, say, Movies or Books), with a category_id in the questions.
Now, my users would like to be able to add a question to one or more quiz, and to assign one or more categories to questions…
So, I've been thinking about removing the Quiz and Category models and replace them with tags, so that, there will be a halloween tag, a movie tag, and a question can have "halloween movie christmas" for tags.
In my searchs, I've seen quite a few ways to include tags like acts_as_taggable, acts_as_taggable_on_steroids or whatever else someone has imagined :-)
Now, I'm wondering what I should do, and so, I'm asking, what you have done, how you've done it, why you did it this way.
acts_as_taggable_on_steroids is older, but it still works, and is still being maintained. Be sure you're visiting the primary repository for it:
http://svn.viney.net.nz/things/rails/plugins/acts_as_taggable_on_steroids/
You can use acts_as_taggable_on_steroids with named_scopes, here's an article that shows how:
Speed Up and named_scope acts_as_taggable_on_steroids Finds
The actual addition to your model is pretty trivial (this is directly from the article above):
named_scope :tagged_with, lambda { |tags| YourModel.find_options_for_find_tagged_with(tags) }
I think Category can easily be replaced by tags, because they are both used to add metadata to a question.
However, I have my doubts about the Quiz model. If you only use the Quiz model to group your questions, it could be possible to replace it with tags. But I think the Quiz model will include more functionality than just grouping alone. For example, score keeping, picking the next question, etc. So I would keep the Quic model intact.
To implement tagging, acts_as_taggable_on_steroids does work, but is a bit old. It would be nice to have a tagging plugin that uses named_scope in the background, as it would make the plugin far more flexible.

Passing parameters as path variables in ruby on rails

I'm still new to ROR, so pardon the simplicity of the question...
So http://www.example.com/controller/:id displays a record in my table, with :id being a number (1,2,3 etc.).
Is there a way I can have :id in the URL be the value of a field in the displayed record? Such that I can have http://www.example.com/controller/record_field? I want to have a human-friendly reference to specific records in my table. I'm sure this must be possible. Do I change something in routes.rb?
Thanks for the help!
The cleanest way is to add a new find method in your model (or simply use the find_by_fieldname Rails gives you in your control). Then you'll have your controller use that method instead of the regular find(params[:id]) to pull your model record.
Check out Ryan B's screencast on this here. It's pretty easy, and he's a good teacher, so you shouldn't have any problems.
I use the excellent rails plugin named friendly_id.
http://github.com/norman/friendly_id/tree/master
That should sort you out nicely. It is well documented too.
Take care around fields that might have modern Greek characters—might need to figure a work around for those.
Jon Smock's solution will work, too. I tend to prefer the following.
class Hamburger << ActiveRecord::Base
#this normally defaults to id
def to_param
name
end
end
class SomeModelController << ApplicationController
def show
#hamburger = Hamburger.find(params[:id]) #still default code
end
end
#goes in some view
This is the <%= link_to "tastiest hamburger ever", url_for(#hamburger) %>.
This is, loosely speaking, an SEO technique (beautiful URLs are also user-friendly and I suggest them to absolutely everyone even if you don't care about SEO, for example on pages behind a login). I have a more extended discussion of Rails SEO, which includes other tips like this, here.
Important tip: You should consider, at design-time, what you are going to do if the param should change. For example, in my hamburger scenario, it is entirely possible that I might rename "Sinfully Delicious Cheeseburger" to "Triple Bypass". If that changes URLs, there are some possible implications, such as breakage of customer links to my website. Accordingly, for production use I usually give these models an immutable permalink attribute which I initialize to be human-meaningful exactly once. If the object later changes, oh well, the URL stays the same. (There are other solutions -- that is just the easiest one.)

Resources