我有两个使用has_and_belongs_to_many
建立了多对多关系的模型。像这样:
class Competition < ActiveRecord::Base
has_and_belongs_to_many :teams
accepts_nested_attributes_for :teams
end
class Team < ActiveRecord::Base
has_and_belongs_to_many :competitions
accepts_nested_attributes_for :competitions
end
如果我们假设我已经在数据库中创建了几个比赛,那么当我创建一个新的团队时,我想使用嵌套表单将新团队与任何相关比赛相关联。
就此而言,我确实需要帮助(已经坚持了好几个小时!)我认为我现有的代码已经以错误的方式解决了这个问题,但我会在以下情况下展示:< / p>
class TeamsController < ApplicationController
def new
@team = Team.new
@competitions.all
@competitions.size.times {@team.competitions.build}
end
def create
@team = Team.new params[:team]
if @team.save
# .. usual if logic on save
end
end
end
而且这个观点......这就是我真正被困住的地方所以我不会同时发布我的努力。我想要的是每个比赛的复选框列表,以便用户可以选择哪些比赛是合适的,而不选择那些不合适的比赛。
我真的很喜欢这个,所以请欣赏任何指向正确的方向:)
答案 0 :(得分:4)
将一起加入模型的has_and_belongs_to_many方法弃用,以支持新的has_many ...:through方法。管理存储在has_and_belongs_to_many关系中的数据非常困难,因为Rails没有提供默认方法,但是:through方法是一流的模型,可以这样操作。
因为它与您的问题有关,您可能希望像这样解决它:
class Competition < ActiveRecord::Base
has_many :participating_teams
has_many :teams,
:through => :participating_teams,
:source => :team
end
class Team < ActiveRecord::Base
has_many :participating_teams
has_many :competitions,
:through => :participating_teams,
:source => :competition
end
class ParticipatingTeam < ActiveRecord::Base
belongs_to :competition
belongs_to :team
end
在创建团队时,您应该构建表单,以便您收到的其中一个参数作为数组发送。通常,这是通过将所有复选框字段指定为相同的名称来完成的,例如'competitions []',然后将每个复选框的值设置为竞争的ID。然后控制器看起来像这样:
class TeamsController < ApplicationController
before_filter :build_team, :only => [ :new, :create ]
def new
@competitions = Competitions.all
end
def create
@team.save!
# .. usual if logic on save
rescue ActiveRecord::RecordInvalid
new
render(:action => 'new')
end
protected
def build_team
# Set default empty hash if this is a new call, or a create call
# with missing params.
params[:team] ||= { }
# NOTE: HashWithIndifferentAccess requires keys to be deleted by String
# name not Symbol.
competition_ids = params[:team].delete('competitions')
@team = Team.new(params[:team])
@team.competitions = Competition.find_all_by_id(competition_ids)
end
end
为复选框列表中的每个元素设置选中或取消选中的状态是通过以下方式完成的:
checked = @team.competitions.include?(competition)
“竞争”是被重复的地方。
您可以轻松地在竞赛列表中添加和删除项目,或者只是重新分配整个列表,Rails将根据它找出新的关系。除了使用update_attributes而不是new之外,您的更新方法看起来与新方法不同。