问题描述
我正在构建一个具有 Keynote 模型和 Story 模型(以及我使用 Devise 实现的 User 模型)的应用程序.Keynote 有很多 Stories,一个 Story 属于一个 Keynote.
I'm building an application that has a Keynote model and a Story model (as well as a User model that I implemented with Devise). Keynotes have many Stories and a Story belongs to a Keynote.
我在创建新故事时遇到问题,并收到以下错误:
I'm having problems creating new stories and I get the following error:
StoriesController#create 中的 NoMethodError
#User:0x007fba0e32f760 的未定义方法`keynote'
undefined method `keynote' for #User:0x007fba0e32f760
错误发生在story_controller.rb的第18行
The error happens on line 18 of stories_controller.rb which is
@story = @current_user.keynote.stories.build(params[:story])
在创建方法中.
这是我的story_controller.rb的一部分
This is part of my stories_controller.rb
class StoriesController < ApplicationController
before_filter :authenticate_user!, :except => [:show, :index]
def index
@keynote = Keynote.find(params[:keynote_id])
@stories = @keynote.stories
end
def new
@keynote = Keynote.find(params[:keynote_id])
@story = @keynote.stories.build
end
def create
if user_signed_in?
@keynote = Keynote.find(params[:keynote_id])
@story = @current_user.keynote.stories.build(params[:story])
if @story.save
flash[:notice] = 'Question submission succeeded'
redirect_to keynote_stories_path
else
render :action => 'new'
end
end
end
这是我的 keynotes_controller.rb
This is my keynotes_controller.rb
class KeynotesController < ApplicationController
def index
@keynotes = Keynote.find :all, :order => 'id ASC'
end
def new
@keynote = Keynote.new
end
def show
@keynote = Keynote.find(params[:id])
end
def create
@keynote = Keynote.new(params[:keynote])
if @keynote.save
flash[:notice] = 'Keynote submission succeeded'
redirect_to keynotes_path
else
render :action => 'new'
end
end
end
这些是传递的参数:
{"utf8"=>"✓","authenticity_token"=>"76odSpcfpTlnePxr+WBt36fVdiLD2z+Gnkxt/Eu1/TU=","keynote_id"=>"1", "story"=>{"name"=>"Hi?"}, "commit"=>"Ask"}
这就是我在 routes.rb 文件中的内容:
And this is what I have in my routes.rb file:
get "keynotes/index"
get "users/show"
devise_for :users
get "votes/create"
get "stories/index"
resources :keynotes do
resources :stories
end
resources :stories do
get 'bin', :on => :collection
resources :votes
end
resources :users
root :to => 'keynotes#index'
我从错误行中删除了 current_user
,只留下 @story = @keynote.stories.build(params[:story])
.这会引发不同的错误:
I deleted current_user
from the line with the error, leaving just @story = @keynote.stories.build(params[:story])
. This throws a different error:
路由错误
没有路由匹配 {:controller=>"stories"}
No route matches {:controller=>"stories"}
但是数据库中的记录被创建,虽然没有 user_id.
but the record in the database gets created, without the user_id though.
任何帮助将不胜感激.
更新:这是我的用户模型,user.rb
Update: here's my User model, user.rb
class User < ActiveRecord::Base
has_many :stories
has_many :keynotes
has_many :votes
has_many :stories_voted_on, :through => :votes, :source => :story
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
end
这是 keynote.rb 模型:
Here's the keynote.rb model:
class Keynote < ActiveRecord::Base
validates_presence_of :title, :description, :speaker, :location
has_many :stories
belongs_to :user
end
这是 story.rb 模型:
And here's the story.rb model:
class Story < ActiveRecord::Base
after_create :create_initial_vote
validates_presence_of :name
belongs_to :user
belongs_to :keynote
has_many :votes do
def latest
find :all, :order => 'id DESC', :limit => 3
end
end
protected
def create_initial_vote
votes.create :user => user
end
end
推荐答案
出现错误是因为没有keynote
,而是keynotes
.如果您只想向用户添加故事,请删除 keynote.
:
The error occurs because there is no keynote
, but is keynotes
. If you just want to add a Story to the User, remove the keynote.
:
#return keynote even if it does not belong to current user
@keynote = Keynote.find(params[:keynote_id])
@story = @current_user.stories.build(params[:story]) #removed `keynote.` part
@story.keynote = @keynote #add the keynote to @story before saving @story
您还应该能够:
#return the keynote id only if it belongs to current user
@keynote = @current_user.keynotes.find(params[:keynote_id])
@story = @keynote.stories.build(params[:story])
因为主题演讲已经属于某个用户.你应该总是把你的范围协会.所以,而不是这样:
Because the keynote already belongs to a certain user. you should always scope yourassociations. So, instead of this:
@keynote = Keynote.find(params[:keynote_id])
做:
@keynote = @current_user.keynotes.find(params[:keynote_id])
这样,您就知道您总是在为当前用户找到主题演讲.如果黑客发送了参数 keynote_id = 55
,但 55 不属于 current_user,这意味着黑客能够将一个故事与一个可能无意的主题相关联.
This way, you know that you are always finding the keynote for current user. If a hacker send the param keynote_id = 55
, but 55 does not belong to current_user, that means the hacker was able to associate a story with an probably-uninteded keynote.
我只是猜测您不想允许向属于其他用户的主题演讲添加故事.
I'm just guessing that you don't want to allow adding a story to a keynote belonging to some other user.
这篇关于Controller#action 中的 NoMethodError - #<User:0x007fba0e32f760> 的未定义方法`keynote'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!