【问题标题】:ActiveRecord::RecordInvalid: Validation failed: Team must existActiveRecord::RecordInvalid:验证失败:团队必须存在
【发布时间】:2017-05-11 14:19:59
【问题描述】:

我在运行rake db:seed 时收到错误ActiveRecord::RecordInvalid: Validation failed: Team must exist

我正在尝试在玩家和团队之间建立关联。我有数据要播种到我的数据库中,但我不确定错误是由我如何设置关联或我如何构建数据引起的。

Team 是父级,Player 是子级。

型号

# player.rb
class Player < ApplicationRecord
  belongs_to :team, class_name: "Player"

  validates :team, presence: true, allow_nil: true
end


# team.rb
class Team < ApplicationRecord
  has_many :players
end

路线

# routes.rb
Rails.application.routes.draw do
  get 'welcome/index'

  resources :players

  resources :teams do
    resources :players
  end

  root 'welcome#index'
end

迁移

# create_players.rb
class CreatePlayers < ActiveRecord::Migration[5.1]
  def change
    create_table :players do |t|
      t.belongs_to :team, index: true

      t.string :name

      t.string :shoots
      t.string :catches
      t.string :position
      t.string :pos
      t.integer :number
      t.integer :gp
      t.integer :goals
      t.integer :assists
      t.integer :points
      t.integer :pim
      t.integer :plusMinus
      t.decimal :gaa
      t.integer :svs

      t.integer :team_id
      t.references :teams

      t.timestamps
    end
  end
end


# create_teams.rb
class CreateTeams < ActiveRecord::Migration[5.1]
  def change
    create_table :teams do |t|

      t.string :team_name
      t.string :abr
      t.string :sm_logo
      t.string :lg_logo

      t.integer :player_id

      t.timestamps
    end
  end
end

尝试播种的数据示例

# Player data
players = Player.create!({
  "name": "Some Guy",
  "shoots": "Right",
  "position": "Forward",
  "pos": "F",
  "number": 8,
  "gp": 15,
  "goals": 12,
  "assists": 6,
  "points": 18,
  "pim": 12,
  "plusMinus": 7,
  "team_id": 1
})


# Team data
teams = Team.create!({
  "team_name": "A Team",
  "abr": "ATM"
})

宝石文件

source 'https://rubygems.org'

gem 'rails', '~> 5.1.0'
gem 'pg', '~> 0.18'
gem 'puma', '~> 3.7'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

#Bootstrap 4 and Tether gems
gem 'bootstrap', '~> 4.0.0.alpha6'
gem 'rails-assets-tether', '>= 1.3.3', source: 'https://rails-assets.org'

gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.5'
gem 'rails-ujs', '~> 0.1.0'
gem 'jquery-rails'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

