如何设计警察罚款的数据库?
How to design a database for police fines?
使用 Rails 6 我正在设计一个应用程序来管理警察罚款。一个用户可以违规多篇文章,一篇文章可以有多个字母,一个字母可以有多个逗号。
这是我的实现:
#models/fine.rb
class Fine < ApplicationRecord
has_many :violations
has_many :articles, through: :violations
has_many :letters, through: :violations
has_many :commas, through: :violations
end
#models/article.rb
class Article < ApplicationRecord
has_many :letters
has_many :violations
has_many :fines, through: :violations
end
#models/letter.rb
class Letter < ApplicationRecord
belongs_to :article
has_many :commas
has_many :violations
has_many :fines, through: :violations
end
#models/comma.rb
class Comma < ApplicationRecord
belongs_to :letter
has_many :violations
has_many :fines, through: :violations
end
#models/violation.rb
class Violation < ApplicationRecord
belongs_to :fine
belongs_to :article
belongs_to :letter, optional: true
belongs_to :comma, optional: true
end
当我以 PDF 格式打印罚款时,我需要显示违规行为:文章、字母和逗号。我很难创建一个表格来编译罚款,因为它太深了。我正在使用 Active Admin,当我创建新罚款时,我想关联许多违规行为。
违规示例:
Violation.new
=> #<Violation id: nil, article_id: nil, fine_id: nil, letter_id: nil, comma_id: nil, note: nil, created_at: nil, updated_at: nil>
我如何创建一个表单(使用 Active Admin,它使用 Formtastic)将许多违规行为与罚款相关联?示例表格:
示例(带有示例数据):
Violation.new fine: fine, article: a, letter: a.letters.last, comma: a.letters.second.commas.last
=> #<Violation id: nil, article_id: 124, fine_id: 66, letter_id: 10, comma_id: 4, note: nil, created_at: nil, updated_at: nil>
依我拙见,您的问题相当模糊,仅根据提供的信息很难回答。由于我无法给出肯定能解决您问题的答案,请允许我尝试为您指明正确的方向。
呈现表单
首先让我们了解这里的问题:您正在尝试以嵌套资源形式创建关联记录。
您需要为 Fine
自定义表单,以包含针对每个违规行为的表单。看看how ActiveAdmin handles nested resources。它应该是这样的:
ActiveAdmin.register Fine do
form do |f|
inputs 'Violations' do
f.has_many :violations do |vf|
vf.input :article, as: :select, collection: Article.all
vf.input :letter, as: :select, collection: Letter.all
vf.input :comma, as: :select, collection: Comma.all
end
end
end
end
简而言之,这就是您的问题“我如何创建一个表单(使用 Active Admin,使用 Formtastic)将许多违规与罚款相关联?” .
注意事项
您可能已经注意到,这种方法存在一些问题。
首先,它与您的示例完全不同。您可以使用 as: :check_boxes
轻松更改 Formtastic 的内容以添加复选框,但您会发现复选框没有按您想要的那样组织,缩进很漂亮。据我所知,您无法使用 Formtastic 执行此操作。相反,我相信你必须使用 a partial.
使用 partial 您可以轻松浏览文章,为每篇文章呈现一个复选框,浏览每个人的信件,等等。但是,请记住此表单将要求您 customize the controller 以便它理解每个复选框并创建相应的违规行为。不那么直接。
其次,这里没有强制执行数据完整性。一个人可以 select 一篇文章,另一篇文章的字母和第三篇文章的逗号(顺便说一下,我希望你有一个验证来保护你免受这个)。要让表单动态变化,因此只有给定文章的字母显示在其 selection 之后,对于逗号也是如此,这将需要一些客户端逻辑。如果你问我不值得麻烦。
结论
你的问题远非简单明了,既要回答又要解决。您始终拥有的一个选项是一组自定义路由,用于在 ActiveAdmin 之外管理此类资源。请记住,此类工具的价值取决于它们为您所做的工作。如果你不得不与之抗争,最好让开对方的路。
希望这对您有所帮助。
已解决:
f.has_many :violations do |vf|
vf.input :article, as: :select, include_blank: false, collection: options_for_select(Article.all.map {|article| [article.number, article.id, { :'data-article-id' => article.id, :'data-letters' => article.letters.map(&:id).to_json }]})
vf.input :letter, as: :select, collection: options_for_select(Letter.all.map {|letter| [letter.letter, letter.id, { :'hidden' => true, :'data-letter-id' => letter.id, :'data-article-id' => letter.article.id, :'data-commas' => letter.commas.map(&:id).to_json }]})
vf.input :comma, as: :select, collection: options_for_select(Comma.all.map {|comma| [comma.number, comma.id, { :'hidden' => true, :'data-comma-id' => comma.id, :'data-letter-id' => comma.letter.id }]})
end
还有一点 javascript:
$(document).on('has_many_add:after', '.has_many_container', function (e, fieldset, container) {
selects = fieldset.find('select');
article_select = selects[0];
letter_select = selects[1];
comma_select = selects[2];
$(article_select).on("change", function () {
$(letter_select).prop('selectedIndex', 0);
$(comma_select).prop('selectedIndex', 0);
$("#" + letter_select.id + " option").prop("hidden", true);
$("#" + comma_select.id + " option").prop("hidden", true);
letters = $(this).find(':selected').data('letters');
$.each(letters, function (index, id) {
$("#" + letter_select.id + " option[data-letter-id='" + id + "']").removeAttr("hidden");
});
});
$(letter_select).on("change", function () {
$(comma_select).prop('selectedIndex', 0);
$("#" + comma_select.id + " option").prop("hidden", true);
commas = $(this).find(':selected').data('commas');
$.each(commas, function (index, id) {
$("#" + comma_select.id + " option[data-comma-id='" + id + "']").removeAttr("hidden");
});
});
});
我在选择框中显示了所有文章、字母和逗号。最初隐藏逗号和字母,然后当用户单击文章时,字母的选择框仅显示相关字母。
逗号代码的工作原理与字母相同。
在我可以在 Violation 模型中添加一些验证之后。
使用 Rails 6 我正在设计一个应用程序来管理警察罚款。一个用户可以违规多篇文章,一篇文章可以有多个字母,一个字母可以有多个逗号。
这是我的实现:
#models/fine.rb
class Fine < ApplicationRecord
has_many :violations
has_many :articles, through: :violations
has_many :letters, through: :violations
has_many :commas, through: :violations
end
#models/article.rb
class Article < ApplicationRecord
has_many :letters
has_many :violations
has_many :fines, through: :violations
end
#models/letter.rb
class Letter < ApplicationRecord
belongs_to :article
has_many :commas
has_many :violations
has_many :fines, through: :violations
end
#models/comma.rb
class Comma < ApplicationRecord
belongs_to :letter
has_many :violations
has_many :fines, through: :violations
end
#models/violation.rb
class Violation < ApplicationRecord
belongs_to :fine
belongs_to :article
belongs_to :letter, optional: true
belongs_to :comma, optional: true
end
当我以 PDF 格式打印罚款时,我需要显示违规行为:文章、字母和逗号。我很难创建一个表格来编译罚款,因为它太深了。我正在使用 Active Admin,当我创建新罚款时,我想关联许多违规行为。
违规示例:
Violation.new
=> #<Violation id: nil, article_id: nil, fine_id: nil, letter_id: nil, comma_id: nil, note: nil, created_at: nil, updated_at: nil>
我如何创建一个表单(使用 Active Admin,它使用 Formtastic)将许多违规行为与罚款相关联?示例表格:
示例(带有示例数据):
Violation.new fine: fine, article: a, letter: a.letters.last, comma: a.letters.second.commas.last
=> #<Violation id: nil, article_id: 124, fine_id: 66, letter_id: 10, comma_id: 4, note: nil, created_at: nil, updated_at: nil>
依我拙见,您的问题相当模糊,仅根据提供的信息很难回答。由于我无法给出肯定能解决您问题的答案,请允许我尝试为您指明正确的方向。
呈现表单
首先让我们了解这里的问题:您正在尝试以嵌套资源形式创建关联记录。
您需要为 Fine
自定义表单,以包含针对每个违规行为的表单。看看how ActiveAdmin handles nested resources。它应该是这样的:
ActiveAdmin.register Fine do
form do |f|
inputs 'Violations' do
f.has_many :violations do |vf|
vf.input :article, as: :select, collection: Article.all
vf.input :letter, as: :select, collection: Letter.all
vf.input :comma, as: :select, collection: Comma.all
end
end
end
end
简而言之,这就是您的问题“我如何创建一个表单(使用 Active Admin,使用 Formtastic)将许多违规与罚款相关联?” .
注意事项
您可能已经注意到,这种方法存在一些问题。
首先,它与您的示例完全不同。您可以使用 as: :check_boxes
轻松更改 Formtastic 的内容以添加复选框,但您会发现复选框没有按您想要的那样组织,缩进很漂亮。据我所知,您无法使用 Formtastic 执行此操作。相反,我相信你必须使用 a partial.
使用 partial 您可以轻松浏览文章,为每篇文章呈现一个复选框,浏览每个人的信件,等等。但是,请记住此表单将要求您 customize the controller 以便它理解每个复选框并创建相应的违规行为。不那么直接。
其次,这里没有强制执行数据完整性。一个人可以 select 一篇文章,另一篇文章的字母和第三篇文章的逗号(顺便说一下,我希望你有一个验证来保护你免受这个)。要让表单动态变化,因此只有给定文章的字母显示在其 selection 之后,对于逗号也是如此,这将需要一些客户端逻辑。如果你问我不值得麻烦。
结论
你的问题远非简单明了,既要回答又要解决。您始终拥有的一个选项是一组自定义路由,用于在 ActiveAdmin 之外管理此类资源。请记住,此类工具的价值取决于它们为您所做的工作。如果你不得不与之抗争,最好让开对方的路。
希望这对您有所帮助。
已解决:
f.has_many :violations do |vf|
vf.input :article, as: :select, include_blank: false, collection: options_for_select(Article.all.map {|article| [article.number, article.id, { :'data-article-id' => article.id, :'data-letters' => article.letters.map(&:id).to_json }]})
vf.input :letter, as: :select, collection: options_for_select(Letter.all.map {|letter| [letter.letter, letter.id, { :'hidden' => true, :'data-letter-id' => letter.id, :'data-article-id' => letter.article.id, :'data-commas' => letter.commas.map(&:id).to_json }]})
vf.input :comma, as: :select, collection: options_for_select(Comma.all.map {|comma| [comma.number, comma.id, { :'hidden' => true, :'data-comma-id' => comma.id, :'data-letter-id' => comma.letter.id }]})
end
还有一点 javascript:
$(document).on('has_many_add:after', '.has_many_container', function (e, fieldset, container) {
selects = fieldset.find('select');
article_select = selects[0];
letter_select = selects[1];
comma_select = selects[2];
$(article_select).on("change", function () {
$(letter_select).prop('selectedIndex', 0);
$(comma_select).prop('selectedIndex', 0);
$("#" + letter_select.id + " option").prop("hidden", true);
$("#" + comma_select.id + " option").prop("hidden", true);
letters = $(this).find(':selected').data('letters');
$.each(letters, function (index, id) {
$("#" + letter_select.id + " option[data-letter-id='" + id + "']").removeAttr("hidden");
});
});
$(letter_select).on("change", function () {
$(comma_select).prop('selectedIndex', 0);
$("#" + comma_select.id + " option").prop("hidden", true);
commas = $(this).find(':selected').data('commas');
$.each(commas, function (index, id) {
$("#" + comma_select.id + " option[data-comma-id='" + id + "']").removeAttr("hidden");
});
});
});
我在选择框中显示了所有文章、字母和逗号。最初隐藏逗号和字母,然后当用户单击文章时,字母的选择框仅显示相关字母。 逗号代码的工作原理与字母相同。 在我可以在 Violation 模型中添加一些验证之后。