4

I am putting together an app that allows users to make posts. Each post will have a type (image, video, link, text) with both similar and unique variables. I want to submit these through different forms in a "composer" that's available throughout the site.

Here is the post model, Gallery:

class Gallery < ActiveRecord::Base
    attr_accessible :name, :asset
    has_attached_file :asset, :styles => { :small => '160x120#', :medium => "500x", :thumb => "300x200#" }
    belongs_to :user
    has_many :likes
    validates :user_id, presence: true
    validates :type, presence: true
    validates :name, presence: true, length: { maximum: 140, minimum: 1 }
end

I was thinking of using Single Table Inheritance, like this:

class Image < Gallery
end

class Link < Gallery
end

class Video < Gallery
end

class Text < Gallery
end

But I'm not achieving the result I want. For one, I'd like to use the methods in my Gallery controller, such as:

# galleries_controller.rb
def like 
    @gallery = Gallery.find(params[:id])
    @like = @gallery.likes.build(:user_id => current_user.id)
    respond_to do |format|
        if @like.save
        format.html { redirect_to @gallery }
        format.js
    end
end

end

Moreover, I want to create a "publisher" form that contains a form for each post type and lets you create any kind of post.

How would you approach this? I'm new to Rails and I want to take advantage of all the conveniences it offers. Much appreciated!

2 Answers2

0

I would make Gallery an abstract class and each sub class have a seperate db table. This will allow the sub classes to have unique attributes as well as shared ones.

class Gallery < ActiveRecord::Base
  self.abstract_class = true # very important
  .
  .
end

I would make the gallery controller polymorphic:

class GalleriessController < ApplicationController
  before_filter :find_gallery

  private

  def find_gallery
    @klass = params[:gallery_type].capitalize.constantize
    @gallery = @klass.find(params[:gallery_id])
  end
end

Views:

You can use form_for @gallery but it will need a little bit of massaging to work with the polymorphic controller above. It will need to submit a gallery_type and gallery_id parameters instead of just an id. You could modify form_for's :url param to do this or with hidden_fields. Inside the form_for you could use partials, one for each sub class.

Routes:

You can define a regular resource like so: resources :galleries You will need, however to make the id parameter to be gallery_id (and also always pass the galley_type param). Check this: Changing the id parameter in Rails routing

(Possible) conclusion:

Sometimes fancy polymorphic stuff will work out well but in other cases a more simple brute-force approach might be better meaning: have a controller for each sub-class. It depends on the situation. If you end up doing too much stuff that the Rails framework does not give you for free maybe it's better to think of another approach.

Community
  • 1
  • 1
Yoni Baciu
  • 2,667
  • 1
  • 22
  • 28
0

I had a similar scenario, and after looking for a nice way of implementing it, I found this gem which I'm using:

https://github.com/hzamani/acts_as_relation

It uses a polymorphic has_one association to simulate a multi-table inheritance, so in your case you could do the following:

class Gallery < ActiveRecord::Base
  acts_as_superclass
  ...
end

class Image < ActiveRecord::Base
  acts_as :gallery
  ...
end

class Link < ActiveRecord::Base
  acts_as :gallery
  ...
end

I hope this helps you. Cheers!

bigardone
  • 174
  • 1
  • 10