Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a complex Nested -> Belongs To object?

I'm building a form where a user should be able to create a template with fields. However they should also be able to create an optional Collection which belongs_to each Field at the same time.

So far it looks like this:

Tables

templates: id, name
template_fields: id, template_id, collection_id, field_name
collections: id, name
collection_values: id, collection_id, value

Models

Template

class Template < ActiveRecord::Base
  has_many :template_fields
  accepts_nested_attributes_for :template_fields
end

Template Fields

class TemplateField < ActiveRecord::Base
  belongs_to :template
  belongs_to :collection
end

Collection

class Collection < ActiveRecord::Base
  has_many :collection_values
end

CollectionValue

class CollectionValue < ActiveRecord::Base
  belongs_to :collection
end

How can I create these objects? How do I go about this in the controller?

The only way I can think of is to create it as a nested association (even though Collection isn't really a nested attribute) or create the Collections before the Templates, and somehow link each Field to each Collection that was created.

Controller

def create
  @template = Template.new(template_params)
  if @template.save
    flash[:notice] = "Template successfully created."
    flash[:color]= "valid"
    redirect_to templates_path
  else
    flash[:notice] = "Form is invalid"
    flash[:color]= "invalid"
    render :new
  end
end

def template_params
  params.require(:template).permit(:id,:name, template_fields_attributes: [:id, :template_id, :field_name, :collection_id, collection_values_attributes: [:value] ])
end
like image 781
Shannon Avatar asked Mar 02 '17 23:03

Shannon


1 Answers

I think you need to add these kind of relationships to your model has_many :through and has_one :through to relate collection and collection_values to template and then modify your template.rb to include:

has_one :collection, through: :template_fields

The line above assumes that one template has only one collection

has_many :collection_values, through: :collection
accepts_nested_attributes_for :template_fields, :collection, :collection_values

You also need to modify the template_params in your controller to include collection_attributes and collection_values_attributes

For a more detailed implementation, your template_model will look like this

Template

class Template < ActiveRecord::Base
  has_many :template_fields
  has_many :collections, through: :template_fields
  has_many :collection_values, through: :collection
  accepts_nested_attributes_for :template_fields, :collections, :collection_values
end
like image 190
user3402754 Avatar answered Sep 21 '22 03:09

user3402754