如何创建复杂的嵌套 - >属于对象?

时间:2017-03-02 23:15:30

标签: ruby-on-rails ruby

我正在构建一个表单,用户应该可以使用字段创建模板。但是,他们也应该能够同时创建一个Collection belongs_to Fieldtemplates: id, name template_fields: id, template_id, collection_id, field_name collections: id, name collection_values: id, collection_id, value

到目前为止看起来像这样:

表格

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

模型

模板

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

模板字段

class Collection < ActiveRecord::Base
  has_many :collection_values
end

集合

class CollectionValue < ActiveRecord::Base
  belongs_to :collection
end

CollectionValue

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

如何创建这些对象?我如何在控制器中进行此操作?

我能想到的唯一方法是将其创建为嵌套关联(即使Collection不是一个真正的嵌套属性),也可以在模板之前创建集合,并以某种方式将每个Field链接到每个Collection。创建

控制器

from selenium import webdriver
import csv

keyword = ['script']

driver = webdriver.Chrome(executable_path=r'C:\Users\Jacob\PycharmProjects\Testing\chromedriver_win32\chromedriver.exe')
html = driver.page_source

with open('listofwebsites.csv', 'r') as f:
    csv_f = csv.reader(f, lineterminator='\n')
    for line in f:
        strdomain = line.strip()
        if '.nl' in strdomain:
            try:
                driver.get(strdomain)
                for searchstring in keyword:
                    if searchstring.lower() in html.lower():
                        print (strdomain, keyword, 'found')
                    else:
                        print (strdomain, keyword, 'not found!')

            except strdomain.HTTPError:
                print (strdomain, 'HTTP ERROR')

            except strdomain.URLError:
                print (strdomain, 'URL ERROR')

            except strdomain.socket.error:
                print (strdomain, 'SOCKET ERROR')

            except strdomain.ssl.CertificateError:
                print (strdomain, 'SSL Certificate ERROR')    
f.close()

3 个答案:

答案 0 :(得分:5)

我认为您需要将这些关系添加到模型has_many :throughhas_one :through,以便将collectioncollection_valuestemplate相关联,然后修改您的template.rb包括:

has_one :collection, through: :template_fields

上面的一行假设一个模板只有一个集合

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

您还需要修改控制器中的template_params以包含collection_attributescollection_values_attributes

要获得更详细的实施,您的template_model将如下所示

模板

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

答案 1 :(得分:4)

根据您的要求,您可能有:

class CollectionValue < ActiveRecord::Base
  belongs_to :collection
end

class Collection < ActiveRecord::Base
  has_many :collection_values
  accepts_nested_attributes_for :collection_values
end

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

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

这将使以下代码有效:

Template.create name: 'template_name',
  template_fields_attributes: [
    {name: 'field_name', collection_attributes:
      {name: 'collection_name', collection_values_attributes: [
        {name: 'col_value_1'},
        {name: 'col_value_2'}
      ]}
    }
  ]

您可以在rails控制台中试用它。此示例将创建所有记录,因为它不包含任何ID。它在TemplateController#create

中的工作方式相同

您可以更好地阅读和理解accepts_nested_attributes_for

答案 2 :(得分:0)

这可以做到但是没有好办法做到这一点。它需要在很大程度上操纵params并且非常复杂/紧密耦合。在保存表单之前选择使用AJAX创建collection