Redacted On A Feedback Loop

This post is a little more of a rant than I usually make, but I think its warranted. If you don’t know what a feedback loop is, read here.

I’m not sure who thinks its a good idea to replace all instances of an email addresses in a feedback loop with [redacted]@feedbackloopcompany.com, but it is of no help to anyone. An argument can be made for protecting the identity of the recipient, but that argument holds little weight because there is little the sender can do about it.

If a sender needs to go through the authorization process of a larger recipient domain (like AOL, Yahoo!, or Excite for example) where their IP reputation is checked and their history is checked, etc. then why should there still be restrictions placed on the information going between the two domains (you as the sender and them as the recipient domains). I am aware that the draft specification allow the operating domain for the feedback loop to keep the identity private of the user clicking the “Report SPAM” button, but that forces the sending domains to use tactics to circumvent this to keep their reputation up.

Therefore I believe that if a sending company has verified their feedback loop address, they should be able to see which recipient reported their email as “Junk”. Get rid of the redacted and leave the email address intact.

Posted in Mail. Tags: , . 1 Comment »

Shortcut Notation in Rails Callbacks

As I have spent the last few weeks/months learning Ruby and Rails, I have grown to love it more and more. The ease of use and the high learning curve make is fantastic for people like me who aren’t developers by nature.

I have recently come across a scenario in Rails that there is not yet a shortcut for. If you have a method that you want to execute in a few different callbacks, there is no shortcut for it. ie, I have the following:

  after_create   :methodFoo
  after_save     :methodFoo
  after_destroy  :methodFoo

I would like to be able to write this as:

 after_create, after_save, after_destroy => :methodFoo

This would obviously only work if the callbacks were then treated as arrays of functions and each time a callback was found in the model, the method was pushed onto the array.

Posted in Rails. Tags: . No Comments »

Adding An Average Column To A Model

Using Ruby on Rails is all about what people find to be common uses. These items then become part of the core system. An example of this is counter_cache. For more information on this, I suggest checking out the Railscast on it here.

A little more of an edge case is if you want a column that rather than counting totals, its calculates an average. To me this is just common enough to require a HOWTO and not common enough to be in the core rails system. Hence here is my HOWTO.

Context: Let’s use an example similar to Yelp where there is a business and each business gets reviewed. The review count is handled by the counter_cache so that column already exists in our database.

| reviews_count | INT(11)      | YES  |     | 0       |                |

The trick here is that every review also has a rating of the business being reviewed. So we are going to use this rating column from the reviews table to calculate the average rating of a business.

First thing we need to do is create the migration:

beacon:test elubow$ script/generate migration add_average_rating_to_business
      exists  db/migrate
      create  db/migrate/20090811135219_add_average_rating_to_business.rb

Edit the migration file to look like this (Note: I know the precision here is 2 when the idea is to not go greater than 5, but MySQL requires precision to be >= scale):

class AddAverageRatingToBusiness < ActiveRecord::Migration
  def self.up
    add_column :businesses, :average_rating, :decimal,  :precision => 4, :scale => 2
  end

  def self.down
    remove_column :businesses, :average_rating
  end
end
beacon:site elubow$ rake db:migrate
(in /Users/elubow/Sites/site)
==  AddAverageRatingToBusiness: migrating =====================================
-- add_column(:businesses, :average_rating, :decimal, {:scale=>4, :precision=>2})
   -> 0.7018s
==  AddAverageRatingToBusiness: migrated (0.7021s) ============================

Now we are going to use the after_save callback hook. We are using after_save because we want the current change to be entered into the database before we make any calculations. In our reviews model, we are going to the following lines:

  after_create   :update_business_average_rating
  after_save     :update_business_average_rating
  after_destroy  :update_business_average_rating

  def update_business_average_rating
    average_rating = Review.average(:rating, :conditions => [ 'business_id = ?', business_id ] )
    business = Business.find(:first, business_id)
    business.average_rating = average_rating
    business.save
  end

Let’s walk through this line by line (Note: The business ID and actual ratings will be different based on your data). First, we grab the average rating from every review of that business. What I would like to note is that by default since it is a callback, the review just added is automagically passed into the method. That is how we are able to access the business_id both to find the average of all the reviews of that business, but to also find the business record to update the average_rating attribute.

The method above causes the following SQL to execute:

SELECT avg(`reviews`.rating) AS avg_rating FROM `reviews` WHERE (business_id = 1)

The next line finds the record of the business and updates it with the newly calculated average rating. The resulting executed SQL will be this:

UPDATE `businesses` SET `average_rating` = 3.0, `updated_at` = '2009-08-13 22:08:55' WHERE `id` = 1

Now that we’re done adding the column and calculating its value, don’t forget to add it to your view. A simple display should do just fine.

< %=h @business.average_rating %>
Posted in Rails. Tags: . No Comments »

Checking Roles in Views Using RoleRequirement

One of the rails projects I am working on is using the RoleRequirement plugin. This is a great plugin for seamless integration of roles into the controller level, but there wasn’t really much documentation on integrating this into the views themselves. So I figured I would put this little gem out there which has done wonders for the DRYness and cleanliness of my code.

For instance, the code below checks whether or not the current user has the admin role. If they do, it prints the admin menu (in my case I use a partial for this).

< % if current_user.has_role?('admin') %>
<!-- Begin Admin Panel -->
<h2>admin</h2>
< %= render :partial => '/layouts/admin' %>
<!-- End Admin Panel -->
< % end %>

The great thing is that (although it might be a little unclean), you can chain some conditionals here to show the appropriate menu items based on a users role(s). This is powerful because a user< ->role relationship is a HABTM (Has And Belongs To Many) relationship.

Posted in Rails. Tags: . 2 Comments »