我刚刚在我的Rails应用程序中添加了一个联系表单,以便网站访问者可以向我发送消息。该应用程序有一个Message
资源,我已经定义了这个自定义路由,以使URL更好,更明显:
map.contact '/contact', :controller => 'messages', :action => 'new'
如果模型验证失败,如何将URL保留为/contact
?目前,在验证失败时,网址会更改为/messages
。
这是create
中的messages_controller
方法:
def create
@message = Message.new(params[:message])
if @message.save
flash[:notice] = 'Thanks for your message etc...'
redirect_to contact_path
else
render 'new', :layout => 'contact'
end
end
提前致谢。
答案 0 :(得分:8)
一种解决方案是使用以下代码制作两个条件路线:
map.contact 'contact', :controller => 'messages', :action => 'new', :conditions => { :method => :get }
map.connect 'contact', :controller => 'messages', :action => 'create', :conditions => { :method => :post } # Notice we are using 'connect' here, not 'contact'! See bottom of answer for explanation
这将使所有获取请求(直接请求等)使用“新”操作,并且帖子请求“创建”操作。 (还有另外两种类型的请求:put和delete,但这些都与此无关。)
现在,以您创建消息对象的形式更改
<%= form_for @message do |f| %>
到
<%= form_for @message, :url => contact_url do |f| %>
(表单助手将自动选择帖子请求类型,因为在创建新对象时这是默认值。)
应该解决你的烦恼。
(这也不会导致地址栏闪烁其他地址。它从不使用其他地址。)
修改强>
如果你认为额外的路线有点乱(特别是当你经常使用它时),你可以创建一个特殊的方法来创建它们。这种方法不是很漂亮(可怕的变量名称),但它应该可以完成这项工作。
def map.connect_different_actions_to_same_path(path, controller, request_types_with_actions) # Should really change the name...
first = true # There first route should be a named route
request_types_with_actions.each do |request, action|
route_name = first ? path : 'connect'
eval("map.#{route_name} '#{path}', :controller => '#{controller}', :action => '#{action}', :conditions => { :method => :#{request.to_s} }")
first = false
end
end
然后像这样使用它
map.connect_different_actions_to_same_path('contact', 'messages', {:get => 'new', :post => 'create'})
我更喜欢原始方法......
答案 1 :(得分:1)
我刚刚提出了第二个解决方案,在奥马尔对我的第一个问题的评论的指导下。
如果你把它写成资源路线
map.resources :messages, :as => 'contact'
这给(以及其他)以下路线
/contact # + GET = controller:messages action:index
/contact # + POST = controller:messages action:create
因此,当您将“新”操作代码移动到“索引”操作中时,您将获得相同的结果。没有闪烁和更容易阅读的路线文件。但是,你的控制器没有任何意义。
但是,我认为这是一个更糟糕的解决方案,因为您很快就会忘记为什么要将“新”代码放入索引操作中。顺便说一下。如果你想保留一种索引动作,你可以这样做
map.resources :messages, :as => 'contact', :collection => { :manage => :get }
这将为您提供以下路线
manage_messages_path # = /contact/manage controller:messages action:manage
然后,您可以将索引操作代码移动到管理操作中。
答案 2 :(得分:0)
我怀疑您是从表单中发布'/ messages'来创建邮件,该邮件解释了您在网址中看到的原因。
任何原因都不起作用:
def create
@message = Message.new(params[:message])
if @message.save
flash[:notice] = 'Thanks for your message etc...'
redirect_to contact_path
else
flash[:notice] = 'Sorry there was a problem with your message'
redirect_to contact_path
end
end
答案 3 :(得分:0)
据我所知,没有。因为即时通讯假设你想要渲染,以便保持@message对象不变,附带错误。
我有一个可怕的解决方案让你这样做,但是,它太可怕了,我不推荐它:
before_filter :find_message_in_session, :only => [:new]
def new
@message ||= Message.new
end
def create
@message = Message.new(params[:message])
if @message.save
flash[:notice] = 'Thanks for your message etc...'
redirect_to contact_path
else
flash[:notice] = 'Sorry there was a problem with your message'
store_message_in_session
redirect_to contact_path
end
end
private
def find_message_in_session
@message = session[:message]; session[:message] = nil
end
def store_message_in_session
session[:message] = @message
end