Удаление записей с помощью Ajax в Rails - PullRequest
5 голосов
/ 16 декабря 2009

У меня есть страница пользователя, где пользователь может печатать и отправлять сообщения. Я использую Ajax, чтобы позволить пользователю сделать это со страницы пользователя / шоу. Проблема, которая возникает у меня, когда я пытаюсь позволить пользователю удалять сообщения. Когда пользователь нажимает ссылку «удалить», сообщение удаляется со страницы. Однако, когда я перезагружаю страницу, сообщение возвращается. Это не разрушается.

У меня тот же код, реализованный на странице пользователя / редактирования в другом контексте, и это прекрасно работает, потому что запись записи уничтожается при отправке формы. Однако в этой ситуации, когда форма не отправлена, я не уверен, как заставить это работать.

Вот мои настройки:

:user has_many :posts
:post belongs_to :user
:post belongs_to :post_type
:post_type has_many :posts

Пользователь # показать:
Это код для пользователя, чтобы отправить сообщение. Это работает отлично.

<% if logged_in? && current_user == @user %>
  <% form_tag(:controller => "posts", :action => "create") do %>
    <div><%= text_area_tag(:message, nil, :size => "27x3") %></div>
    <div><%= submit_tag("Post") %></div>
    <div><%= label_tag(:post_type_id, "Update type?", :class => 'typeLabel') %></div>
    <div><%= collection_select(@posts, :post_type_id, PostType.all, :id, :name) %></div>
  <% end %>
<% end %>

Это код, в котором отображаются сообщения, в том числе «удалить ссылку»:

<% @user.posts.each do |c| %>
  <div class="postS">
    <div><%=h c.message %></div>
    <p><%=h c.post_type.name %></p>
    <p>Posted <%=h time_ago_in_words(c.created_at) %> ago</p>       
    <% if logged_in? && current_user == @user %>
        <%= link_to_function "- Delete Post", "if(confirm('Are you sure you want to permanently delete this post?')) $(this).up('.postS').remove()" %>                          
    <% end %>                   
<%end%>

PostsController

def destroy
  @post = Post.find(params[:id])
  if @post.destroy
    redirect_to :back
  else
    flash[:notice] = "Post failed to delete."
    redirect_to :back
end
end

Дайте мне знать, будет ли полезна любая другая информация. Спасибо!

Обновление 2

Я пытался использовать link_to_remote, как объяснено в ответе ниже. Я согласен, что это правильное решение, но не могу заставить его работать. Я думаю, что это из-за проблемы маршрутов.

У меня есть сообщения, настроенные как пользовательский ресурс:

map.resources :users, :member => { :enable => :put } do |users|
  users.resources :posts
end  

Когда я реализую код link_to_remote, указанный в ответе, я получаю исключение "ошибка метода" следующим образом: undefined method post_url 'для # `

Я попробовал некоторые настройки, которые объясняли это, но ни одна из моих попыток не сработала. Есть идеи? Я прав, что это связано с моим маршрутом?

UPDATE

Код из Руководств по Rails не работает. Я также попробовал много вариантов.

Самое близкое, что я получил, это:

<%= link_to_remote "- Delete Post", :url => { :controller => 'posts', :action => 'destroy', :id => @user.posts, :method => :delete }, :confirm => "Are you sure you want to permanetly delete this post?", :success => "$(this).up('.postS').remove();" %>  

Используя этот код, я нажимаю ссылку удаления, и мне предлагается принять удаление. После того, как я принимаю, сообщение не удаляется на экране. ОДНАКО, он удаляется из базы данных. Затем, когда я перезагружаю страницу, сообщение фактически удаляется с экрана. Так что это в основном работает, за исключением того, что действие удаления ajax теперь не работает.

Но код кажется неправильным. Обратите внимание, что я написал:: id => @ user.posts

Мне это не кажется правильным, но это единственный способ, как заставить этот код работать вообще. Посмотрите, что это делает с файлом журнала:
Обработка PostsController # destroy (для 127.0.0.1 в 2009-12-17 02:07:05) [POST]

`Parameters: {"action"=>"destroy", "authenticity_token"=>"GZfPHUc2+qPa6Fj5jNogMyhuB4YUO+KlOdkwjM5NSvw=", "id"=>"12/11", "method"=>"delete", "controller"=>"posts"}  `

Обратите внимание на id => "12/11". Это не то, что я хочу, чтобы произошло.

