nil的未定义方法`build':NilClass rails

K W*_*ers 3 ruby-on-rails ruby-on-rails-4

我的想法是:我的视图中的:pledge属性(:amount和:frequency)没有传递给控制器​​中的新动作.另外,我知道我的承诺属性没有保存,也许这是因为在调用@user时pledge_id是nil.

new.html.erb

<%= form_for @user, url: pledge_path, controller: 'user', action:     'create', method: 'post' do |f| %>
  <%= f.label :user_name %>
  <%= f.text_area :user_name %>
  <%= f.label :email %>
  <%= f.text_area :email%>
  <%= f.label :address %>
  <%= f.text_area :address %>
  <%= f.fields_for(:pledge) do |b| %>
    <%= b.label :amount %>
    <%= b.text_area :amount %>
    <%= b.label :frequency %>
    <%= b.text_area :frequency %>
    <%= b.submit 'I also want o pledge' %>
  <% end %>
<%= f.submit 'I just want to sumbit my info' %>

<% end %>
Run Code Online (Sandbox Code Playgroud)

pledge.rb

class Pledge < ActiveRecord::Base
  belongs_to :user
  validates_presence_of :user

end
Run Code Online (Sandbox Code Playgroud)

user.rb

class User < ActiveRecord::Base
  has_many :pledges, foreign_key: "pledge_id"
   accepts_nested_attributes_for :pledges
   attr_accessor :pledges

end
Run Code Online (Sandbox Code Playgroud)

schema.rb

ActiveRecord::Schema.define(version: 20150318161827) do

create_table "pledges", force: :cascade do |t|
  t.integer "frequency"
  t.float   "amount"
  t.integer "user_id"
end

add_index "pledges", ["user_id"], name: "index_pledges_on_user_id"

create_table "users", force: :cascade do |t|
  t.string  "user_name"
  t.string  "email"
  t.string  "address"
  t.integer "pledge_id"
end

end
Run Code Online (Sandbox Code Playgroud)

user_controller.rb

class UserController < ApplicationController
def new
    @user = User.new
    @user.pledges.build 
end

def create
    if params[:commit] == 'I just want to sumbit my info'
        User.create(user_params)

    elsif
        @pledge = Pledge.new(params[:pledge])
        @pledge.save
        @user = User.create(pledge_params)  
    end
    redirect_to thank_you_path

end
def pledge_params
    params.require(:user).permit(:email, :user_name, :address,
                                pledge_attributes: [:id, :amount, :frequency])
end

def user_params
    params.require(:user).permit(:email, :user_name, :address)
end
end
Run Code Online (Sandbox Code Playgroud)

在此先感谢您的任何建议!

Max*_*kin 14

在像你这样的类似情况下,来自这里的信息对我来说很有帮助.

所以在Sontya的代码中你需要@user.pledges.build改为@user.build_pledges.

虽然,我认为你解决了你的问题,但我这样做的答案是帮助任何搜索这些信息的人.

  • 对于单个资源(has_one),例如,如果用户只有一个承诺`@ user.build_pledge`是使它工作的唯一方法. (14认同)

Son*_*ute 2

你不能打电话

@user.pledges.build
Run Code Online (Sandbox Code Playgroud)

如下行只会创建 的实例User,但不会将其保存到数据库。

@user = User.new
Run Code Online (Sandbox Code Playgroud)

2)为什么你pledge_id在用户表中,因为用户有_许多承诺,你不能在用户表中存储一个承诺_id 3)应该只有一个submit按钮,将formpledges值发送为nested_attributes

编辑

class Pledge < ActiveRecord::Base
  belongs_to :user
  validates_presence_of :user

end

class User < ActiveRecord::Base
   has_many :pledges
   accepts_nested_attributes_for :pledges
   attr_accessor :pledges
end
Run Code Online (Sandbox Code Playgroud)

控制器,现在应该可以了

def new
   @user = User.new
   @user.pledges.build
end

def create
  @user = User.new(user_params)
  respond_to do |format|
    if @user.save
      format.html { redirect_to @user, notice: 'User was successfully created.' }
    else
      format.html { render action: 'new' }
      format.json { render json: @user.errors, status: :unprocessable_entity }
    end
  end
end

def user_params
  params.require(:user).permit(:name, etc..., pledges_attributes:[:amount, etc..])
end    
Run Code Online (Sandbox Code Playgroud)

new.erb.html

<%= form_for @user do |f| %>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
      <ul>
      <% @user.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :email %><br>
    <%= f.text_field :email %>
  </div>
  <%= f.fields_for :pledge do |builder| %>
     <%= builder.label :amount %>
     <%= builder.text_field :amount %>
  <% end %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>  
Run Code Online (Sandbox Code Playgroud)