0

I have set up a rails application that uses single table inheritance but I need to have a distinct form for my child classes. The application keeps a collection of indicators of security compromise, such as malicious IP addresses. So I have a class called Indicator which holds most of the information. However, if the indicator is a malware hash I need to collect additional information. So I created another class called MalwareIndicator which inherits from Indicator. Everything is working fine with that.

I wanted my routes to be restful and look nice so I have this in my config/routes.rb file

resources :indicators
resources :malware, :controller => "indicators", :type => "MalwareIndicator"

That works very nicely. I have all these routes that point back to my single controller. But then in the controller I'm not sure how to handle multiple forms. For example, if someone goes to malware/new the Indicators#New function is called and it is able to figure out that the user wants to create a MalwareIndicator. So what must my respond_to block look like in order to send the user to the correct form? Right now it still sends the user to the new indicator form.

  def new
    if params[:type] == "MalwareIndicator"
        @indicator = MalwareIndicator.new
    else
        @indicator = Indicator.new
    end
    @pagename = "New Indicator(s)"

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @indicator }
    end
  end

I feel like I'm pretty close. On the other hand, I might be doing everything wrong so if anyone wants to slap me and say "quit being a dumbass" I would be grateful for that as well.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Kevin Thompson
  • 2,466
  • 4
  • 29
  • 40

2 Answers2

1

I usually try to avoid STI because there are only troubles with that (image third indcator with different attributes and fourth and fifth with more fields and before you realize you end up with huge table where most columns are unused). To answer your question: you can create different new views for different classes and respond like that:

respond_to do |format|
  format.html { render action: "new_#{@indicator.class.to_s.underscore}"   }
  format.json { render json: @indicator }
end

that should render new_indicator.html.erb or new_malware_indicator.html.erb depends on @indicator class.

lisowski.r
  • 3,671
  • 1
  • 19
  • 16
0

I handled it in the view itself. The route entry for malware causes the controller to receive a type parameter and the controller uses that to create an instance of the correct class. In the new.html.erb file I put this at the end:

<%= render :partial => @indicator.class.to_s.downcase %>

So if a MalwareIndicator was created by the controller then @indicator.class.to_s.downcase will return malwareindicator. I have a partial file called _malwareindicator.html.erb which has the correct form in it.

So if I have to create another descendant of the Indicator class I can add another resources entry to the routes file and create a partial called _whateverindicator.html.erb and it should work out OK.

Kevin Thompson
  • 2,466
  • 4
  • 29
  • 40