2012-01-23 6 views
0

ありがとうございます。私はレールを学んでおり、ウェブアプリケーションを構築しています。私は「安心して」、そのような言葉で考えようとしています。したがって、私は自分のデータをリソースとして見ています。私がマイクロポストと呼ばれるテーブルを持っていて、何人の人がアップ投票したのかダウン投票したのかを数える「投票」という列があるとします。ビューでこれはRailsアプリケーションの属性を更新するための「適切な」方法ですか?

:ユーザーがボタンをクリックすると、

<td> 
    <%= form_for feed_item do |f| %> 
     <div><%= hidden_field_tag 'todo', 'upvote' %></div> 
     <div class="action"><%= f.submit "Up" %></div> 
    <% end %> 
</td> 
<td> 
    <%= form_for feed_item do |f| %> 
     <div><%= hidden_field_tag 'todo', 'downvote' %></div> 
     <div class="action"><%= f.submit "Down" %></div> 
    <% end %> 
<td> 

は、それはコントローラの「更新」メソッドを呼び出して、私はそれがこのように取り組んでいます。そして、コントローラで、私はアップデートでこれを持っている:

def update 
    @todo = params[:todo] 
    if @todo == "upvote" 
     Micropost.find(params[:id]).increment!(:votes) 
     flash[:success] = "Increase micropost vote" 
     redirect_to root_path 
    elsif @todo == "downvote" 
     Micropost.find(params[:id]).decrement!(:votes) 
     flash[:success] = "Decrease micropost vote" 
     redirect_to root_path 
    else 
     redirect_to root_path 
    end 
    end 

は私が押されたボタンが「upvote」または「downvote」であるかどうかを知るために隠しフィールドを渡します。したがって、他のマイクロポスト属性を変更したい場合は、より多くのif文が必要です。私はこの権利をしているとは思わない。 DBの属性またはレコードを更新するためのレールの方法は何ですか?

ありがとうございます!

答えて

3

よりRESTfulなリワーク通話、これらのタイプのそれぞれを受け取るために、理想的には、別のルートとしてあなたの行動のそれぞれを定義し、あなたがしなければならない場合は、GET、POSTすることです:

before_filter :load_micropost 

def load_micropost 
    @micropost = Micropost.find(params[:id]) 
end 

def upvote 
    @micropost.increment!(:votes) 
    flash[:success] = "Increase micropost vote" 
    redirect_to root_path 
end 

def downvote 
    @micropost.decrement!(:votes) 
    flash[:success] = "Decrease micropost vote" 
    redirect_to root_path 
end 

は、作成することを忘れないでくださいモデルのルーチンの読み込みを処理する方法はload_micropostです。あなたのメソッドについていくつかの異なる呼び出しがあって、将来のある時点で調整が必要な場合があります。

あなたはこのように、これらのルートをしたい:

map.resources :microposts, 
    :member => { 
    :upvote => :post, 
    :downvote => :post 
    } 

あなたがテーブルを追加して検討する必要がありますもう一つは、あなたが監査し、必要に応じて調整することができますので、何のために投票したレコード。これにより、卸売価格を再設定することなく、不正行為を解消することが容易になります。

<%= link_to('Upvote', upvote_micropost_path(feed_item), :method => :post) %> 

これは、要素が必要とされるあらゆる形式のレンダリングの世話をします。

また、あなたは彼らのために頼む場合は、POST、単純なリンクを作成することができます。

+0

'GET'と破壊的なアクション?それについて考えることさえしないでください! RESTは更新のために 'PUT'を予約します。この場合、' POST'よりもIMOが優れています。 –

+0

'PUT'は更新用です、' POST'は一般的には新しいレコードを作成します。一般に投票は一度しか作成されず、調整されることはめったにないので、ここでは 'POST'が適切かもしれません。リンクプリローダーなどのために、「GET」が問題になっているのは間違いありません。そういうわけで、私はあなたが "必要なら"と言ったのです。 – tadman

+1

ありがとう!私はRails 3を使用していますので、putとあなたのソリューションは動作します – okysabeni

4

追加のアクションupvote/downvote(またはちょうどvote)を作成し、memberリソースとして追加します。 RESTは実際にCRUDに限定されず、いつでも他のアクションを追加できます。

map.resources :my_resource, :member => {:upvote => :put}

、その後、あなたはupvote_my_resource_pathを使用して、updateで台無しにしないように、あなたのコントローラにupvoteアクションを追加することができます。例えばRailsの2に、それは次のようになります。

+0

有効な方法はありますが、純粋にRESTfulではありません。 RESTが常に答えだとは思いません。 – DGM

+0

私の場合は、Rails 3.0を使用していますが、このように見えますか?リソース:マイクロポストは、メンバーが置くかどうか:upvote、:downvote end end?ありがとう – okysabeni

0

まず、お使いのモデルに仮想属性を追加します。

Class Micropost 
    def change_vote(value) 
    if value == 'upvote' 
     votes += 1 
    elseif value == 'downvote' 
     votes -= 1 
    end 
    end 
end 

を、あなたのフォームで、それはフォームヘルパーを使用していてください:(feed_itemがmicropostであると仮定)

<%= form_for feed_item do |f| %> 
    <div><%= f.hidden_field 'change_vote', 'upvote' %></div> 
    <div class="action"><%= f.submit "Up" %></div> 
<% end %> 

これにより、REST用の適切な形式でリソースが戻されます。すべてのコントローラが実行する必要がある。もちろん

def update 
    @mp = Micropost.find(params[:id]) 
    @mp.update_attributes(params[:micropost]) 
    if params[:micropost][:change_vote] == 'upvote' 
    flash[:success] = "Increase micropost vote" 
    else 
    flash[:success] = "Decrease micropost vote" 
    end 
    redirect_to root_url 
end 

、これはまだ検討の検証とそのようになりませんが、それはそれを

+0

これは、少なくともRESTfulな観点から、元の質問と全く同じものだと思います。本当にRESTfulな方法は、おそらく投票数を持つスピナーを作成し、 'edit'アクションでそれを表示し、それを他の属性と一緒に更新リクエストとして送り返すことでしょう。もう一つの疑問は、そのようなことが必要な人です。 –

+0

元の投稿がリクエストに実際のリソースを渡さなかったため、元の投稿は安らかではなかったという意味では、全く同じではありません。それよりも、それは必然的にロジックをモデルに入れるためにリファクタリングされます。私のやり方では、他の属性や投票を更新するかどうかにかかわらず、更新呼び出しを使用できます。それはすべて更新されているリソースです。 – DGM

+0

実際に何が行われているのか混同するほど、無駄な複製がたくさんあります。 'attr_accessor'を使用して保存時の動作をトリガする方法は、怠惰で危険です。 – tadman

1

を行うためのRESTfulな方法だ、私は別のモデルに投票を救うVote(micropost_id, user_id, positive, created_at)も、などのフィールドに追加します。そのようなフィールドには、(count_up_votes - count_down_votes)が含まれます。

その後、マイクロポストの下に新しいリソースvotesを作成しますので、micropost_votes_pathのようなルートがあります。

デザインを選択すると、ユーザーは投票を取り消すことができ、ユーザーごとに複数の投票を防止することができます。

関連する問題