【发布时间】:2010-11-21 04:45:06
【问题描述】:
请参阅问题底部的更新...
作为参考,这个问题是由我根据之前在这里遇到的问题所做的一些修复演变而来的:Associating Two Models in Rails (user and profile)
我正在构建一个具有用户模型和配置文件模型的应用程序。
我想这样关联这些模型:
- 用户创建帐户后,会自动转到“创建个人资料”页面,并且他创建的个人资料仅与该特定用户关联。
- 只有拥有个人资料的用户才能对其进行编辑。
我使用 nifty_generators 生成了用户模型。当用户点击提交以创建帐户时,我将他重定向到“新配置文件”视图以创建配置文件。我通过在用户控制器中编辑重定向路径来做到这一点。用户控制器如下所示:
def new
@user = User.new
end
def create
@user = User.new(params[:user])
if @user.save
session[:user_id] = @user.id
flash[:notice] = "Thank you for signing up! You are now logged in."
redirect_to new_user_profile_path(:user_id => @user)
else
render :action => 'new'
end
end
当我单击“提交”以创建新用户时,它现在将我发送到以下 url,这似乎是正确的:localhost:3000/users/6/profile/new。但它会引发以下异常:
NoMethodError 在 ProfilesController#new 你有一个 nil 对象,当你没想到它! 评估时发生错误 nil.build
跟踪表明问题出在配置文件控制器中,在 New 方法中。配置文件控制器如下所示:
def index
@user = User.find(params[:user_id])
@profile = @user.profile(:order => "created_at DESC")
end
def show
@user = User.find(params[:user_id])
@profile = @user.profile.find(params[:id])
end
def new
@user = User.find(params[:user_id])
@profile = @user.profile.build
end
def edit
@user = User.find(params[:user_id])
@profile = @user.profile.find(params[:id])
end
def create
@user = User.find(params[:user_id])
@profile = @user.profile.build(params[:profile])
if @profile.save
flash[:notice] = 'Profile was successfully created.'
redirect_to(@profile)
else
flash[:notice] = 'Error. Something went wrong.'
render :action => "new"
end
end
此外,当我尝试查看配置文件的索引页面时,该应用程序也会引发异常(当前没有配置文件,因为我无法通过用户创建步骤来创建一个)。这是一个例外:
ProfilesController#index
中的 ActiveRecord::RecordNotFound
找不到没有 ID 的用户
这是日志告诉我的:
Processing ProfilesController#index [获取] 参数: {"动作"=>"索引", “控制器”=>“配置文件”}
ActiveRecord::RecordNotFound(不能 查找没有 ID 的用户):
应用程序/控制器/profiles_controller.rb:5:in `索引'
为了向您提供应用程序的其余详细信息,模型具有以下关联:
个人资料属于 _to :user
用户有 _one :profile
我在 routes.rb 文件中有这个:map.resources :users, :has_one => :profile
在抛出上面列出的第一个异常的新个人资料页面的视图中,我有这个:
<% form_for([@user, @profile]) do |f| %>
<%= f.error_messages %>
....
<% end %>
在引发上述第二个异常的配置文件索引视图中,我有这个:
<% @profiles.each do |profile| %>
<div class="post">
<div class="left">
<p>Store: </p>
<p>Category: </p>
</div>
<div class="right">
<p><%=h profile.name %></p>
<p><%=h profile.category %></p>
</div>
<div class="bottom">
<p><%= link_to 'Go to profile', user_profile_path(@user, profile) %></p>
<p><%= link_to 'Edit', edit_user_profile_path(@user, profile) %></p>
<p><%= link_to 'Destroy', user_profile_path(@user, profile), :confirm => 'Are you sure?', :method => :delete %></p>
</div>
我已经花了几个小时试图自己找出问题作为学习练习,但目前我不知道如何解决这个问题。感谢您的帮助!
更新:
jdl,根据您的要求:
配置文件/new.html.erb:
<% form_for([@user, @profile]) do |f| %>
<%= f.error_messages %>
<div class="left">
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>required
</p>
<p>
<%= f.label :category %><br />
<%= f.text_field :category %>required
</p>
<p>
<%= f.label :address1 %><br />
<%= f.text_field :address1 %>
</p>
<p>
<%= f.label :address2 %><br />
<%= f.text_field :address2 %>
</p>
<p>
<%= f.label :city %><br />
<%= f.text_field :city %>
</p>
<p>
<%= f.label :state %><br />
<%= f.text_field :state %>
</p>
<p>
<%= f.label :zip %><br />
<%= f.text_field :zip %>required
</p>
<p>
<%= f.label :phone %><br />
<%= f.text_field :phone %>
</p>
<p>
<%= f.label :email %><br />
<%= f.text_field :email %>
</p>
</div>
<div class="right">
<p>
<%= f.label :website %><br />
<%= f.text_field :website %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description %>
</p>
</div>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
routes.rb:
ActionController::Routing::Routes.draw 做 |map|
map.signup 'signup', :controller => 'users', :action => 'new'
map.logout '注销', :controller => 'sessions', :action => 'destroy'
map.login 'login', :controller => 'sessions', :action => 'new'
map.resources:会话
map.resources :users, :has_one => :profile
map.root :controller => "home"
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
配置文件控制器(截至 2009 年 8 月 20 日,美国东部标准时间晚上 8 点)
类 ProfilesController
def index
@users = User.all(:order => "created_at DESC")
end
def show
@user = User.find(params[:user_id])
end
def new
@user.profile = Profile.new
end
def edit
@user = User.find(params[:user_id])
@profile = @user.profile.find(params[:id])
end
def create
@user = User.find(params[:user_id])
@profile = @user.profile.build(params[:profile])
if @profile.save
flash[:notice] = 'Profile was successfully created.'
redirect_to(@profile)
else
flash[:notice] = 'Error. Something went wrong.'
render :action => "new"
end
end
def update
@profile = Profile.find(params[:id])
if @profile.update_attributes(params[:profile])
flash[:notice] = 'Profile was successfully updated.'
redirect_to(@profile)
else
render :action => "edit"
end
end
def destroy
@profile = Profile.find(params[:id])
@profile.destroy
redirect_to(profiles_url)
end
end
Cody,下面的索引页面抛出以下异常:
配置文件中的 NoMethodError#index
显示第 14 行出现的 app/views/profiles/index.html.erb:
# 的未定义方法“名称”
<div id="posts">
<% @users.each do |profile| %>
<div class="post">
<div class="left">
<p>Store: </p>
<p>Category: </p>
</div>
<div class="right">
<p><%=h profile.name %></p>
<p><%=h profile.category %></p>
</div>
<div class="bottom">
<p><%= link_to 'Go to profile', user_profile_path(@user, profile) %></p>
<p><%= link_to 'Edit', edit_user_profile_path(@user, profile) %></p>
<p><%= link_to 'Destroy', user_profile_path(@user, profile), :confirm => 'Are you sure?', :method => :delete %></p>
</div>
</div>
【问题讨论】:
-
你的路线是什么样的?专门针对用户和个人资料
-
也许:redirect_to new_user_profile_path(:user_id => @user.id)
-
好问题,顺便说一句。用适量的示例代码和对问题的清晰解释写得很好。新用户注意了。
-
Cody,我在 routes.rb 文件中有这个:map.resources :users, :has_one => :profile