gpt4 book ai didi

ruby-on-rails - 使用2个相关模型创建和更新模型

转载 作者:行者123 更新时间:2023-12-04 04:41:04 25 4
gpt4 key购买 nike

我有这个模特

class Book < ActiveRecord::Base
has_many :accountings
has_many :commodities, through: :accountings
end

class Accounting < ActiveRecord::Base
belongs_to :book
belongs_to :commodity
end

class Commodity < ActiveRecord::Base
has_many :accountings
end

我的书的形式是:
<%= form_for(book) do |f| %>
<%= render 'shared/error_messages', object: book %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :commodity_ids %>
<%= f.collection_select :commodity_ids, Commodity.all, :id, :name, {}, {multiple: true} %>
<br />
<%= f.submit class: 'btn btn-primary' %>
<% end %>

在BooksController上:
  def new
@book = Book.new
end

def create
@book = Book.new(book_params)
if @book.save
redirect_to @book
else
render 'new'
end
end

def edit
@book = Book.find(params[:id])
end

def update
@book = Book.find(params[:id])
if @book.update_attributes(book_params)
redirect_to @book
else
render 'edit'
end
end

private

def book_params
params.require(:book).permit(:name, commodity_ids: [])
end

所有这些都很好。并在更新 Accounting时添加和删除 commodity_ids记录。 (1)

现在,我需要添加一个新模型: Company,因为 BookCommodity由所有公司共享,因此 Accounting必须属于 company,并且在所有系统中都不共享。 Accounting变为:
class Accounting < ActiveRecord::Base
belongs_to :book
belongs_to :commodity
belongs_to :company
end
Company模型:
class Company < ActiveRecord::Base
has_many :accountings
end
Accounting不仅仅是商品和书籍(以及公司)之间的关系,它还代表一种商业模型。

这里的约束是:当将新的 Commodity添加到 Book时,则必须为每个 Accounting创建一个新的Company。 (2)

我确实尝试通过Bookcompaniesaccountings关联。但是,它不起作用。即使它不代表业务模型,Book也不在乎公司,我认为Book是链接模型的不错的选择。 (3)

现在,我正在考虑添加一个新模型BookCommodity,该模型通过该模型关联书籍和商品,并在保存此新模型后生成所有Accounting所需的companies记录。 (4)

在添加第五种模型之前,我想问问您是否有更好的方法来管理这些东西?

编辑

在Github上,您可以找到一个demo_finance项目,仅包含本文的代码。它有4个分支:
  • :添加公司模型之前的第一个版本当然可以正常工作。 (1)
  • with_companies :公司模型的分支,以及“会计”模型所需的约束。 (2)这是任何更改的起点。
  • first_attempt :尝试使用 with_companies 分支:(3)。这没用。
  • second_attempt :尝试使用 with_companies 分支:(4)。有用。它在创建时具有用于创建会计的回调,但是在Books#update上需要更多的回调来删除商品。我对这种方法并不完全满意。

  • 此处的关键任务是在书籍中添加或删除商品,并更新会计,就像它在版本(1)(主分支)中一样。

    编辑#2

    我试图做到这一点:
    class Book < ActiveRecord::Base
    has_many :accountings
    has_many :commodity_companies, through: :accountings
    has_many :commodities, through: :commodity_companies
    end

    但这是行不通的。更新时会引发:
    ActiveRecord::HasManyThroughNestedAssociationsAreReadonly
    Cannot modify association 'Book#commodities' because it goes through more than one other association.

    我也尝试这样做:
    class Book < ActiveRecord::Base
    has_many :accountings do
    def build(attributes = {}, &block)
    Company.all.each do |company|
    @association.build(attributes.merge(company_id: company.id), &block)
    end
    end
    end
    has_many :commodities, through: :accountings
    end

    但是,在带有commodity_ids=的更新书上不会调用此生成操作。

    最佳答案

    这只是一个解决方案。之后,我对您的问题有了深刻的了解。我要说的是,您必须将所有公司以帐簿形式添加为多种选择。我知道也许现在它会脱离您的想法,但是您必须遵循有关 rails 流动的问题。您已经说过,您想通过基于公司的会计核算来更新商品,然后想要自动更新数据,但是您的代码不提供执行这些操作的功能。

    选项1

    这是建议:

    Controller

    添加新的强参数

    def book_params
    params.require(:book).permit(:name, commodity_ids: [], company_ids: [])
    end

    模型

    您需要修改一些关联
    class Book < ActiveRecord::Base
    has_many :accountings
    has_many :commodities, through: :accountings
    has_many :companies, through: :accountings
    end

    class Accounting < ActiveRecord::Base
    belongs_to :book
    belongs_to :commodity
    belongs_to :company
    end

    class Commodity < ActiveRecord::Base
    has_many :accountings
    has_many :companies, through: :accountings
    has_many :books, through: :accountings
    end

    class Company < ActiveRecord::Base
    has_many :accountings
    has_many :books through: :accountings
    has_many :commodites through: :accountings
    end

    查看

    您可以选择所有公司,以便用户不需要选择选项(可选)
    <%= form_for(book) do |f| %>
    <%= render 'shared/error_messages', object: book %>
    <%= f.label :company_ids %>
    <%= f.collection_select :company_ids, Company.all, :id, :name, {:selected: Company.all.map(&:id)}, {multiple: true} %>
    <%= f.label :name %>
    <%= f.text_field :name %>
    <%= f.label :commodity_ids %>
    <%= f.collection_select :commodity_ids, Commodity.all, :id, :name, {}, {multiple: true} %>
    <br />
    <%= f.submit class: 'btn btn-primary' %>
    <% end %>

    另外,请尝试不要创建 BookCommodity来创建 Accounting,因为 BookCommodity等于 Accounting
    选项2

    对于另一个选项,如果您不想在表单中显示,则可以在before_save回调中添加模型。这只是
    before_save :set_companies

    def set_companies
    self.company_ids = Company.all.map(&:id)
    end

    结论:

    这些都各有利弊。在第一个选项中,用户可以选择公司,但用户需要首先选择公司。最后,用户没有选择公司,但是当用户想要更新书籍或商品的公司时,他会遇到困难。与往常一样,我希望您使用第一种方式,因为用户将易于编辑。就这样。希望对您有所帮助。

    关于ruby-on-rails - 使用2个相关模型创建和更新模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32752971/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com