美好的一天,社区。 p>
首先,我是Rails的新手。 4年前我在大学做过一些事情,现在我决定重新开始。版本4中发生了很多变化。
无论如何,我遇到了强参数的问题。这就是我所拥有的:
我使用的是Ruby 2.1,Rails 4.1。
我正在尝试使用参数(id,team_a,team_b,arena,date,score_a,score_b)为曲棍球比赛创建表单。团队是一个表(id,name),竞技场是一个表(id,name)。
当我将参数从表单传递给控制器时,json参数似乎没问题。但是,当它被转换为match_params时,它会丢失来自其他表的参数的一些值。例如,我传递了arena_id:12,但它显示了arena_id:as blank。
我花了5天多时间做这件事。任何帮助赞赏。
部分代码如下。如果您需要我提供更多信息,请告诉我......
迁移数据
class CreateMatches < ActiveRecord::Migration
def change
create_table :matches do |t|
t.references :team_a, default: 1 # unknown
t.references :team_b, default: 1 # unknown
t.references :arena, default: 1 # unknown
t.datetime :date
t.integer :score_a
t.integer :score_b
t.timestamps
end
add_index :matches, :team_a_id
add_index :matches, :team_b_id
add_index :matches, :arena_id
end
end
class CreateTeams < ActiveRecord::Migration
def change
create_table :teams do |t|
t.string :name, null: false
t.timestamps
end
end
end
class CreateArena < ActiveRecord::Migration
def change
create_table :arena do |t|
t.string :name, null: false
t.timestamps
end
end
end
match.rb(型号)
class Match < ActiveRecord::Base
belongs_to :team_a, :class_name => 'Team'
belongs_to :team_b, :class_name => 'Team'
belongs_to :arena
end
team.rb(型号)
class Team < ActiveRecord::Base
has_many :matches
accepts_nested_attributes_for :matches
end
arena.rb(型号)
class Arena < ActiveRecord::Base
has_many :matches
accepts_nested_attributes_for :matches
end
matches_controller.rb
class MatchesController < ApplicationController
before_action :set_match, only: [:show, :edit, :score, :update, :destroy]
include ActionView::Helpers::DateHelper
def index
# some code
end
def show
# some code
end
def new
@match = Match.new
@teams = Team.all.order("name ASC")
@arenas = Arena.all.order("name ASC")
end
# GET /matches/1/edit
def edit
# some code
end
def create
puts YAML::dump(match_params) # Checking passed params. Output is bellow
@match = Match.new(match_params)
respond_to do |format|
if @match.save
format.html { redirect_to @match, notice: 'Match was successfully created.' }
format.json { render action: 'show', status: :created, location: @match }
else
format.html { render action: 'new' }
format.json { render json: @match.errors, status: :unprocessable_entity }
end
end
end
def update
end
def destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_match
@match = Match.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def match_params
params.require(:match).permit(:date, :score_a, :score_b, team_a_id: [:id, :name], team_b_id: [:id, :name], arena_id: [:id, :name])
end
public
end
teams_controller.rb
class TeamsController < ApplicationController
before_action :set_team, only: [:show, :edit, :update, :destroy]
layout :false
def index
@teams = Team.all
end
def show
end
def new
@team = Team.new
end
def edit
end
def create
@team = Team.new(team_params)
respond_to do |format|
if @team.save
format.json { render action: 'show', status: :created, location: @team }
format.html { redirect_to @team, notice: 'Team was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: @team.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @team.update(team_params)
format.json { head :no_content }
format.html { redirect_to @team, notice: 'Team was successfully updated.' }
else
format.html { render action: 'edit' }
format.json { render json: @team.errors, status: :unprocessable_entity }
end
end
end
def destroy
@team.destroy
respond_to do |format|
format.html { redirect_to teams_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_team
@team = Team.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def team_params
params.require(:team).permit(:name)
end
end
arenas_controller.rb
class ArenasController < ApplicationController
before_action :set_arena, only: [:show, :edit, :update, :destroy]
layout false
def index
@arena = Arena.all
end
def show
end
def new
@arena = Arena.new
end
def edit
end
def create
@arena = Arena.new(arena_params)
respond_to do |format|
if @arena.save
format.json { render action: 'show', status: :created, location: @arena }
format.html { redirect_to @arena, notice: 'Arena was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: @arena.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @arena.update(arena_params)
format.json { head :no_content }
format.html { redirect_to @arena, notice: 'Arena was successfully updated.' }
else
format.html { render action: 'edit' }
format.json { render json: @arena.errors, status: :unprocessable_entity }
end
end
end
def destroy
@arena.destroy
respond_to do |format|
format.html { redirect_to arenas_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_arena
@arena = Arena.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def arena_params
params.require(:arena).permit(:name)
end
end
匹配/ _match.html.erb
<%= form_for(@match, html: {role: 'form', class: 'form-horizontal'}) do |f| %>
<% if @match.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@match.errors.count, "error") %> prohibited this match from being saved:</h2>
<ul>
<% @match.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label 'Home Team' %>
<%= f.collection_select :team_a_id, @teams, :id, :name, {prompt: true}, {class: ''} %>
<%= f.label 'Visitor Team' %>
<%= f.collection_select :team_b_id, @teams, :id, :name, {prompt: true}, {class: ''} %>
<%= f.label 'Arena' %>
<%= f.collection_select :arena_id, @arenas, :id, :name, {prompt: true}, {class: ''} %>
<%= f.label 'Date' %>
<%= f.datetime_select :date, class: 'form-control' %>
<%= f.submit value: 'Submit' %>
<% end %>
以下是转储数据后我在控制台中获得的内容:
Started POST "/matches" for 127.0.0.1 at 2014-05-06 18:24:20 -0700
Processing by MatchesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"0RJjnpczVkp2unG9VITyHYC89ThgELn5kVE2wYRymBU=", "match"=>{"team_a_id"=>"24", "team_b_id"=>"27", "arena_id"=>"21", "date(1i)"=>"2014", "date(2i)"=>"5", "date(3i)"=>"6", "date(4i)"=>"18", "date(5i)"=>"24"}, "commit"=>"Update"}
User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
--- !ruby/hash:ActionController::Parameters
date(1i): '2014'
date(2i): '5'
date(3i): '6'
date(4i): '18'
date(5i): '24'
team_a_id:
team_b_id:
arena_id:
(0.2ms) BEGIN
SQL (1.5ms) INSERT INTO `matches` (`created_at`, `date`, `arena_id`, `team_a_id`, `team_b_id`, `updated_at`) VALUES ('2014-05-07 01:24:20', '2014-05-07 01:24:00', NULL, NULL, NULL, '2014-05-07 01:24:20')
(0.2ms) COMMIT
Redirected to http://localhost:3000/matches/90
Completed 302 Found in 13ms (ActiveRecord: 2.4ms)
答案 0 :(得分:2)
查看您的match_params
,并将其与从表单传递给控制器的参数进行比较。
def match_params
params.require(:match).permit(:date, :score_a, :score_b, team_a_id: [:id, :name], team_b_id: [:id, :name], area_id: [:id, :name])
end
Parameters: {"utf8"=>"✓", "authenticity_token"=>"0RJjnpczVkp2unG9VITyHYC89ThgELn5kVE2wYRymBU=", "match"=>{"team_a_id"=>"24", "team_b_id"=>"27", "arena_id"=>"21", "date(1i)"=>"2014", "date(2i)"=>"5", "date(3i)"=>"6", "date(4i)"=>"18", "date(5i)"=>"24"}, "commit"=>"Update"}
您允许将arena_id
match_params
作为名为area_id
的数组:id
,其元素为:name
和arena_id
。但是,它只是从您的表单传递为match_params
。您应该将def match_params
params.require(:match).permit(:date, :score_a, :score_b, :team_a_id, :team_b_id, :arena_id)
end
功能更改为:
:team_a_id
请注意,我还更改了:team_b_id
和:score_a
,以便与您在参数中传递的内容保持一致,尽管它看起来不像您正在传递:score_b
或{{1}}。您应该在导轨指南中查看strong parameters以获取更多信息。
答案 1 :(得分:1)
好的,我发现了自己的错误。 (感谢JKen13579)
我把params放在错误的地方。
应该是这样的:
def match_params
params.require(:match).permit(:date, :score_a, :score_b, :team_a_id, :team_b_id , :arena_id)
end
def team_params
params.require(:team).permit(:name, matches_params:[:id, :match_id, :name])
end
def arena_params
params.require(:arena).permit(:name, matches_params:[:id, :match_id, :name])
end
解决了这个问题。
答案 2 :(得分:0)
除了名字之外的所有内容都会在您致电时删除:
params.require(:arena).permit(:name)