Software Development | Ruby on Rails
altered_beast Monitorship

The altered_beast data model shows that Users to Monitor a Topic via a Monitorship. What wasn't clear to me is what that actually meant for the User. I suspect Monitorship is a work in progress for the altered_beast authors.

Data Model

OK, first port of call is the schema. Looks a pretty standard many-to-many link table. The only interesting field is active.

db/schema.rb

create_table "monitorships", :force => true do |t|
  t.integer "user_id"
  t.integer "topic_id"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.boolean "active", :default => true
end

The User and Topic models confirm the many-to-many relationship. Once again the only twist is active, this time in the condition :conditions => {"#{Monitorship.table_name}.active" => true. In other words inactive Monitorships don't count.

app/models/topic.rb

has_many :monitorships, :dependent => :delete_all
has_many :monitoring_users, :through => :monitorships, 
                :source => :user, :conditions => {"#{Monitorship.table_name}.active" => true}

app/models/user.rb

has_many :monitorships, :dependent => :delete_all
has_many :monitored_topics, :through => :monitorships, 
                 :source => :topic, :conditions => {"#{Monitorship.table_name}.active" => true}

active

In fact active is just a soft delete mechanism. The controller sets active to false instead of deleting the record.

app/controllers/monitorships_controller.rb (snippet)

def destroy
  Monitorship.update_all ['active = ?', false], ['user_id = ? and topic_id = ?', current_user.id, params[:topic_id]]
  respond_to do |format| 
    format.html { redirect_to topic_path(params[:forum_id], params[:topic_id]) }
    format.js
  end
end

The model ensures that any existing inactive record is used rather than creating a new one.

app/models/monitorship.rb (snippet)

before_create :check_for_inactive

def check_for_inactive
  monitorship = self.class.find_by_user_id_and_topic_id_and_active(user_id, topic_id, false)
  if monitorship
    monitorship.active = true
    monitorship.save
    false
  end
end

What is not clear to me is why Monitorship needs a soft delete. Normally you'd soft delete something if you want to retain reference integrity. But that doesn't seem to be a factor here.

Start/Stop monitoring

Users can start/stop monitoring a Topic on the Show view for the Topic. Checking the box launches an Ajax call to create the Monitorship; unchecking deletes the Monitorship via Ajax.

app/views/topics/show.html.erb (snippet)

<% @monitoring = logged_in? && !Monitorship.count(:id, 
  :conditions => ['user_id = ? and topic_id = ? and active = ?', current_user.id, @topic.id, true]).zero? %>


<% if logged_in? %>

<% form_tag monitorship_path(@forum, @topic), :style => 'margin-top:0em; float:right;' do -%>
<div>
  <input id="monitor_checkbox" type="checkbox" <%= "checked='checked'" if @monitoring %> 
  onclick="if (this.checked) {<%= remote_function :url => monitorship_path(@forum, @topic) %>} else 
              {<%= remote_function :url => monitorship_path(@forum, @topic), :method => :delete %>}" />
  <label id="monitor_label" for="monitor_checkbox">
  <%= @monitoring ? I18n.t('txt.monitoring_topic', 
      :default => 'Monitoring topic') : I18n.t('txt.monitor_topic', :default => 'Monitor topic') %></label>
  <%= hidden_field_tag '_method', 'delete' if @monitoring %>
  <%= submit_tag :Set, :id => 'monitor_submit' %>
</div>
<% end -%>

<% end -%>

Actually there is a bug here. Perhaps two. The Ajax doesn't seem to work and the "Set" button explodes.

Sweeper

There is also a sweeper class to clean up Monitorships.

app/models/monitorships_sweeper.rb (snippet)

class MonitorshipsSweeper < ActionController::Caching::Sweeper
  observe Monitorship
  
  def after_save(monitorship)
    FileUtils.rm_rf File.join(RAILS_ROOT, 'public', 'users', monitorship.user_id.to_s)
  end
  
  alias_method :after_destroy, :after_save
end

TODO

  • Investigate sweepers.

But so what?

All of the above is understandable ... the only problem is that that is it. As far as I can tell Monitorships don't actually do anything. I suspect they are a work in progress by the authors.