views:

31

answers:

2

I'm adding a categorization functionality to my app and struggling with it. Objects have many categories through categorizations. I'm trying to intercept the creation of a new categorization, check if theres a similar one, if so, increment it's count, if not, create a new object. Here's what I have so far.

  validate :check_unique

  protected

  def check_unique
    categorization = Categorization.where(:category_id => self.category_id, :categorizable_id => self.categorizable_id, :categorizable_type => self.categorizable_type)
    if categorization.first
      categorization.first.increment(:count)
    end
  end
A: 

I decided to move it out of the model object and put it into the controller method creating the categorization. It now works (Yay!) and here's the code if anyone is interested.

  def add_tag
    object = params[:controller].classify.constantize
    @item = object.find(params[:id])
    @categories = Category.find(params[:category_ids]) 
    @categories.each do |c|
      categorization = @item.categorizations.find(:first, :conditions => "category_id = #{c.id}")
      if categorization
        categorization.increment!(:count)
      else
        @item.categorizations.create(:category_id => c.id, :user_id => current_user.id)
      end
    end
    if @item.save
    current_user.update_attribute(:points, current_user.points + 15) unless @item.categorizations.exists?(:user_id => current_user.id)
      flash[:notice] = "Categories added"
      redirect_to @item
    else
      flash[:notice] = "Error"
      redirect_to 'categorize'
    end
  end
amctammany
+1  A: 

This kind of logic should not exist in the controller. This is really business domain and should be in the model. Here's how you should go about it:

categorization = Categorization.find_or_create_by_category_id_and_categorizable_id_and_categorizable_type(self.category_id, self.categorizable_id, self.categorizable_type)
categorization.increment!(:count)

find_or_create will try to find the category in the DB, and if it doesn't exist, it'll create it. Now just make sure that count defaults to zero, and this code will do what you want. (when initially created the count would be 1, then later it'll increment)

PS: I'm not sure if find_or_create has changed in rails 3. But this is the main idea

Faisal
Alright. That's exactly what I was looking for, I just didn't know how to do it. I really didn't want to put it into any controller action, but it was a quick fix. Thanks mate.
amctammany
glad to see hear that. If this answer helped you, please consider accepting it.
Faisal