Ruby on Rails -- 保存和更新连接表中的属性有很多 =>通过 [英] Ruby on Rails -- Saving and updating an attribute in a join table with has many => through

查看:50
本文介绍了Ruby on Rails -- 保存和更新连接表中的属性有很多 =>通过的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了简化事情,我有 3 个表:

has_many :abilities, 通过 => :stats

能力

has_many :people, through => :stats

统计数据

属于:人

belongs_to :能力

Stats 有一个名为评级"的额外属性.

我想做的是制作一个编辑人员表格,它总是列出数据库中当前的所有能力,并让我为每个人分配一个等级.

就我的一生而言,我不知道该怎么做.在使用以下内容创建新用户时,我设法使其正常工作:

(来自人员控制器)

def new@character = Character.new@abilities = 能力.all@abilities.each 做 |能力|@person.stats.build(:ability_id => ability.id )结尾结尾从人的形式:<% for @ability in @abilities do %><%= fields_for "person[stats_attributes]" do |t|%><div class="field"><%= t.label @ability.name %><%= t.hidden_​​field :ability_id, :value =>@ability.id, :index =>零%><%= t.text_field :rating, :index =>零%>

<%结束%><%结束%>

这成功地为我提供了一个带有评级框的能力列表,如果我是新用户,我可以保存它们.

问题是,如果我然后加载编辑表单(使用相同的表单部分),它不会带回评级,如果我保存,即使评级完全相同,它也会在stats 表,而不是更新它.

我意识到我是一个糟糕的程序员,我可能以错误的方式做这件事,但是我如何获得编辑表单以回忆分配给该用户的每个能力的当前评级,其次我如何获得它如果人与能力的组合已经存在,如何更新而不是复制它?

解决方案

不应该是

字符has_many :统计has_many :能力,通过=>:统计能力has_many :统计has_many :字符,通过 =>:统计统计归属地:字符归属地:能力

?

另外,是人物还是人物?你对两者都有不同的指称.(我将在我的回答中使用 Character)

我认为您已经违反了我将尝试制作我的架构的简化版本以试图说明问题,但相反,通过搞砸使事情变得更加复杂并混淆问题,因此它不会没有意义"综合症.无论如何,我可以看到一些问题:

1) 首先,您要在角色创建后立即为其添加所有可能的能力.这很愚蠢 - 默认情况下,他们应该从没有能力开始,然后您为他们确实拥有的那些创建连接表记录(统计数据)(通过勾选表单中的复选框).

2) 像这样操作连接记录的一种简单方法是利用 has_many :abilities 宏为您提供的ability_ids="方法 - 在 api http://railsbrain.com/api/rails-2.3.2/doc/index.html?a=M001885&name=has_many

换句话说,如果你说

@character.ability_ids = [1,12,30]

然后将在该角色与能力 1、12 和 30 之间建立连接,并删除该角色与能力之间的任何其他连接不在上述列表中.将此与以 [] 结尾的表单字段名称将其值放入数组的事实相结合,您可以执行以下操作:

#controller定义新@character = Character.new@abilities = 能力.all结尾#形式<% @abilities.each 做 |ability|%><div class="field"><%= t.label @ability.name %><%= check_box_tag "character[ability_ids][]" %>

<%结束%>#后续控制器(创建动作)@character = Character.new(params[:character]) #完全标准代码

请注意,这里根本没有提及统计信息.我们指定我们想要的角色和能力之间的关联,并让 rails 处理连接.

To simplify things, I have 3 tables :

Person

has_many :abilities, through => :stats

Ability

has_many :people, through => :stats

Stats

belongs_to :people

belongs_to :abilities

Stats has an extra attribute called 'rating'.

What I'd like to do is make an edit person form that always lists all the abilities currently in the database, and lets me assign each one a rating.

For the life of me, I can't figure out how to do this. I managed to get it to work when creating a new user with something like this:

(from the people controller)

def new
 @character = Character.new
    @abilities = Ability.all
    @abilities.each do |ability|
        @person.stats.build(:ability_id => ability.id )
    end
end

From the people form:

<% for @ability in @abilities do %>
    <%= fields_for "person[stats_attributes]" do |t| %>
 <div class="field">
    <%= t.label @ability.name %>
    <%= t.hidden_field :ability_id, :value => @ability.id, :index => nil %>
    <%= t.text_field :rating, :index => nil %>
  </div>
  <% end %>
  <% end %>

This successfully gives me a list of abilities with ratings boxes next to them, and lets me save them if i'm making a new user.

The problem is that if I then load up the edit form (using the same form partial), it doesn't bring back the ratings, and if I save, even with the exact same ratings, it creates duplicate entries in the stats table, instead of updating it.

I realize I'm a terrible programmer and I'm probably doing this the wrong way, but how do I get the edit form to recall the current ratings assigned to each ability for that user, and secondly how do i get it to update the rating instead of duplicating it if the combination of person and ability already exists?

解决方案

Shouldn't that be

Character
has_many :stats
has_many :abilities, through => :stats

Ability
has_many :stats
has_many :characters, through => :stats

Stat
belongs_to :character
belongs_to :ability

?

Also, is it Person or Character? You refer variously to both. (I'm going to go with Character in my answer)

I think you've fallen foul of the "I'll try to make a simplified version of my schema in order to attempt to illustrate a problem but instead make things more complex and muddle the issue by screwing it up so it doesn't make sense" syndrome. Anyway, there's a couple of issues i can see:

1) first thing is that you're adding all the possible abilities to a character as soon as they're created. This is silly - they should start out with no abilities by default and then you create join table records (stats) for the ones they do have (by ticking checkboxes in the form).

2) A simple way to manipulate join records like this is to leverage the "ability_ids=" method that the has_many :abilities macro gives you - referred to as "collection_ids=" in the api http://railsbrain.com/api/rails-2.3.2/doc/index.html?a=M001885&name=has_many

In other words, if you say

@character.ability_ids = [1,12,30]

then that will make joins between that character and abilities 1, 12 and 30 and delete any other joins between that character and abilities not in the above list. Combine this with the fact that form field names ending in [] put their values into an array, and you can do the following:

#controller
def new
 @character = Character.new
 @abilities = Ability.all
end

#form
<% @abilities.each do |ability| %>
  <div class="field">
    <%= t.label @ability.name %>
    <%= check_box_tag "character[ability_ids][]" %>
  </div>
<% end %>

#subsequent controller (create action)
@character = Character.new(params[:character]) #totally standard code

Notice that there's no mention of stats here at all. We specify the associations we want between characters and abilities and let rails handle the joins.

这篇关于Ruby on Rails -- 保存和更新连接表中的属性有很多 =>通过的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