【问题标题】:How to set foreign key using value from nested form?如何使用嵌套形式的值设置外键?
【发布时间】:2018-08-02 06:12:41
【问题描述】:

我有一个显示 Content 的 Rails 应用程序。每条内容都属于一个Source 和一个Source has_many Contents。每个 Source 由一个 name 和一个 domain 组成。

内容也属于Edition。我的应用程序设置方式是,在创建/编辑 Editions 的表单中,我使用 Cocoon gem 嵌套了 Contents 的表单字段。

内容的嵌套字段包括link 字段。我需要做的是检查 link 与 Sources 表中的各种 domains 并在新创建/编辑的内容上设置相关的 source_id

我在想我可以在editions controller 中设置相关的source_id updatecreate 操作。但是,由于我收到的唯一数据是带有嵌入式contents_attributes 散列的参数散列(它不包含对source_id 的引用,因为source 未在表单中设置),我该如何设置@987654339 @使用表单上提交的“链接”?

这是我在 editions_controller 上的创建和更新操作:

def create
  @edition = Edition.new(edition_params)

  respond_to do |format|
    if @edition.save
      format.html { redirect_to @edition, notice: 'Edition was successfully created.' }
      format.json { render :show, status: :created, location: @edition }
    else
      format.html { render :new }
      format.json { render json: @edition.errors, status: :unprocessable_entity }
    end
  end
end

def update
  respond_to do |format|
    if @edition.update(edition_params)
      format.html { redirect_to @edition, notice: 'Edition was successfully updated.' }
      format.json { render :show, status: :ok, location: @edition }
    else
      format.html { render :edit }
      format.json { render json: @edition.errors, status: :unprocessable_entity }
    end
  end
end

这里是使用的参数:

def edition_params
  params.require(:edition).permit(:date, 
                                  :clicks, 
                                  :product_id,
                                  contents_attributes: [:id,
                                                        :heading,
                                                        :body,
                                                        :link,
                                                        :top_story,
                                                        :section_id,
                                                        :_destroy
                                                       ]
                                 )
end

我应该在带有 source_id 的表单上隐藏输入吗?或者这可以在控制器上完成吗?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-5 nested-forms cocoon-gem


    【解决方案1】:

    如果您在内容表单中设置了link 值,并且您有一个从link 的值确定source 的逻辑,那么您不需要在表单或中设置source_id控制器。

    设置source_id 的最佳位置是在模型中,因此无论您如何创建content 记录(即从版本表单、控制台或其他控制器),它总是被设置。在这种情况下,您不必担心这一点。

    在您的模型中包含这些关联和回调应该可以解决您的目的:

    class Source
      # field :name
      # field :domain
    
      has_many :contents
    
      def self.fetch_from_link(link)
        match_link_with_domains_and_return_source_record
      end
    end
    
    class Edition
      # field :date
      # field :clicks
    
      has_many :contents
      accepts_nested_attributes_for :contents
    end
    
    class Content
      # field :heading
      # field :body
      # field :link
      # field :top_story
    
      belongs_to :source
      belongs_to :edition
    
      before_validation :set_source
    
      private
    
      def set_source
        # Set source *only* if not already set. You can change `||=` to `=` to set it always.
        self.source ||= link && Source.fetch_from_link(link)
      end
    end
    

    【讨论】:

    • 工作就像一个魅力! :D 正如你所说,我最终将||= 替换为=,因为我希望它在链接被编辑时也能正常工作。我不明白的一件事是你为什么在最后一行使用&&self.source ||= link && Source.fetch_from_link(link)?关于这一点,为什么不直接说self.source = Source.fetch_from_link(link)
    • Source.fetch_from_link(link) if link一样,只是更漂亮。当链接为nil 时,您不想遇到错误。
    • 哦,好吧,是不是因为说link && Source.fetch_from_link(link) 会检查两个项目都存在,但只返回最后一个项目,即Source.fetch_from_link(link)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2021-01-22
    • 2023-03-17
    • 1970-01-01
    相关资源
    最近更新 更多