开发者

Voting app in rails 3: how do I link to vote method?

To teach myself Rails, im building an extremely simple Voting app.

There are 2 models, Question and Option. Question has_many Options and Option belongs_to Question.

Using the standard scaffolding, I have reached a stage where you can add a question, view it, and add options to it and see these options.

What I would like to do now is add the code that increases an option.count value by one when clicking on a link. I have a vote_up method in the Option model:

class Option < ActiveRecord::Base
  validates :text, :presence => :true
  belongs_to :question

  def vote_up
    self.count += 1
  end
end

My Options controller looks like:

class OptionsController < ApplicationController
  def create
    @question = Question.find(params[:question_id])
    @option = @question.options.create(params[:option])
    redirect_to question_path(@question)
  end

end

My Question model looks like:

class Question < ActiveRecord::Base
  validates :text, :presence => {:message => 'A question normally has text...'}
  has_many :options, :dependent => :destroy


  def vote
    # Maybe the vote code will go here???
  end
end

And my Question controller has the usual new, create, edit, destroy methods that the scaffold creates. V little customisation here.

My show.html.erb view where I would like to put the link to the vote method looks like:

  <p id="notice"><%= notice %></p>
    <p>
      <b>Question <%= @question.guid %></b>:
      <%= @question.text %>
    </p>
    <% if @question.options.count == 0 %>
        <p>Shame! there are currently no options to vote on. Add some! </p>
    <% elsif @question.options.count == 1 %>
        <p>One option in a vote is a dictatorship... Maybe add some more?</p>
    <% end %>
    <h2>Options:</h2>
    <% @question.options.each do |option| %>
      <p>
        <%= option.text %>:  ** Link to vote here!
      </p>
    <% end %>

    <h2>Add an option to vote on</h2>
    <%= form_for([@question, @question.options.build]) do |f| %>
      <div class="field">
        <%= f.label :text %><br />
        <%= f.text_field :text %>
      </div>
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>

    <% if @question.options.count == 0 # Only show edit if no options saved. %> 
        <%= link_to 'Edit', edit_question_path(@question) %> |
    <% end %>
    <%= link_to 'Back', questions_path %>

So what I am trying to do is add a "v开发者_运维百科ote" link next to each option that calls the vote_up method in the options model. This is probably laughably easy, but i've hit a wall and would really appreciate any help.

Also, any suggestions on how to do this better would be welcome!

Thanks

Simon


I think @oded-harth has showed a right way, but I have two remarks:

First of all, Rails is a beautiful language and is written to simplify our developer lives ;) When programming in Rails you must never forget that. With this in mind, I want to point you to "increment()" method. So you can simply up-vote without unnecessary += 1. To down-vote use decrement(). I believe you can use it like this: option.increment(:count)

Second, I think it's a little dirty to have a whole form for a simple vote action. You can use something like this

<%= link_to "Vote Up", :url => { :action => :vote_up, :option_id => option.id }, :method => :put %>

To make it work you'll have to set your route something like this:

resources :votes
  put :vote_up
end


What I would do is make the vote_up method in the controller:

def vote_up 

option = Option.find(params[:option_id])
option.count += 1

redirect (to where do you want...)

end

And in the view I would call that method this way:

<%= form_for( option, :url => { :action => "vote_up", :option_id => option.id} ) do |f| %>
<%= f.submit("vote up") %>  
<% end %>
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