如何解决Rails 3模型子类使我疯狂!请帮助纠正url /参数散列
|| 我在继承Rail \的模型时遇到问题。假设您有一个“ 0”模型及其几个子类(用户类型),它们存储特定的方法和关联,例如:“ 1”,“ 2”,“ 3”,“ 4”等。这只是简单的“单表继承”。问题是2倍。 当传递子类而不是基类时,路径/ URL经常崩溃或发生奇怪的事情。这是一个例子:<% if user.enabled? %>
<%= link_to \'Disable\',disable_user_path(user) %>
<% else %>
<%= link_to \'Enable\',enable_user_path(user) %>
<% end %>
如果您传入User
模型,则效果很好。但是,如果您传递一个子类(例如Admin
),它将抛出此异常:
No route matches {:controller=>\"users\",:action=>\"disable\",:id=>#<Admin id: 1,first_name: \"Ken\",...,created_at: \"2011-05-23 21:01:35\",updated_at: \"2011-05-23 21:04:28\">}
显然,这不正确。我们如何才能使Rails始终使用基类?
形式更令人不安(我正在使用simple_form
)。假设您有一个10英镑的表格。您希望所有的“ 0”子类均等地访问它,并且您不想在特殊情况下处理它们的子类。它应该是100%通用的。
出于某种原因,如果用户是Admin
,它将把params哈希发布为
params[:admin]
更糟糕的是,如果您查看表格的来源,它实际上说的是user[first_name]
而不是admin[first_name]
,因此,肯定有些螺丝钉!实例变量也是@user
,所以我不知道为什么要将它发布到params[:admin]
。
这是(2)的表单视图代码:
<%= simple_form_for(@user,:url => profiles_path,:method => :put,:html => {:multipart => true}) do |f| %>
<%= f.error_notification %>
<div class=\"form\">
<fieldset>
<legend>Personal Information</legend>
<%= f.input :first_name %>
<%= f.input :last_name %>
</fieldset>
<fieldset>
<legend>Credentials</legend>
<%= f.input :email %>
</fieldset>
<fieldset>
<legend>Preferences</legend>
<%= f.input :receive_email_notifications %>
<%= f.input :receive_newsletters %>
<%= f.input :allow_private_messages %>
</fieldset>
<fieldset>
<legend>Avatar</legend>
<p>
Select an image from your computer to use as your avatar. You will be given the oppurtunity
to crop this image further after your image has been uploaded.
</p>
<%= f.input :avatar,:as => :file,:label => \"Select File\" %>
<%= f.hidden_field :avatar_cache %>
</fieldset>
<div class=\"actions\">
<%= f.button :submit,:value => \"Update Profile\" %>
<%= link_to \'Cancel\',profiles_path %>
</div>
</div>
<% end %>
这是控制器的操作,它们首先呈现视图,而当我提交表单时:
def edit
@user = User.find(current_user.id)
end
def update
@user = User.find(current_user.id)
if @user.update_attributes(params[:user]) # <-- this bombs for Admin subclass
if params[:user][:avatar] # <-- this would bomb also.
redirect_to(crop_avatar_profiles_path)
else
redirect_to(profiles_path,:notice => \'Your profile was successfully updated.\')
end
else
render :action => \"edit\"
end
end
def crop_avatar
@user = User.find(current_user.id)
end
def update_avatar
@user = User.find(current_user.id)
@user.crop(params[:x].to_i,params[:y].to_i,params[:h].to_i,params[:w].to_i)
redirect_to(profiles_path,:notice => \'Your profile and avatar was successfully updated.\')
end
除了想出一些非常优雅的解决方案(尤其是表单问题)之外,我对如何解决它们也无所适从。必须有一种更好的方法来处理这些情况。
解决方法
由于动态铸造导轨对我造成了影响,所以我在STI上也遇到了同样的问题。我使用gets方法解决了它。
在您的用户模型中:
#return an array [User,User,...],instead of [Admin,Director,Instructor,...]
def self.all_without_typecast
self.all.collect! do |u|
u.becomes(User)
end
end
#makes subclasses of User (Admin,...) into User class
def userize #cast_into_user could be a better name
self.becomes(User)
end
现在,只要您不希望用户实例具有特定类型(Admin,Director ..),而只是User,就可以:
@user = @user.userize
现在,您的@user对象将被视为用户,而不是Admin或Director或其他任何对象,all_without_typecast也是如此,如下所示:
@users = User.all_without_typecast # if you\'re having problems with User.all
也许可以在每个作用域之前运行此方法,所以您不必重写每个方法。
希望能帮助到你!
,= simple_form_for @fruit,:as => :fruit do |form|
@fruit
可以是任何类别(橙色,苹果,梨),并且仍会在输入的前面加上\'fruit \',因此每次给出giving25ѭ。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。