【问题讨论】:

    标签: postgresql activerecord ruby-on-rails-5


    【解决方案1】:

    首先你需要创建团队:

    team = Team.create!({ team_name: "A Team", abr: "ATM" })
    

    请注意,我将hash 传递给create! 方法,而不是像您在示例中那样使用散列的array

    然后您可以创建玩家并将其添加到团队中:

    player = Player.create!({
      "name": "Some Guy",
      "shoots": "Right",
      "position": "Forward",
      "pos": "F",
      "number": 8,
      "gp": 15,
      "goals": 12,
      "assists": 6,
      "points": 18,
      "pim": 12,
      "plusMinus": 7,
      "team": team
    })
    

    请注意,我可以将 team 对象传递给 Player.create! 方法。这将使玩家与团队相关联。否则你可以只使用id。

    player = Player.create!({
      ...
      team_id: team.id
    })
    

    player = Player.create!({
      ...
      team_id: 1
    })
    

    省略号(3 个点)应替换为如上所示的实际属性。

    更新

    create_players.rb 迁移中删除以下行:

      t.integer :teams_id
      t.references :teams
    

    create_teams.rb 迁移中删除以下行:

      t.integer :player__id
    

    写入t.belongs_to :player 产生与写入t.integer :player_id 相同的结果。它只是 Rails 的语法糖。写t.belongs_to :playert.references :player 只是比写t.integer :player_id 更清楚一点

    我假设您希望一名球员属于一支球队(一对多的关系)。如果您认为一个玩家可能属于多个团队(通常情况并非如此,但我不知道您正在开发什么),那么您需要在 Google 上搜索 Rails 多对多关系。

    【讨论】:

    • 谢谢@Greg 答案,这已经解决了问题,但我现在收到错误:ArgumentError: wrong number of arguments (given 5, expected 0..1) 这是在将播放器数据更新为种子到:player = Player.create!({ ... team_id: 1 }) 并将播放器迁移更新到@之后987654341@ 从 teams_id 复数。我已经搜索了有关新错误的答案,但我还是没有找到答案。
    • 省略号(3 个点)只是所有其他属性的占位符。我希望你没有在编辑器中直接输入player = Player.create!({ ... team_id: 1 })
    • 我还注意到您的create_teams.rb 迁移中有t.integer :player__id。它应该有一个下划线,而不是 2。我希望这只是 Stack Overflow 上的一个错字。其次,您在此迁移中不需要该行。此外,您应该从同一迁移中删除 t.belongs_to :player, index: trueplayer 应该属于team,但您不需要在teams 表上为玩家添加一列。这是一对多的关系。
    • hahaha @Greg 回答是的,我意识到... 是为了简洁,所以不,我没有按字面意思写:) 我已经编辑了我的代码和问题,并提出了新的建议更改,但我再次我得到了同样的错误wrong number of arguments ... 错误
    • 我也更新了我的答案。请确保您传递的是这样的散列 player = Player.create!({ ... team_id: 1 }) 而不是包裹在这样的数组中的散列 player = Player.create!([{ ... team_id: 1 }])。注意方括号[ { ... } ]?删除它们。它应该只是像这样的哈希{ ... }
    【解决方案2】:

    @Greg 回答感谢您的帮助。我现在找到了一个可行的解决方案。

    为了解决这个问题,我恢复到以前的提交并决定遵循以下文章: https://www.learneroo.com/modules/137/nodes/767

    我完成的工作代码如下所示:

    型号

    # Team model
    class Team < ApplicationRecord
      has_many :players
    end
    
    # Player model
    class Player < ApplicationRecord
      belongs_to :team
    end
    

    迁移

    # create_teams.rb
    class CreateTeams < ActiveRecord::Migration[5.1]
      def change
        create_table :teams do |t|
    
          t.string :team_name
          t.string :abr
    
          t.timestamps
        end
      end
    end
    
    # create_players.rb
    class CreatePlayers < ActiveRecord::Migration[5.1]
      def change
        create_table :players do |t|
          t.string :name
          t.string :shoots
          t.string :catches
          t.string :position
          t.string :posAbr
          t.string :abr
          t.integer :number
          t.integer :gp
          t.integer :goals
          t.integer :assists
          t.integer :points
          t.integer :pim
          t.integer :plusMinus
          t.decimal :gaa
          t.integer :svs
    
          t.timestamps
        end
      end
    end
    
    # add_team_id_to_players.rb
    class AddTeamIdToPlayers < ActiveRecord::Migration[5.1]
      def change
        add_column :players, :team_id, :integer
      end
    end
    

    种子数据示例

    # Team data
    teams = Team.create([{
      "team_name": "A Team",
      "abr": "ATM"
    }])
    
    # Player data
    players = Player.create!([{
      "name": "Some Guy",
      "shoots": "Right",
      "position": "Forward",
      "pos": "F",
      "number": 8,
      "gp": 15,
      "goals": 12,
      "assists": 6,
      "points": 18,
      "pim": 12,
      "plusMinus": 7,
      "team_id": 1
    }])
    

    【讨论】:

      【解决方案3】:

      你在class Player的关联是错误的,看看什么时候一定要用:

      如果其他模型的名称不能从关联名称派生,您可以使用 :class_name 选项来提供模型名称。例如,如果一本书属于某个作者,但包含作者的模型的实际名称是 Patron,您可以这样设置:

      class Book < ApplicationRecord
        belongs_to :author, class_name: "Patron"
      end
      

      查看使用此关联的所有选项:Rails Guide

      【讨论】:

        猜你喜欢
        • 2020-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多