开发者

RoutingError on empty field, conflicting with friendly_id

开发者 https://www.devze.com 2023-02-16 21:16 出处:网络
I have a edit form for @users. In there I have a text_field :username <%= form_for @user, :url => { :action => \"update\" } do |f| %>

I have a edit form for @users. In there I have a text_field :username

<%= form_for @user, :url => { :action => "update" } do |f| %>
 <%= render 'shared/error_messages', :target => f.object %>
 <div class="field">
    <%= f.label :username %><br />
    <%= f.text_field :username %>
 </div>

In my User model I use the friendly_id gem, set to :username as well. So my urls look like domain.com/users/:username instead of :id.

has_friendly_id :username

Now in my application layout, I also use @user.username in my navigation to link to the profile.

All works well, EXCEPT if I leave my :username field empty on save. It fails to save cause of validations,

validates :username, :presence => true, :uniqueness => { :case_sensitive => false }, :length => { :maximum => 50 }

and tries to render "edit" again. But to render "edit" we need the username to create the link in the navb开发者_开发问答ar. And apparently it's passed on as username => "", even though it rightfully so failed to save and proper validations are in place.

 def update
  @user = current_user
  if @user.update_attributes(params[:user])
    flash[:success] = "Account updated."
    redirect_to :back
  else
    @title = "Edit"
    render "edit"
  end

end

So I end up with a RoutingError:

No route matches {:action=>"show", :controller=>"users", :id=>#<User id: 6, username: "", persistence_token: "c2f2545659c186131537155347f46f7da5eb0d51b27707e71da...", created_at: "2011-03-14 14:26:48", updated_at: "2011-03-15 01:54:33", email: "test@test.com", crypted_password: "0d6489b1447d278bc4f7c86bab13787f226a10a302b43ec02ff...", password_salt: "Lq2G80iSVeaitB5PDwf", perishable_token: "Tm7Jzyq8QutfaxL3JLZ8", active: true>}


First of all, redirecting to :back, even if you successfully change the username, will likely fail because the URL itself is going to be different. So you should probably do

redirect_to @user

instead.

If you want to use the username field as the basis of a friendly_id, then it's probably best to not let it be blank, which you could enforce by adding a validation to the model:

class User < ActiveRecord::Base
  ...
  validates_presence_of :username
  ...
end

Alternatively, if for some reason in your app makes sense to have them blank, you can force Rails to generate the URL based on the numeric id rather than the friendly_id in these cases.

To do this, you would need to set username value to nil rather than blank, and then either do

redirect_to @user

or

redirect_to user_url(@user)

In this case you'll also want to use the :allow_nil => true option to has_friendly_id.

I'm the author of FriendlyId, if this doesn't solve your problem feel free to send a message to FriendlyId's Google Group or to me personally at norman@njclarke.com, and I'll try to help you out.


You don't really need to re-render the edit screen if your validation fails.

It'd probably work better if you updated your page using ajax and use a remote_form_for (Rails 2) or form_for :remote => true (Rails 3) when submitting your form. That way if your form passes the validation you can just redirect the user like you're trying to do, but you don't need to actually leave the page if your validation fails, you can just send the validation message back to the form.

Simone Carletti's blog has a pretty decent example on how to do it.

http://www.simonecarletti.com/blog/2010/06/unobtrusive-javascript-in-rails-3/

Ryan Bates has put up a simple example of how to use it as well.

http://railscasts.com/episodes/205-unobtrusive-javascript

0

精彩评论

暂无评论...
验证码 换一张
取 消