我想为条目构建一个表单,用户可以预测几个contest_questions。
这意味着我动态地想要获取与推特竞赛相关的竞赛项目,然后让用户注册一个包含每个问题预测的条目。
我该怎么做?截至目前,我的字段未显示,因为<%= f.fields_for :predictions do |prediction| %>
未在contest_question块中执行,如果我将其更改为contest_question.fields_for ...
,我会收到
对于#,未定义的方法`fields_for'
tipster_contest.rb
class TipsterContest < ActiveRecord::Base
belongs_to :bookmaker
belongs_to :game
has_many :entries
has_many :contest_questions
extend FriendlyId
friendly_id :name, use: [:slugged, :history]
enum status: { "Scheduled" => 0, "Open" => 1, "Closed" => 2, "Graded" => 3 }
scope :published?, -> { where(published: :true) }
end
entry.rb
class Entry < ActiveRecord::Base
belongs_to :user
belongs_to :tipster_contest
has_many :predictions
accepts_nested_attributes_for :predictions
end
contest_question.rb
class ContestQuestion < ActiveRecord::Base
belongs_to :tipster_contest
has_many :predictions
end
prediction.rb
class Prediction < ActiveRecord::Base
belongs_to :entry
has_one :contest_question
end
_form.html.erb
<%= form_for(@entry) do |f| %>
<% @contest.contest_questions.order(name: :asc).each do |contest_question| %>
<%= f.fields_for :predictions do |prediction| %>
<div class="field">
<%= prediction.label contest_question.name %>
<%= prediction.select(:prediction, @contest.teams) %>
</div>
<div class="field">
<%= prediction.label :wager_amount %>
<%= prediction.input :wager_amount %>
</div>
<% end %>
<% end %>
<div class="actions">
<%= f.submit "Save entry", :class => "btn btn-success" %> <%= link_to 'Back', bets_path, :class => "btn btn-danger" %>
</div>
<% end %>
我的schema.rb的相关部分,如果需要的话:
create_table "contest_questions", force: true do |t|
t.integer "tipster_contest_id"
t.string "name"
t.string "result"
t.integer "min_wager"
t.integer "max_wager"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "entries", force: true do |t|
t.integer "user_id"
t.integer "tipster_contest_id"
t.integer "bankroll"
t.integer "won"
t.string "currency"
t.boolean "entry_valid"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "predictions", force: true do |t|
t.integer "entry_id"
t.integer "contest_question_id"
t.string "prediction"
t.integer "wager_amount"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "tipster_contests", force: true do |t|
t.integer "bookmaker_id"
t.integer "game_id"
t.string "name"
t.string "tournament"
t.integer "status", default: 0
t.text "rules"
t.integer "prizepool"
t.string "currency"
t.text "payout_structure"
t.integer "tipster_wallet"
t.string "teams", default: [], array: true
t.datetime "registration_open"
t.datetime "registration_close"
t.boolean "published", default: false
t.datetime "created_at"
t.datetime "updated_at"
t.string "logo"
t.text "description"
t.string "slug"
end
add_index "tipster_contests", ["slug"], name: "index_tipster_contests_on_slug", using: :btree
答案 0 :(得分:0)
管理好解决它,至少让它运转起来。我不知道解决方案在rails标准方面是否有任何好处。无论如何它是:
<强> _form.html.erb 强>
<% title("#{@contest.name}") %>
<% description("Join #{@contest.name} and use your eSports knowledge to win extra cash or in-game skins for games like CS:GO, Dota 2, etc.") %>
<p id="notice"><%= notice %></p>
<%= form_for(@entry) do |f| %>
<% if @entry.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@entry.errors.count, "error") %> prohibited this entry from being saved:</h2>
<ul>
<% @entry.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field 'tipster_contest_id', :value => @contest.id %>
<div class="t_container">
<div class="t_row">
<div class="t_left"><b>Placement</b></div>
<div class="t_middle"><b>Team</b></div>
<div class="t_right"><b>Wager Amount</b></div>
</div>
<%= f.fields_for :predictions, @predictions do |p| %>
<div class="t_row">
<div class="t_left"><%= @entry.contest_questions.order(:name => :asc)[p.index].name %></div>
<div class="t_middle"><%= p.select :prediction, @contest.teams %></div>
<div class="t_right"><%= p.text_field :wager_amount, label: "Wager amount" %></div>
<%= p.hidden_field 'contest_question_id', :value => @entry.contest_questions.order(:name => :asc)[p.index].id %>
</div>
<% end %>
</div>
</br>
<div class="actions">
<%= f.submit "Save entry", :class => "btn btn-success" %> <%= link_to 'Back', bets_path, :class => "btn btn-danger" %>
</div>
<% end %>
<强> entries_controller.rb 强>
class EntriesController < ApplicationController
before_action :set_entry, only: [:show, :edit, :update, :destroy]
# GET /entries
# GET /entries.json
def index
@entries_open = current_user.entries.includes(:tipster_contest).where(:tipster_contests => {status: 1})
@entries_closed = current_user.entries.includes(:tipster_contest).where(:tipster_contests => {status: 2})
@entries_graded = current_user.entries.includes(:tipster_contest).where(:tipster_contests => {status: 3})
@contests = TipsterContest.where(status: 0..1).includes(:game)
end
# GET /entries/1
# GET /entries/1.json
def show
end
# GET /entries/new
def new
if user_signed_in?
begin
@contest = TipsterContest.friendly.find(params[:contest])
redirect_to tipster_contests_path(@contest), notice: "#{@contest.name} does not accept entries at this point. Registration opens at: #{@contest.registration_open} and closes at: #{@contest.registration_close}." and return true unless @contest.status == "Open"
@entry = Entry.new(tipster_contest: @contest)
@predictions = []
@contest.contest_questions.order(name: :asc).each do |cq|
@predictions << Prediction.new(entry: @entry.id, contest_question_id: cq.id)
end
rescue
redirect_to tipster_contests_path, notice: 'Could not find a tipster-contest with that ID'
end
else
redirect_to new_user_registration_path, notice: 'You need to sign up to enter the tipster contest!'
end
end
# GET /entries/1/edit
def edit
if user_signed_in?
@contest = @entry.tipster_contest
@predictions = @entry.predictions
redirect_to tipster_contests_path, notice: 'This is not your entry to edit' and return true unless @entry.user == current_user
else
redirect_to new_user_registration_path, notice: 'You need to sign up to enter or edit a tipster contest entry!'
end
end
# POST /entries
# POST /entries.json
def create
@entry = Entry.new(entry_params)
@predictions = @entry.predictions
@contest = @entry.tipster_contest
@entry.user = current_user
@entry.won = 0
@entry.bankroll = @contest.tipster_wallet
@entry.currency = @contest.currency
respond_to do |format|
if @entry.save
format.html { redirect_to @entry, notice: 'Entry was successfully created.' }
format.json { render :show, status: :created, location: @entry }
else
format.html { render :new }
format.json { render json: @entry.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /entries/1
# PATCH/PUT /entries/1.json
def update
@contest = @entry.tipster_contest
#@predictions = @entry.predictions
respond_to do |format|
if @entry.update(entry_params)
format.html { redirect_to @entry, notice: 'Entry was successfully updated.' }
format.json { render :show, status: :ok, location: @entry }
else
format.html { render :edit }
format.json { render json: @entry.errors, status: :unprocessable_entity }
end
end
end
# DELETE /entries/1
# DELETE /entries/1.json
def destroy
@entry.destroy
respond_to do |format|
format.html { redirect_to entries_url, notice: 'Entry was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_entry
@entry = Entry.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def entry_params
params[:entry].permit(:id, :tipster_contest_id, predictions_attributes: [:prediction, :wager_amount, :contest_question_id, :id])
end
end