ruby-on-railsrubycontrollerpolymorphic-associationsvote-up-buttons

How can I create a controller for polymorphic association using ruby on rails?


I have created a feed_item using this migration

class CreateFeeds < ActiveRecord::Migration
  def change
    create_table :feeds do |t|
      t.integer :item_id
      t.string :item_type
      t.integer :user_id

      t.timestamps
    end
  end
end

class Feed < ActiveRecord::Base
  belongs_to :user
  belongs_to :item, polymorphic: true
end

and I am displaying the content of the feed like

photos = image_tag feed.item.image_url

post = feed.item.text

I trying to add a vote button so the migration for the vote model looks like

class CreateVotes < ActiveRecord::Migration
  def change
    create_table :votes do |t|
      t.integer :votable_id
      t.string :votable_type

      t.timestamps
    end
  end
end


class Vote < ActiveRecord::Base
  belongs_to :votable, polymorphic: true
end

class Post < ActiveRecord::Base
  belongs_to :user
  has_many :votes, as: :votable
end

How do I create the vote controller's create action?

I tried

class VotesController < ApplicationController
  def create
    @votable = find_votable
    @vote = @votable.votes.build(params[:vote])
  end

  private
    def find_votable
      params.each do |name, value|
        if name =~ /(.+)_id$/
          return $1.classify.constantize.find(value)
        end
      end
      nil
    end

    def vote_params
      params.require(:vote).permit(:votable)
    end
end

and got undefined metheod "votes"

also tried

@vote = params[:votable_type].classify.constantize.find(params[:votable_type])

I got undefined metheod "classify"


Solution

  • You wouldn't use a VotesController, you would create votes via other models which have a polymorphic relationship with them. In your example above, you would create them via:

    post.votes
    

    (assuming post was an instance of Post)

    The idea behind polymorphic relationships is a many-to-many relationship with multiple models, so you should be creating any 'votable' records via the source models, in this example, Post.

    For instance, you could create a vote method in your PostController that would create the vote association as I've outlined above and then add the appropriate route to submit your voting form.

    Additionally, your Vote model could also contain other data, depending on how you want to use voting. For instance, if you wanted to track the number of votes a model gets, you could add a count column. In which case, you would create the record as:

    post.votes.count += 1