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"
Related
I am building a rails app and the data should be reset every "season" but still kept. In other words, the only data retrieved from any table should be for the current season but if you want to access previous seasons, you can.
We basically need to have multiple instances of the entire database, one for each season.
The clients idea was to export the database at the end of the season and save it, then start fresh. The problem with this is that we can't look at all of the data at once.
The only idea I have is to add a season_id column to every model. But in this scenario, every query would need to have where(season_id: CURRENT_SEASON). Should I just make this a default scope for every model?
Is there a good way to do this?
If you want all the data in a single database, then you'll have to filter it, so you're on the right track. This is totally fine, as data is filtered all the time anyway so it's not a big deal. Also, what you're describing sounds very similar to marking data as archived (where anything not in the current season is essentially archived), something that is very commonly done and usually accomplished (I believe) via setting a boolean flag on every record to true or false in order to hide it, or some equivalent method.
You'll probably want a scope or default_scope, where the main downside of a default_scope is that you must use .unscoped in all places where you want to access data outside of the current season, whereas not using a default scope means you must specify the scope on every call. Default scopes can also seem to get applied in funny places from time to time, and in my experience I prefer to always be explicit about the scopes I'm using (i.e. I therefore never use default_scope), but this is more of a personal preference.
In terms of how to design the database you can either add the boolean flag for every record that tells whether or not that data is in the current season, or as you noted you can include a season_id that will be checked against the current season ID and filter it that way. Either way, a scope of some sort would be a good way to do it.
If using a simple boolean, then either at the end of the current season or the start of the new season, you would have to go and mark any current season records as no longer current. This may require a rake task or something similar to make this convenient, but adds a small amount of maintenance.
If using a season_id plus a constant in the code to indicate which season is current (perhaps via a config file) it would be easier to mark things as the current season since no DB updates will be required from season to season.
[Disclaimer: I'm not familiar with Ruby so I'll just comment from the database perspective.]
The problem with this is that we can't look at all of the data at once.
If you need to keep the old versions accessible, then you should keep them in the same database.
Designing "versioned" (or "temporal" or "historized") data model is something of a black art - let me know how your model looks like now and I might have some suggestions how to "version" it. Things can get especially complicated when handling connections between versioned objects.
In the meantime, take a look at this post, for an example of one such model (unrelated to your domain, but hopefully providing some ideas).
Alternatively, you could try using a DBMS-specific mechanism such as Oracle's flashback query, but this is obviously not available to everybody and may not be suitable for keeping the permanent history...
I have some code like this:
u = ... some user ...
u.clubs << Club.new(:name => "Stu's house of Disco")
With a join model, ClubMemberships that is created automatically via the above.
So far, so good. However, users have an attribute that is kept in memory, not in the database, for security reasons, and when the "<<" method fires, it reloads the user from the database, and thus blows up some code in ClubMemberships#after_create that depends on the user having its secret decoder ring intact, which it does not have when freshly loaded from the database. This seems a bit strange: why is it loading the user when we have a perfectly good one sitting right there? More importantly, is there a way to work around this, or are we going to have to simply create our own add_club method for the user?
Here's what we did. It's an ugly hack, and superior solutions would be welcome.
We created a ##secret_decoder_ring class variable in User with a hash linking the object's ID and the secret, non-DB piece of information, so that if the object in question has been seen and had the secret data filled in, it will be visible in the future.
In reality, we only want the visibility to be the duration of a request processed in Rails, so we have an after_filter that wipes the data in question.
Ugly? Yes, but it does the job for the time being.
I am looking for a Ruby/Rails tool that will help me accomplish the following:
I would like to store the following string, and ones similar to it, in my database. When an object is created, updated, deleted, etc., I want to run through all the strings, check to see if the CRUD event matches the conditions of the string, and if so, run the actions specified.
When a new ticket is created and it's category=6 then notify user 1234 via email
I am planning to create an interface that builds these strings, so it doesn't need to be a human-readable string. If a JSONish structure is better, or a tool has an existing language, that would be fantastic. I'm kinda thinking something along the lines of:
{
object_types: ['ticket'],
events: ['created', 'updated'],
conditions:'ticket.category=6',
actions: 'notify user',
parameters: {
user:1234,
type:'email'
}
}
So basically, I need the following:
Monitor CRUD events - It would be nice if the tool had a way to do this, but Ican use Rails' ModelObservers here if the tool doesn't natively provide it
Find all matching "rules" - This is my major unknown...
Execute the requested method/parameters - Ideally, this would be defined in my Ruby code as classes/methods
Are there any existing tools that I should investigate?
Edit:
Thanks for the responses so far guys! I really appreciate you pointing me down the right paths.
The use case here is that we have many different clients, with many different business rules. For the rules that apply to all clients, I can easily create those in code (using something like Ruleby), but for all of the client-specific ones, I'd like to store them in the database. Ideally, the rule could be written once, stored either in the code, or in the DB, and then run (using something Resque for performance).
At this point, it looks like I'm going to have to roll my own, so any thoughts as to the best way to do that, or any tools I should investigate, would be greatly appreciated.
Thanks again!
I don't think it would be a major thing to write something yourself to do this, I don't know of any gems which would do this (but it would be good if someone wrote one!)
I would tackle the project in the following way, the way I am thinking is that you don't want to do the rule matching at the point the user saves as it may take a while and could interrupt the user experience and/or slow up the server, so...
Use observers to store a record each time a CRUD event happens, or to make things simpler use the Acts as Audited gem which does this for you.
1.5. Use a rake task, running from your crontab to run through the latest changes, perhaps every minute, or you could use Resque which does a good job of handling lots of jobs
Create a set of tables which define the possible rules a user could select from, perhaps something like
Table: Rule
Name
ForEvent (eg. CRUD)
TableInQuestion
FieldOneName
FieldOneCondition etc.
MethodToExecute
You can use a bit of metaprogramming to execute your method and since your method knows your table name and record id then this can be picked up.
Additional Notes
The best way to get going with this is to start simple then work upwards. To get the simple version working first I'd do the following ...
Install acts as audited
Add an additional field to the created audit table, :when_processed
Create yourself a module in your /lib folder called something like processrules which roughly does this
3.1 Grabs all unprocessed audit entries
3.2 Marks them as processed (perhaps make another small audit table at this point to record events happening)
Now create a rules table which simply has a name and condition statement, perhaps add a few sample ones to get going
Name: First | Rule Statement: 'SELECT 1 WHERE table.value = something'
Adapt your new processrules method to execute that sql for each changed entry (perhaps you want to restrict it to just the tables you are working with)
If the rule matched, add it to your log file.
From here you can extrapolate out the additional functionality you need and perhaps ask another question about the metaprogramaming side of dynamically calling methods as this question is quite broad, am more than happy to help further.
I tend to think the best way to go about task processing is to setup the process nicely first so it will work with any server load and situation then plug in the custom bits.
You could make this abstract enough so that you can specify arbitrary conditions and rules, but then you'd be developing a framework/engine as opposed to solving the specific problems of your app.
There's a good chance that using ActiveRecord::Observer will solve your needs, since you can hardcode all the different types of conditions you expect, and then only put the unknowns in the database. For example, say you know that you'll have people watching categories, then create an association like category_watchers, and use the following Observer:
class TicketObserver < ActiveRecord::Observer
# observe :ticket # not needed here, since it's inferred by the class name
def after_create(ticket)
ticket.category.watchers.each{ |user| notify_user(ticket, user) }
end
# def after_update ... (similar)
private
def notify_user(ticket, user)
# lookup the user's stored email preferences
# send an email if appropriate
end
end
If you want to store the email preference along with the fact that the user is watching the category, then use a join model with a flag indicating that.
If you then want to abstract it a step further, I'd suggest using something like treetop to generate the observers themselves, but I'm not convinced that this adds more value than abstracting similar observers in code.
There's a Ruby & Rules Engines SO post that might have some info that you might find useful. There's another Ruby-based rules engine that you may want to explore that as well - Ruleby.
Hope that this helps you start your investigation.
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
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.