Before we begin going through the technique, I suggest you read through the Rate Content design pattern page on UI Patterns.com. That page should give you a little more detail on what I am shooting for. For our purposes, let's focus on the following mechanisms:
* Voting mechanism.
* Display the average rating an item has received.
* Display explanatory comments from users rating an item.
I've left off the three mechanisms below, but they seem like a perfect fit for dashboard-like functionality.
* Show the highest rated items.
* Favor quality items.
* Related items.
In the original post, I wasn't taking into account security on the document that is being rated. Thus, this technique really wouldn't work for most real world situations. To overcome this, I decided to use the concept of stub documents to capture each user's rating of a particular document. This offers several advantages. First, I can easily perform a lookup to see if the user has already rated a given document or not. Second, it allows me to extend the original functionality by allowing for additional information such as comments. Finally, this idea respects the security of the main document, as the average rating is calculated by an agent so that the user never has to have edit access to it. Thus, the flow of the process goes something like this:
1. User clicks a star to define their rating.
2. If desired, pop up a dialog box to capture their comments about why they rated the document as they did.
3. Write a stub document that captures a unique key value that corresponds to main document and user, their rating and comments.
4. Run an agent (that executes with proper authority) to update the main document with the new average rating. This agent will loop through all of its rating documents to determine the average.
At the risk of making this post too long, I am going to break this down step-by-step:
Step 1: Add columns to your view. I created a separate column for each star, since I want to know explicitly which one was clicked. Set the column to be editable and set it to "Display values as icons".
Step 2: The column value checks the current average rating of the document and based on the position of the column determines if it should show the filled or unfilled star.
@If(num_Rating >= 1; "star_red"; "star_open") and so on...
Step 3: Add the code to the InViewEdit event. I've included a bunch of comments to the code so you can follow what is happening. It's here that we first check to see if the user has rated the document previously and decide to allow them to edit that rating or not. I chose to implement this as a flag that you can enable or disable in the code itself for easy demonstration, but you could make this and some of the other options part of the db configuration. If the user hasn't voted yet, the InViewEdit code creates the stub doc, asks them for a comment (if appropriate) and kicks off the update agent.
(Please note I added some line breaks into the code samples. If you want to copy and paste, do so from the sample database)
provided by Julian Robichaux at nsftools.com.
Step 4: Add the agent that updates the main document with the average rating. This agent is called by the InViewEdit code as described above. This agent will take the main document, find all of the stub rating documents based on the UNID of the main doc and then loop through the collection, simply adding the values of the ratings and then dividing by the number of ratings to get the average. This average value is then written back to the main document. Make sure that this agent is set to run with an id that has access to all of the main documents, not as the current user.
provided by Julian Robichaux at nsftools.com.
There are a lot of ways in which you could flush this technique out even more. For example, I added an embedded view to the main document form that is used to show the stub document ratings. This way, when you open a particular content document, you can see in detail who rated the content and why (via their comments). This is a nice way to provide users with real meaning behind the values. I'd be interested in hearing about other ways you might use this functionality as well.
The sample database is available below. You've likely seen this before, as it contains a variety of sample design patterns, some of which I haven't talked about yet. You can switch to the "User Ratings" view by using the selection box in the lower right corner of the main screen. Yes...this database is a bit ugly. I was playing with some different theme ideas and didn't want to make another boring looking Notes app. ;-)
Have fun, let me know what you think and please share with the others if you find a use for this in your company's applications.