我再次修改了这个问题以包含控制器文件。
在我们的应用中,我们有三种型号。用户模型,记分牌模型,团队模型。用户has_many记分板和记分板属于用户。记分板控制器中与两者相关联的创建操作的代码是" @scoreboard = current_user.scoreboards.build"。这段代码非常好用。
现在,问题出现在第三个模型上。记分牌模型拥有多个团队,每个团队都属于一个记分牌。这是一个has_many,belongs_to的关系。因此,外键位于team表中。记分板和团队迁移和模型文件分别在下面给出。
记分牌模型
class Scoreboard < ActiveRecord::Base
belongs_to :user
has_many :teams, dependent: :destroy
default_scope -> { order(created_at: :desc) }
end
记分牌迁移
class CreateScoreboards < ActiveRecord::Migration
def change
create_table :scoreboards do |t|
t.string :name_of_scoreboard
t.string :name_of_organization
t.string :name_of_activity
t.references :user, index: true
t.timestamps null: false
end
add_foreign_key :scoreboards, :users
add_index :scoreboards, [:user_id, :created_at]
end
end
团队模型
class Team < ActiveRecord::Base
belongs_to :scoreboard
end
团队迁移
class CreateTeams < ActiveRecord::Migration
def change
create_table :teams do |t|
t.string :name
t.integer :win
t.integer :loss
t.integer :tie
t.references :scoreboard, index:true
t.timestamps null: false
end
add_foreign_key :teams, :scoreboards
end
end
我认为我已正确关联模型。因此,我的团队控制器中用于创建操作的代码应该正确创建关联。控制器如下:
记分牌控制器:
class ScoreboardsController < ApplicationController
before_action :logged_in_user, only: [:new, :create, :show, :index]
before_action :correct_user, only: [:destroy, :edit, :update]
def new
@scoreboard = Scoreboard.new
end
def create
@scoreboard = current_user.scoreboards.build(scoreboard_params)
if @scoreboard.save
flash[:scoreboard] = "Scoreboard created successfully"
redirect_to scoreboard_path(@scoreboard)
else
render 'new'
end
end
def show
@scoreboard = Scoreboard.find_by_id(params[:id])
end
def index
if params[:search]
@scoreboards = Scoreboard.all.search(params[:search])
else
@scoreboards = current_user.scoreboards
end
end
def edit
@scoreboard = Scoreboard.find_by_id(params[:id])
end
def update
@scoreboard = Scoreboard.find_by_id(params[:id])
if @scoreboard.update_attributes(scoreboard_params)
flash[:success] = "Updated Successfully"
redirect_to scoreboard_path(@scoreboard)
else
render 'edit'
end
end
def destroy
@scoreboard = Scoreboard.find_by_id(params[:id])
@scoreboard.destroy
flash[:success] = "Deleted Successfully."
redirect_to scoreboards_path
end
private
def scoreboard_params
params.require(:scoreboard).permit(:name_of_scoreboard, :name_of_organization,
:name_of_activity, :starts_at, :ends_at, :cities, :states, :country, :picture )
end
def correct_user
@user = Scoreboard.find(params[:id]).user
redirect_to scoreboards_path unless current_user?(@user)
end
end
这是球队的控制者:
class TeamsController&lt; ApplicationController中
def new
@team = Team.new
end
def create
@scoreboard= current_user.scoreboards.build
@team = @scoreboards.teams.build(team_params)
if @team.save
flash[:success] = "Saved Successfully"
redirect_to scoreboard_path
else
render 'new'
end
end
def index
end
def show
end
private
def team_params
params.require(:team).permit(:name, :win, :loss, :tie)
end
end
然而,我得到一个错误&#34;未定义的方法`团队&#39;为零:NilClass&#34;当我提交应用创建动作的表单时。我不确定为什么会这样,因为我对用户和记分板模型做了同样的事情。
答案 0 :(得分:0)
我在回答你的问题后修正了我的答案:
我认为您的关联是正确的,也许可以尝试使用@scoreboard而不是记分牌。这样的事可能呢?
def blah
.... some code ....
@scoreboard = current_user.scoreboards.build
@team = @scoreboard.teams.build
.... more code ....
end
答案 1 :(得分:0)
Rails有很多方法可以通过用户输入创建相关记录。在这种情况下,我们假设您只想在记分板的上下文中创建团队。
我们要做的第一件事就是将球队路线嵌入记分牌:
# config/routes.rb
Rails.application.routes.draw do
# ...
resources :scoreboards do
resources :teams, shallow: true
end
end
这将为我们提供创建嵌套团队的路线:
Prefix Verb URI Pattern Controller#Action
scoreboard_teams GET /scoreboards/:scoreboard_id/teams(.:format) teams#index
POST /scoreboards/:scoreboard_id/teams(.:format) teams#create
new_scoreboard_team GET /scoreboards/:scoreboard_id/teams/new(.:format) teams#new
edit_team GET /teams/:id/edit(.:format) teams#edit
team GET /teams/:id(.:format) teams#show
PATCH /teams/:id(.:format) teams#update
PUT /teams/:id(.:format) teams#update
DELETE /teams/:id(.:format) teams#destroy
为什么?,因为这提供了RESTful设计,很明显您正在创建嵌套资源。嵌套索引路径实际上是可选的。
如果您想要一个非嵌套索引,无论记分牌如何都显示所有团队,您可以按以下方式定义路线:
# config/routes.rb
Rails.application.routes.draw do
# ...
resources :teams, only: :index
resources :scoreboards do
resources :teams, shallow: true, except: :index
end
end
如您所知,我们想要在Team
Scoreboards#show
个实例
# GET /scoreboards/1
def show
@team = @scoreboard.teams.build
end
我们还需要在记分板中添加一个团队表单。让我们使用可重用的部分:
# app/views/scoreboards/show.html.erb
<%= render partial: 'teams/form' %>
# app/views/teams/_form.html.erb
<%= form_for(@team.new_record? ? [@scoreboard, @team] : @team ) do |f| %>
<% if @team.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@team.errors.count, "error") %> prohibited this team from being saved:</h2>
<ul>
<% @team.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :wins %><br>
<%= f.number_field :wins %>
</div>
<div class="field">
<%= f.label :loss %><br>
<%= f.number_field :loss %>
</div>
<div class="field">
<%= f.label :tie %><br>
<%= f.number_field :tie %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
注意@team.new_record? ? [@scoreboard, @team] : @team
。我们使用三元运算符(紧凑的if语句),以便表单正确路由新记录和编辑记录。
因此,在我们的TeamsController
中,我们要设置回调以从params[:schoolboard_id]
加载记分板,以便我们可以使用新的和创建操作。
class TeamsController < ApplicationController
before_action :set_scoreboard, only: [:new, :create]
before_action :set_team, only: [:show, :edit, :update, :destroy]
# GET /scoreboard/:scoreboard_id/teams
def index
@scoreboard = Scoreboard.eager_load(:teams)
.find(params[:scoreboard_id])
@teams = @scoreboard.teams
end
# GET /teams/1
def show
end
# GET /scoreboard/:scoreboard_id/teams/new
def new
@team = @scoreboard.teams.new
end
# POST /scoreboard/:scoreboard_id/teams
def create
@team = @scoreboard.teams.new(team_params)
if @team.save
redirect_to @team, notice: 'Team was successfully created.'
else
render :new
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_team
@team = Team.find(params[:id])
end
def set_scoreboard
@scoreboard = Scoreboard.find(params[:scoreboard_id])
end
# Only allow a trusted parameter "white list" through.
def team_params
params.require(:team).permit(:name, :wins, :loss, :tie, :scoreboard_id)
end
end