Search code examples
ruby-on-railsrubypolymorphic-associations

Rails Polymorphic Associations has_one / belongs_to


I have the following situation:

I have a model called "ConfigurationItem".

class ConfigurationItem < ActiveRecord::Base

  belongs_to :contract_asset
  belongs_to :provider

  belongs_to :configuration, polymorphic: true


  validate :name, :contract_asset, presence: true

end

Then I have for the moment two models, "OsConfiguration" and "HardwareConfiguration"

class OsConfiguration < ActiveRecord::Base

  has_one :configuration_item, as: :configuration

end

class HardwareConfiguration < ActiveRecord::Base

  has_one :configuration_item, as: :configuration

end

On my process of creation, I first come to the form of ConfigurationItem. So my question is, how can I create an Os or Hardware Configuration from the ConfigurationItem form. Something like this:

enter image description here

What I tried so far is to route like this:

resources :configuration_items do
    resources :os_configurations
    resources :hardware_configurations
end

But the rest is a bit heavy for me (I'm very new to rails).

Plus, I'm using this gem : https://github.com/codez/dry_crud

edit:

To be more specific, from the configurationItem a form, I can choose an os or hardware configuration. If I choose an os configuration, a modal form will appear with his form. When I save the Os Configuration, I have to set his attribute configuration_item with the previous form, so he's not created yet and I can't access it from the os configuration's controller.

It's like in rails_admin when from a form, you can create and add a new instance of an other model.

Thank's !


Solution

  • Here is my solution, In my ConfigurationItem's list view, I added the dropdown menu

    %ul.dropdown-menu.pull-right
          - ConfigurationItemsController::ITEM_TYPES.keys.each do |type|
            %li= link_to("Add #{type.titleize} Item", new_contract_contract_asset_configuration_item_path(@contract, @contract_asset, type: type))
    

    In my ConfigurationItemsController, I create the configuration with the type of the dropdown.

    ITEM_TYPES = { 'plain'    => nil,
                     'os'       => OsConfiguration,
                     'hardware' => HardwareConfiguration }
    
    before_filter :assign_configuration_type, only: [:new, :create]
    
    def assign_configuration_type
        if type = ITEM_TYPES[params[:type]]
          entry.configuration = type.new
        end
    end
    
    def models_label(plural = true)
        if @configuration_item
          if config = @configuration_item.configuration
            "#{config.class.model_name.human.titleize} Item"
          else
            "Plain Configuration Item"
          end
        else
          super(plural)
        end
    end
    

    In my ConfigurationItem's form view I extend the form with my configuration's field

    - if entry.new_record?
        = hidden_field_tag :type, params[:type]
    
    - if @configuration_item.configuration
        = f.fields_for(:configuration) do |fields|
          = render "#{@configuration_item.configuration.class.model_name.plural}/fields", f: fields
    

    So I choose before the form which configuration I'll have, and not in the form.