Когда я изменяю параметр id на: id => @ user.post, я получаю сообщение «ошибка метода отсутствует». undefined метод `post 'для #User: 0x3ddc20c

Когда я пытаюсь :id => user_post_url(@user, @post), я получаю: "user_post_url не удалось сгенерировать из [и затем в нем перечислены все значения столбца базы данных для этого пользователя].

Когда я пытаюсь :id => user_posts_url(@user, @posts), страница загружается. Когда я нажимаю на ссылку удаления, мне предлагается принять. Тогда ничего не происходит. Когда я перезагружаю страницу, сообщение все еще там и никогда не удаляется из базы данных.

Это все варианты, о которых я мог подумать. Есть идеи?

Обновление 3

Вот как выглядят мои маршруты:

    user_posts GET    /users/:user_id/posts(.:format)          {:controller=>"posts", :action=>"index"}
               POST   /users/:user_id/posts(.:format)          {:controller=>"posts", :action=>"create"}
 new_user_post GET    /users/:user_id/posts/new(.:format)      {:controller=>"posts", :action=>"new"}
edit_user_post GET    /users/:user_id/posts/:id/edit(.:format) {:controller=>"posts", :action=>"edit"}
     user_post GET    /users/:user_id/posts/:id(.:format)      {:controller=>"posts", :action=>"show"}
               PUT    /users/:user_id/posts/:id(.:format)      {:controller=>"posts", :action=>"update"}
               DELETE /users/:user_id/posts/:id(.:format)      {:controller=>"posts", :action=>"destroy"}

ОБНОВЛЕНИЕ 4

Исходя из приведенных ниже рекомендаций ScottD, мой код теперь выглядит следующим образом:

<%= link_to_remote "- Delete Post", :url => user_post_url(@user,c), :method => :delete, :confirm => "Are you sure you want to permanently delete this post?", :success => "$(this).up('.postS').remove();" %>  

Это решает большую часть моей проблемы, но действие удаления javascript все еще не запускается. Другими словами, я нажимаю на ссылку удаления. Пост удаляется из базы данных, но остается на экране. Когда я перезагружаю страницу, сообщение исчезает. Итак, проблема в том, что следующая часть не запускается:: success => "$ (this) .up ('. PostS'). Remove ();"

Вот что происходит в журнале, когда я нажимаю на ссылку удаления, как описано выше:

Processing PostsController#destroy (for 127.0.0.1 at 2009-12-17 11:59:18) [DELETE]  
  Parameters: {"action"=>"destroy", "authenticity_token"=>"ccF1QNCGs9IlvbIYWwmQmcbi7kROgQsTZjM1dM687xA=", "_method"=>"delete", "id"=>"14", "controller"=>"posts", "user_id"=>"1"}  
  User Columns (3.2ms)   SHOW FIELDS FROM `users`
  User Load (29.6ms)   SELECT * FROM `users` WHERE (`users`.`id` = 1) ORDER BY name
  Post Columns (8.7ms)   SHOW FIELDS FROM `posts`
  Post Load (1.6ms)   SELECT * FROM `posts` WHERE (`posts`.`id` = 14) 
    app/controllers/posts_controller.rb:22:in `destroy'
  SQL (0.1ms)   BEGIN
    app/controllers/posts_controller.rb:23:in `destroy'
  Post Destroy (0.5ms)   DELETE FROM `posts` WHERE `id` = 14
    app/controllers/posts_controller.rb:23:in `destroy'
  SQL (0.9ms)   COMMIT
    app/controllers/posts_controller.rb:23:in `destroy'
Redirected to http://localhost:3000/users/1
Completed in 65ms (DB: 45) | 302 Found [http://localhost/users/1/posts/14]  

Для меня это все выглядит хорошо. Так что я не уверен, почему удаление javascript не работает.

Когда я перезагружаю страницу, журнал показывает, что все загружается нормально, и сообщение исчезло (как и должно быть). Любые идеи о том, как я могу заставить удаление javascript работать?

Обновление # 5

Вот что в настоящее время генерируется в html на основе кода link_to_remote, который я использую:

<a href="#" onclick="if (confirm('Are you sure you want to permanently delete this post?')) { new Ajax.Request('http://localhost:3000/users/1/posts/18', {asynchronous:true, evalScripts:true, method:'delete', onComplete:function(request){$(this).up('.postS').remove();}, parameters:'authenticity_token=' + encodeURIComponent('ccF1QNCGs9IlvbIYWwmQmcbi7kROgQsTZjM1dM687xA=')}); }; return false;">- Delete Post</a>  

Вот что Firebug показывает в консоли, когда я нажимаю текст «удалить» на странице:

POST http://localhost:3000/users/1/posts/18  302 Moved Temporarily  
GET  http://localhost:3000/users/1 200 OK

Ответы [ 2 ]

6 голосов
/ 16 декабря 2009

Проблема в том, что вы используете link_to_function, который вызывает только функцию Javascript, но ничего не добавляет в ваше приложение. Если вы хотите сделать Ajax, попробуйте link_to_remote. Это сделает вызов AJAX, а затем позволит вам вызывать javascript на основе перехватчиков обратного вызова, таких как :success или :complete.

Пример на основе вашего образца:

<% if logged_in? && current_user == @user %>
  <%= link_to_remote "- Delete Post", :url => user_post_url(@user,c, :format => :json), :method => :delete  , :confirm => "Are you sure you want to permanetly delete this post?", :success => "$(this).up('.postS').remove();" %>                                                      
<% end %> 

Ознакомьтесь с документами Rails API для link_to_remote, чтобы получить больше примеров.

Вам также потребуется обновить ваш почтовый контроллер, чтобы отвечать на запрос на удаление из Ajax. Я использую новый камень json для рендеринга json.

def destroy
  @post = Post.find(params[:id])
  respond_to do |format|
    if @post.destroy
      format.html { redirect_to :back }
      format.json { :success => true }.as_json
    else
      flash[:notice] = "Post failed to delete."
      format.html { redirect_to :back }
      format.json { :success => false }.as_json
    end
  end
end

Обновлено для отражения рассматриваемых вложенных маршрутов.

0 голосов
/ 17 июня 2010

В случае, если вам это поможет, у меня возникла похожая проблема в моем приложении, и до сих пор я отслеживал ее до того факта, что все, кроме

:success => "$(this).up('.postS').remove();"

часть link_to_remote не работала так, как представляешь. По некоторым причинам он не находит правильный div в DOM.

Я не утверждаю, что это ваша проблема, но она может привести вас на правильный путь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...