在 Rails 中处理多对多辅助视图的正确方法是什么?

发布于 2024-12-12 05:59:26 字数 2393 浏览 0 评论 0原文

我需要在创建/更新表单中的每个字段旁边添加一个选择框,以确定其来源。有一个包含摄影师信息的表,一个包含来源的表,以及一个在它们之间建立多对多关系的表。关系将采用摄影师的 id、该记录中的列(例如,姓氏的“last”)以及该信息来源的 id(表中的数据以非常精细的方式来自不同的来源)。 - 粒度方式)。

在摄影师的创建/更新表单中的每个字段旁边添加选择框以便选择该信息的来源的最佳方法是什么?

我正在使用 Ruby on Rails 3.0.3 和 mysql2 连接器。

现在,这是我必须显示给定列的源代码的片段(不完整,因为它缺少显示列名称的方法):

Source: <%= collection_select("photographers_sources","source_id",Source.all, :id, :name, {:include_blank => 'None'})%><br />

但我不知道如何:

  1. 预选择其 id 匹配多对多表的 source_id
  2. 将该数据发回(source_id)并在数据库中执行关联

我的架构:

ActiveRecord::Schema.define(:version => 0) do

  create_table "photographers", :force => true do |t|
    t.string  "first"
    t.string  "last"
    ...
  end

  create_table "photographers_sources", :force => true do |t|
    t.string  "photographer_column", :limit => 32, :default => "", :null => false
    t.integer "source_id",                                         :null => false
    t.integer "photographer_id",                                   :null => false
    t.string  "extra"
  end

  add_index "photographers_sources", ["photographer_id"], :name => "photographer_id"
  add_index "photographers_sources", ["source_id"], :name => "source_id"

  create_table "sources", :force => true do |t|
    t.string "name"
  end

end

我的型号:

class Photographer < ActiveRecord::Base
  validates :first,  :presence => true
  has_many :photographers_sources, :dependent => :destroy
  has_many :sources, :through => :photographers_sources

  def sourcelist
    PhotographersSource.where(:photographer_id => id)
  end
end

class Source < ActiveRecord::Base
  validates :name,  :presence => true
  has_many :photographers_sources, :dependent => :destroy
  has_many :photographers, :through => :photographers_sources
end

class PhotographersSource < ActiveRecord::Base
  belongs_to :photographer
  belongs_to :source
  validates :photographer_column,  :presence => true
  validates :source_id, :presence => true,
                        :numericality => { :only_integer => true }
  validates :photographer_id, :presence => true,
                        :numericality => { :only_integer => true }
end

I need to add a select box next to each field in a create/update form which establishes its provenance. There is a table with photographer info, a table with sources, and a table establishing a many to many relation between them. A relation would take the id of a photographer, the column in that record (say, "last" for the lastname) and an id for the source where that information came from (the data in the table comes from different sources in a very fine-grained way).

What is the best way of adding a select box next to every field in the create/update form for a photographer so as to select where that info comes from?

I am using Ruby on Rails 3.0.3 with the mysql2 connector.

Right now this is the snippet I have to show a given column's source (incomplete since it is missing a way to show the column name):

Source: <%= collection_select("photographers_sources","source_id",Source.all, :id, :name, {:include_blank => 'None'})%><br />

But I don't know how to:

  1. pre-select the source whose id matches the many-to-many table's source_id
  2. send that data back (column and source_id) and perform the association in the database

My schema:

ActiveRecord::Schema.define(:version => 0) do

  create_table "photographers", :force => true do |t|
    t.string  "first"
    t.string  "last"
    ...
  end

  create_table "photographers_sources", :force => true do |t|
    t.string  "photographer_column", :limit => 32, :default => "", :null => false
    t.integer "source_id",                                         :null => false
    t.integer "photographer_id",                                   :null => false
    t.string  "extra"
  end

  add_index "photographers_sources", ["photographer_id"], :name => "photographer_id"
  add_index "photographers_sources", ["source_id"], :name => "source_id"

  create_table "sources", :force => true do |t|
    t.string "name"
  end

end

My models:

class Photographer < ActiveRecord::Base
  validates :first,  :presence => true
  has_many :photographers_sources, :dependent => :destroy
  has_many :sources, :through => :photographers_sources

  def sourcelist
    PhotographersSource.where(:photographer_id => id)
  end
end

class Source < ActiveRecord::Base
  validates :name,  :presence => true
  has_many :photographers_sources, :dependent => :destroy
  has_many :photographers, :through => :photographers_sources
end

class PhotographersSource < ActiveRecord::Base
  belongs_to :photographer
  belongs_to :source
  validates :photographer_column,  :presence => true
  validates :source_id, :presence => true,
                        :numericality => { :only_integer => true }
  validates :photographer_id, :presence => true,
                        :numericality => { :only_integer => true }
end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酒中人 2024-12-19 05:59:26

我添加了一个带有源选择框的表单部分:

<%
if @photographer.sourcelist.select{|s| s.photographer_column==column}.length != 0
    @id_to_select = @photographer.sourcelist.select{|s| s.photographer_column==column}[0].source_id
else
    @id_to_select = 0
end
%>

Source: <%= collection_select("photographers_sources_plain", column, Source.all, :id, :name, {:include_blank => 'None', :selected => @id_to_select })%><br />

它放置在每个字段旁边,如下所示:

<%= render (:partial => 'source_form', :locals => {:column => 'category'}) %>

您可以将“类别”更改为任何字段名称。我确信一定有更好的方法,但这对我来说已经足够了。

请注意,选择中生成的 name 是“photographers_sources_plain[column]”,因此在我的 update 操作中的控制器中:

params[:photographer][:photographers_sources] = []
plain_sources = params[:photographers_sources_plain]
plain_sources.each do |key, value|
  if value != ""
    params[:photographer][:photographers_sources] << PhotographersSource.new(:photographer_column=>key,:source_id=>value.to_i)
  end
end

需要等效的添加新的动作。再说一遍,我确信一定有更好的方法,但我是 Rails 新手,所以这就是我能做到的。

这很好地处理了一切。希望这对其他人有帮助。

I added a form partial with the select box for the source:

<%
if @photographer.sourcelist.select{|s| s.photographer_column==column}.length != 0
    @id_to_select = @photographer.sourcelist.select{|s| s.photographer_column==column}[0].source_id
else
    @id_to_select = 0
end
%>

Source: <%= collection_select("photographers_sources_plain", column, Source.all, :id, :name, {:include_blank => 'None', :selected => @id_to_select })%><br />

This is placed next to each field like so:

<%= render (:partial => 'source_form', :locals => {:column => 'category'}) %>

You would change "category" to whatever the field name is. I'm sure there must be a better way but that's good enough for me.

Note that the name generated in the select is "photographers_sources_plain[column]" so in the controller I have in the update action:

params[:photographer][:photographers_sources] = []
plain_sources = params[:photographers_sources_plain]
plain_sources.each do |key, value|
  if value != ""
    params[:photographer][:photographers_sources] << PhotographersSource.new(:photographer_column=>key,:source_id=>value.to_i)
  end
end

An equivalent addition is needed for the new action. Once again, I'm sure there must be a better way but I'm new to Rails so this is what I could manage to do.

This takes care of everything pretty well. Hope this helps someone else.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文