Rails的新手,请原谅我提出一个简单的问题,但我很难过。
Rails 4.1.1和Ruby 2.1.2
我正在根据我从Code School关注的视频创建一个小型Rails应用程序(Zombie Twitter)。
我有四个控制器:应用程序,欢迎,僵尸和推文。
我有三个型号:User,Zombie,Tweet。
用户(来自Devise),has_one :zombie
。
Zombie,belongs_to :user
和 has_many :tweets
。
推文,belongs_to :zombie
。
用户注册时会创建新的僵尸记录。这很有效。
但是,在创建新推文时,不会填充tweets表中的zombie_id字段。我无法弄清楚这是我的问题。
另外:有人可以解释build和build_model方法以及何时使用它们?当我按@zombie.tweets.build
的方式调用某些内容时,我得到一个方法丢失错误。是否有必要在Rails 4.1.1中调用这些方法,还是从早期版本的Rails中保留这些方法?
User.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_one :zombie
accepts_nested_attributes_for :zombie, allow_destroy: true
end
Zombie.rb
class Zombie < ActiveRecord::Base
belongs_to :user
has_many :tweets
validates_uniqueness_of :zombie_name
end
Tweet.rb
class Tweet < ActiveRecord::Base
belongs_to :zombie
attr_accessor :zombie_id
accepts_nested_attributes_for :zombie
end
ApplicationController.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :set_zombie
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << [zombie_attributes: :zombie_name]
end
def set_zombie
if user_signed_in?
@zombie = Zombie.includes(:tweets).find_by user_id: current_user.id
end
end
end
TweetController.rb
class TweetsController < ApplicationController
before_action :set_tweet, only: [:show, :edit, :update, :destroy]
# GET /tweets/new
def new
@tweet = current_user.zombie.tweets.new
end
# POST /tweets
# POST /tweets.json
def create
@tweet = current_user.zombie.tweets.new(tweet_params)
logger.debug params
respond_to do |format|
if @tweet.save
format.html { redirect_to :root, notice: 'Tweet was successfully created.' }
format.json { render :show, status: :created, location: @tweet }
else
format.html { render :new }
format.json { render json: @tweet.errors, status: :unprocessable_entity }
end
end
end
def set_tweet
@tweet = Tweet.find(params[:id])
end
def tweet_params
params.require(:tweet).permit(:status, :is_public)
end
end
/tweets/_form.html.rb
<%= form_for([@zombie, @tweet]) do |f| %>
<% if @tweet.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@tweet.errors.count, "error") %> prohibited this tweet from being saved:</h2>
<ul>
<% @tweet.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label 'Public' %>
<%= f.check_box :is_public, checked: true %>
</div>
<div class="field">
<%= f.label :status %><br>
<%= f.text_area :status %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
create_zombies_migration
class CreateZombies < ActiveRecord::Migration
def change
create_table :zombies do |t|
t.string :zombie_name
t.timestamps
end
add_reference :zombies, :user, index: true
add_index :zombies, [:user_id, :id]
add_index :zombies, :zombie_name, unique: true
end
end
create_tweets_migration
class CreateTweets < ActiveRecord::Migration
def change
create_table :tweets do |t|
t.text :status, :limit => 140
t.boolean :is_public, default: true
t.timestamps
end
add_reference :tweets, :zombie, index: true
add_index :tweets, [:zombie_id, :id], unique: true
end
end
最后,这是来自development.log的记录,详细说明了创建推文的POST请求。
答案 0 :(得分:1)
您需要从attr_accessor :zombie_id
删除tweet.rb
。
在create_tweets_migration
中添加t.references :zombie
zombie_id
应该是数据库中的列,而不是虚拟属性。
PS。 accepts_nested_attributes_for :zombie
中tweet.rb
也没有任何意义。
答案 1 :(得分:0)
尝试交换
current_user.zombie.tweets.new(tweet_params)
在tweets控制器的创建操作中:
current_user.zombie.tweets.build(tweet_params)
我认为应该在保存推文时填充id。