2009-04-29 10 views
3

私のブログアプリケーションでは、一部の投稿が抜粋として表示されます。つまり、ユーザーは最初の500文字を見て、リンクをクリックして投稿全体を表示できます。RailsのビルトインヘルパーなしでAJAXを使用するためのベストプラクティス?

<% href = url_for post_path(:id => post) %> 

<h1 class="title"><%= post.title %></h1> 
<h2 class="published_on"><%= post.author %> wrote this <%= time_ago_in_words(post.published_on)%> ago</h2> 
<div class="body"> 
    <% if defined?(length) %> 
    <%= truncate_html(post.body, :length => length, :omission => "&hellip;<h1><a class='more' href=\"#{href}\">Click here for more!</a></h1>") %> 
    <% else %> 
    <%= post.body %> 
    <% end %> 
</div> 

ただし、「ここをクリックしてください!」ユーザーを別のページに移動させると、残りの投稿をインラインで表示することができます私は、AJAXを行うために私application.jsにこのdiv要素のIDを使用

<div class="post" id="post_<%= post.id %>"> 
    <%= render :partial => 'post_content', :locals => { :post => post, :length => 500 } %> 
</div> 

:現在、私は次のdivに上記のスニペットを置くことによって、これを実施してきた

$(document).ready(function() { 

    $("a.more").click(function() { 
    var url = $(this).attr('href'); 
    var id = url.split("/")[2] 
    $.get(url, null, function(data) { 
     $("#post_" + id).html(data);  
    }); 
    return false; 
    }); 

}); 

これは明らかにうんざりです - 私はjavascriptがリンクのhrefの投稿のIDの場所に依存することを望んでいませんが、javascriptがどの投稿を取得しているかを知るための方法はわかりませんdivを挿入する必要があります。

これを行うにはどうすればよいですか?レールのAJAXヘルパーを使用するだけに戻すべきですか?

+0

あなたはレールのヘルパーを使用したくないのはなぜ? – marcgg

+0

私のjavascriptを控えめに/プレゼンテーションロジックから外しておきますか?一方、それは最も悪い選択肢かもしれない。 「レールヘルパーを使用する」が答えであれば、そうすることができます。 –

+0

私はあなたにレールヘルパーの有無にかかわらず2つの解決策を教えました – marcgg

答えて

7

Horace、あなたは正しいです。 Railsヘルパーはまったく必要ありません。邪魔にならないJavaScript Nirvanaを実現するには、それらを避けるためにうまくいくでしょう。(ごめんなさいMarc!)

Unobstrusive JSは、可能であれば埋め込みJSを避ける​​ことを意味します。確かに、物事を疎結合させようとするが、完全には分離しない。あなたが私たちに与えた例では、HREFからのURLがあるため、簡単です。あなたのJSは、どのようにリクエストするかについて「知る」必要はありません。

HREFのリンクを盲目的に送信し、Railsにajaxレスポンス(つまりレイアウトなし)を返す方法です。

ソリューション:

<!------- Your HTML ------> 
<h1 class="title">Schwein Flu Strikes Again</h1> 
<h2 class="published_on">B.Obama wrote this 2 seconds ago</h2> 
<div class="body"> 
    SUMMARY SUMMARY 
    <h1><a class='more' href="/post/1234">Click here for more!</a></h1> 
</div>
/********* Your JavaScript ***********/ 
$(document).ready(function() {

$("a.more").click(function() { $containing_div = $(e).parents('div.body'); var url = $(this).attr('href'); $.ajax({ beforeSend : function(request) { request.setRequestHeader("Accept", "text/javascript"); }, /* Included so Rails responds via "format.js" */ success : function(response) { $(containing_div).empty.append(response); }, type : 'get', url : url }); return false; });

});

########### Your Controller ########### 
def show 
    @article = Post.find(param[:id]) 
    respond_to do |format| 
    format.html { render :action => "show" and return } 
    format.js { render :partial => "post_content", :layout => false and return } 
    end 
end

これはまた、あなたが処理するのに似たRESTfulなルートまたはを持っていると仮定し/ポスト/:ID

そして、我々が行われています!私はそれが私たち全員のためにあると信じています。 :D

+0

ありがとうございます - アンカーの両親を反復することによって挿入のためのターゲットをつかんで私が探していたトリックです。 (実際には、ajaxSetup呼び出しの一環として "setRequestHeader"を実行して、一度やり直すだけでよいでしょう)。 –

+0

こんにちはHorace、私はajaxSetup呼び出しについてのあなたのコメントに同意しますが、私のアプリでうまく動作していないので、私はそれを取り出した。もう一度それを調べなければならないだろう。あなたのアプリにも幸運があり、邪魔にならないJS! – pchap10k

0

私の意見では、この種の問題については、レールのヘルパーを使用するべきです。より多くのリンクは次のようになり

My post bla bla bla <span id="more_of<%=post.id%>">more</span> 

<%= link_to_remote("more",:update => "more_of_#{your_post.id}",:url =>{:controller => "myposts", :action=>"show_more", :id => your_post.id}, %> 

とコントローラのようなものだろう:

post = Post.find_by_id(params[:id]) 
render :text => post.content.slice(100..post.content.size) 

にすることができ、他の方法を

HTMLは次のように行くだろうすべてをロードして非表示にしてもいいです:

あなたがレールを回避する正当な理由がない限り行くための最善の方法だろう私には3210
bla bla bla this is my post blah <div style="display:none" onclick="this.style.display='block';">and this is the rest of the article</div> 

(divタグのonclickのは、IEで壊すかもしれないが、これはあなたのアイデアを与えることです)

ヘルパー。

希望があれば

1

この場合、私はAJAXコールをまったく持っていないと思います。あなたはすでにpost.bodyに元の投稿の全コンテンツを持っています(dbから500文字しか取得しませんでした).Ajax呼び出しを行うためにJQueryを使用するのではなく、500文字を超えるコンテンツを非表示にしてから、 'more'リンクをクリックすると、divの残りの部分が表示されます。これをクライアント側で完全に行い、ajaxを自分で節約することができます。あなたの部分で

<div class="body"> 
    <%= post.body %> 
</div> 

あなたはJQuery:

var fullText = $('div.body').html(); 
$('div.body').html(fullText.slice(0,499) + '<a class="more" href=\"#\">Click here for more!</a>'); 
$('a.more').live('click', function(event) { 
    this.parent().html(fullText); 
    return false; 
} 
関連する問題