【问题标题】:Access another models attributes through has_many通过 has_many 访问其他模型属性
【发布时间】:2018-04-19 16:57:52
【问题描述】:

我希望能够在视图中以这种方式调用另一个表中的值。

<%= @team.r1.players.full_name %>
<%= @team.r2.players.full_name %>
...
<%= @team.r2.players.full_name %>

r1r10 是保存玩家 ID 的列。

模型非常简单,看起来像这样。

class Player < ApplicationRecord
  has_and_belongs_to_many :teams
end

class Team < ApplicationRecord
  belongs_to :user
  has_many :players
end

导致的错误是 3:Integer 的未定义方法 `players'。我尝试尝试单数和复数版本来拉它,但发生同样的错误。看起来你可能可以做一个连接表,但这并不理想或做一个 has_many :through 关联。

架构

  create_table "players", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "full_name"
  end

  create_table "team_players", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "teams", force: :cascade do |t|
    t.bigint "user_id"
    t.string "team_name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "r1"
    t.integer "r2"
    t.integer "r3"
    t.integer "r4"
    t.integer "r5"
    t.integer "r6"
    t.integer "r7"
    t.integer "r8"
    t.integer "r9"
    t.integer "r10"
    t.index ["user_id"], name: "index_teams_on_user_id"
  end

我通过这种方式在团队中设置更新/添加球员。

<%= f.collection_select(:r1, Player.all, :id, :full_name , {required: true, include_blank: false}, {class: 'uk-input'}) %>

【问题讨论】:

  • 这个 r1, r2 保存玩家 ID 对我来说似乎很奇怪,但你应该可以做到 @team.players.find(@team.r1)
  • 我应该更清楚。 r1到r10基本上是设置阵容。把它想象成一个名册。我确实尝试了您的方法,并认为它应该有效。 PG::UndefinedColumn: 错误:列 player.team_id 不存在

标签: ruby-on-rails


【解决方案1】:

正如 ConorB 在 cmets 中所说,r1r2 等位似乎很奇怪。如果您想限制团队中的玩家数量,我建议您在代码中执行此操作,而不是在您的数据结构中。

作为说明:在您的 Team 模型中,您说:

class Team < ApplicationRecord
  belongs_to :user
  has_many :players
end

根据docs

has_many 关联表示与另一个模型的一对多连接。

这不是你的情况。你在TeamPlayer 之间有一个多对多的基数。因此,在您的情况下,使用 has_many 而不使用 through 是一个错误。

你应该拥有的是:

class Player < ApplicationRecord
  has_many :team_players
  has_many :teams, through: :team_players
end

class Team < ApplicationRecord
  has_many :team_players
  has_many :players, through: :team_players
end

class TeamPlayer < ApplicationRecord
  belongs_to :team
  belongs_to :player
end

然后做:

<% @team.players.each do |player| %>
  <%= player.full_name %> 
<% end %>

可以决定使用has_and_belongs_to_many,在这种情况下,您需要teams_players 表,但不需要TeamPlayer 模型。 (就个人而言,我从不使用 HABTM,但这纯粹是个人喜好。)请参阅guide 了解更多信息。

【讨论】:

  • 更新了架构以提高清晰度。它还显示了我如何将球员安排到名单上。如果您需要控制器的任何部分,请告诉我,因为添加附加模型会导致一些问题。我没有与设置结婚,但我做 r1...r10 因为我将根据它进行计算(每个 r 的计算不同)。
  • team_players 没有任何id 字段用于Team 和/或Player
  • 跳过额外的模型和表并将它们全部放入数组[0..9]然后调用索引怎么样?我让用户按照他们喜欢的顺序设置他们的播放器。然后根据该订单运行计算并比较结果。
  • 当然,你可以使用数组。这对我来说听起来有点可怕,但你可以做到。如果我是你,我会在 TeamPlayers 上添加一个 order 列(或类似的),并按照我最初的建议使用 has_many through
猜你喜欢
  • 1970-01-01
  • 2019-08-27
  • 2022-08-19
  • 1970-01-01
  • 2015-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多