Bw00d Bw00d - 3 months ago 15x
Ruby Question

Creating Submodels in Rails

Hi I have a rails association question. I am building an equipment management app and I am having trouble determining the design of the model associations.

So a user can create an Asset which has :make, :model, :year, :location, and other common attributes including :asset_type. The asset type could be a number of different types of equipment such as dozer, bus, engine, excavator, tender, etc.

I had considered using STI but the asset types do not share the same attributes. What I am leaning towards is making a separate model for each asset type that would belong_to :asset and then accept_nested_params for each asset type in the Asset model so that I can create them in the same form using javascript to show an asset_type partial once the user chooses :asset_type from a select field. Then to access it I would need to do something like:

def show
@asset = Asset.find(params[:id)
@asset_type = @asset.asset_type.classify.constantize.find(params[])

This feels wrong to me. It seems to me that this would be very common situation and maybe I am just missing something very obvious.

Any advice is appreciated.


I don't think the following code would work because constantize doesn't actually take any arguments (source).

  @asset_type = @asset.asset_type.classify.constantize(find[])

If you're defining @asset.asset_type from user input, I wouldn't advise using classify.constantize because there's vulnerability to code injection.

But if asset_type is limited to a few pre-defined values and you have corresponding classes for each asset_type, it should be a workable approach

# in models/asset.rb   
   validates :asset_type, :inclusion=> { :in => ["bulldozer", "firetruck"] }
   def asset_type_object

# assuming Bulldozer and Firetruck classes are also defined

# in the controller
  @asset_type = @asset.asset_type_object

Note that I've also replaced your .constantize(find[]) with .constantize.find_by(asset_id: This is because it doesn't make sense to find a AssetType which has the same primary key as an Asset. You should use foreign keys for associations.