Commit f25abd1e03aa936f7563e57d208ed2dce0a96e50
1 parent
ac6d2493
Exists in
master
and in
1 other branch
First cut at flag inside api
Showing
9 changed files
with
174 additions
and
1 deletions
Show diff stats
app/controllers/choices_controller.rb
@@ -3,6 +3,8 @@ class ChoicesController < InheritedResources::Base | @@ -3,6 +3,8 @@ class ChoicesController < InheritedResources::Base | ||
3 | actions :show, :index, :create, :update | 3 | actions :show, :index, :create, :update |
4 | belongs_to :question | 4 | belongs_to :question |
5 | has_scope :active, :boolean => true, :only => :index | 5 | has_scope :active, :boolean => true, :only => :index |
6 | + | ||
7 | + before_filter :authenticate, :only => [:flag] | ||
6 | #caches_page :index | 8 | #caches_page :index |
7 | 9 | ||
8 | def index | 10 | def index |
@@ -177,4 +179,36 @@ class ChoicesController < InheritedResources::Base | @@ -177,4 +179,36 @@ class ChoicesController < InheritedResources::Base | ||
177 | end | 179 | end |
178 | end | 180 | end |
179 | end | 181 | end |
182 | + | ||
183 | + def flag | ||
184 | + @question = current_user.questions.find(params[:question_id]) | ||
185 | + @choice = @question.choices.find(params[:id]) | ||
186 | + | ||
187 | + flag_params = {:choice_id => params[:id].to_i, :question_id => params[:question_id].to_i, :site_id => current_user.id} | ||
188 | + | ||
189 | + if explanation = params[:explanation] | ||
190 | + flag_params.merge!({:explanation => explanation}) | ||
191 | + | ||
192 | + end | ||
193 | + if visitor_identifier = params[:visitor_identifier] | ||
194 | + visitor = current_user.visitors.find_or_create_by_identifier(visitor_identifier) | ||
195 | + flag_params.merge!({:visitor_id => visitor.id}) | ||
196 | + end | ||
197 | + respond_to do |format| | ||
198 | + if @choice.deactivate! | ||
199 | + flag = Flag.create!(flag_params) | ||
200 | + puts "I AM CREATING A FLAG FOR #{@choice.inspect}" | ||
201 | + format.xml { render :xml => @choice.to_xml, :status => :created } | ||
202 | + format.json { render :json => @choice.to_json, :status => :created } | ||
203 | + else | ||
204 | + format.xml { render :xml => @choice.errors, :status => :unprocessable_entity } | ||
205 | + format.json { render :json => @choice.to_json } | ||
206 | + end | ||
207 | + end | ||
208 | + | ||
209 | + end | ||
210 | + | ||
211 | + | ||
212 | + | ||
180 | end | 213 | end |
214 | + |
app/models/choice.rb
@@ -10,6 +10,7 @@ class Choice < ActiveRecord::Base | @@ -10,6 +10,7 @@ class Choice < ActiveRecord::Base | ||
10 | #validates_length_of :item, :maximum => 140 | 10 | #validates_length_of :item, :maximum => 140 |
11 | 11 | ||
12 | has_many :votes | 12 | has_many :votes |
13 | + has_many :flags | ||
13 | has_many :prompts_on_the_left, :class_name => "Prompt", :foreign_key => "left_choice_id" | 14 | has_many :prompts_on_the_left, :class_name => "Prompt", :foreign_key => "left_choice_id" |
14 | has_many :prompts_on_the_right, :class_name => "Prompt", :foreign_key => "right_choice_id" | 15 | has_many :prompts_on_the_right, :class_name => "Prompt", :foreign_key => "right_choice_id" |
15 | named_scope :active, :conditions => { :active => true } | 16 | named_scope :active, :conditions => { :active => true } |
config/routes.rb
@@ -15,7 +15,7 @@ ActionController::Routing::Routes.draw do |map| | @@ -15,7 +15,7 @@ ActionController::Routing::Routes.draw do |map| | ||
15 | question.resources :items | 15 | question.resources :items |
16 | question.resources :prompts, :member => {:vote_left => :post, :vote_right => :post, :skip => :post, :vote => :post}, | 16 | question.resources :prompts, :member => {:vote_left => :post, :vote_right => :post, :skip => :post, :vote => :post}, |
17 | :collection => {:single => :get, :index => :get} | 17 | :collection => {:single => :get, :index => :get} |
18 | - question.resources :choices, :member => { :activate => :put, :suspend => :put, :update_from_abroad => :put, :deactivate_from_abroad => :put }, :collection => {:create_from_abroad => :post} | 18 | + question.resources :choices, :member => { :activate => :put, :suspend => :put, :update_from_abroad => :put, :deactivate_from_abroad => :put, :flag => :put}, :collection => {:create_from_abroad => :post} |
19 | end | 19 | end |
20 | map.resources :algorithms | 20 | map.resources :algorithms |
21 | map.connect "/questions/:question_id/prompts/:id/vote/:index", :controller => 'prompts', :action => 'vote' | 21 | map.connect "/questions/:question_id/prompts/:id/vote/:index", :controller => 'prompts', :action => 'vote' |
@@ -0,0 +1,17 @@ | @@ -0,0 +1,17 @@ | ||
1 | +class CreateFlags < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :flags do |table| | ||
4 | + table.string :explanation, :default => "" | ||
5 | + table.integer :visitor_id | ||
6 | + table.integer :choice_id | ||
7 | + table.integer :question_id | ||
8 | + table.integer :site_id | ||
9 | + table.timestamps | ||
10 | + end | ||
11 | + | ||
12 | + end | ||
13 | + | ||
14 | + def self.down | ||
15 | + drop_table :flags | ||
16 | + end | ||
17 | +end |
@@ -0,0 +1,80 @@ | @@ -0,0 +1,80 @@ | ||
1 | +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') | ||
2 | + | ||
3 | +describe ChoicesController do | ||
4 | + | ||
5 | + def sign_in_as(user) | ||
6 | + @controller.current_user = user | ||
7 | + return user | ||
8 | + end | ||
9 | + # | ||
10 | + before(:each) do | ||
11 | + sign_in_as(@user = Factory(:email_confirmed_user)) | ||
12 | + end | ||
13 | + # | ||
14 | + def mock_question(stubs={}) | ||
15 | + @mock_question ||= mock_model(Question, stubs) | ||
16 | + end | ||
17 | + | ||
18 | + def mock_prompt(stubs={}) | ||
19 | + @mock_prompt ||= mock_model(Prompt, stubs) | ||
20 | + end | ||
21 | + | ||
22 | + def mock_appearance(stubs={}) | ||
23 | + @mock_appearance||= mock_model(Appearance, stubs) | ||
24 | + end | ||
25 | + | ||
26 | + def mock_visitor(stubs={}) | ||
27 | + @mock_visitor||= mock_model(Visitor, stubs) | ||
28 | + end | ||
29 | + | ||
30 | + def mock_choice(stubs={}) | ||
31 | + @mock_choice||= mock_model(Choice, stubs) | ||
32 | + end | ||
33 | + | ||
34 | + def mock_flag(stubs={}) | ||
35 | + @mock_flag ||= mock_model(Flag, stubs) | ||
36 | + end | ||
37 | + | ||
38 | + describe "PUT flag" do | ||
39 | + before(:each) do | ||
40 | + question_list = [mock_question] | ||
41 | + @user.stub!(:questions).and_return(question_list) | ||
42 | + question_list.stub!(:find).with("37").and_return(mock_question) | ||
43 | + | ||
44 | + choice_list = [mock_choice] | ||
45 | + mock_question.stub!(:choices).and_return(choice_list) | ||
46 | + choice_list.stub!(:find).with("123").and_return(mock_choice) | ||
47 | + mock_choice.should_receive(:deactivate!).and_return(true) | ||
48 | + | ||
49 | + | ||
50 | + end | ||
51 | + | ||
52 | + it "deactives a choice when a flag request is sent" do | ||
53 | + Flag.should_receive(:create!).with({:choice_id => 123, :question_id => 37, :site_id => @user.id}) | ||
54 | + put :flag, :id => 123, :question_id => 37 | ||
55 | + | ||
56 | + assigns[:choice].should == mock_choice | ||
57 | + end | ||
58 | + | ||
59 | + it "adds explanation params to flag if sent" do | ||
60 | + Flag.should_receive(:create!).with({:choice_id => 123, :question_id => 37, :site_id => @user.id, :explanation => "This is offensive"}) | ||
61 | + put :flag, :id => 123, :question_id => 37 , :explanation => "This is offensive" | ||
62 | + | ||
63 | + assigns[:choice].should == mock_choice | ||
64 | + end | ||
65 | + | ||
66 | + it "adds visitor_id params to flag if sent" do | ||
67 | + @visitor_identifier = "somelongunique32charstring" | ||
68 | + visitor_list = [mock_visitor] | ||
69 | + @user.stub!(:visitors).and_return(visitor_list) | ||
70 | + visitor_list.should_receive(:find_or_create_by_identifier).with(@visitor_identifier).and_return(mock_visitor) | ||
71 | + | ||
72 | + Flag.should_receive(:create!).with({:choice_id => 123, :question_id => 37, :site_id => @user.id, :explanation => "This is offensive", :visitor_id => mock_visitor.id}) | ||
73 | + | ||
74 | + put :flag, :id => 123, :question_id => 37 , :explanation => "This is offensive", :visitor_identifier => @visitor_identifier | ||
75 | + | ||
76 | + assigns[:choice].should == mock_choice | ||
77 | + end | ||
78 | + end | ||
79 | + | ||
80 | +end |
spec/models/choice_spec.rb
@@ -4,6 +4,7 @@ describe Choice do | @@ -4,6 +4,7 @@ describe Choice do | ||
4 | 4 | ||
5 | it {should belong_to :question} | 5 | it {should belong_to :question} |
6 | it {should belong_to :item} | 6 | it {should belong_to :item} |
7 | + it {should have_many :flags} | ||
7 | it {should validate_presence_of :question} | 8 | it {should validate_presence_of :question} |
8 | 9 | ||
9 | before(:each) do | 10 | before(:each) do |
@@ -27,4 +28,10 @@ describe Choice do | @@ -27,4 +28,10 @@ describe Choice do | ||
27 | choice1 = Choice.create!(@valid_attributes.merge(:data => '1234')) | 28 | choice1 = Choice.create!(@valid_attributes.merge(:data => '1234')) |
28 | @question.prompts.should_not be_empty | 29 | @question.prompts.should_not be_empty |
29 | end | 30 | end |
31 | + | ||
32 | + it "should deactivate a choice" do | ||
33 | + choice1 = Choice.create!(@valid_attributes.merge(:data => '1234')) | ||
34 | + choice1.deactivate! | ||
35 | + choice1.should_not be_active | ||
36 | + end | ||
30 | end | 37 | end |
@@ -0,0 +1,24 @@ | @@ -0,0 +1,24 @@ | ||
1 | +require 'spec_helper' | ||
2 | + | ||
3 | +describe Flag do | ||
4 | + it {should belong_to :question} | ||
5 | + it {should belong_to :choice} | ||
6 | + it {should belong_to :site} | ||
7 | + it {should belong_to :visitor} | ||
8 | + it {should validate_presence_of :choice_id} | ||
9 | + it {should validate_presence_of :question_id} | ||
10 | + | ||
11 | + before(:each) do | ||
12 | + @valid_attributes = { | ||
13 | + :explanation => "value for explanation", | ||
14 | + :visitor_id => 1, | ||
15 | + :choice_id => 1, | ||
16 | + :question_id => 1, | ||
17 | + :site_id => 1 | ||
18 | + } | ||
19 | + end | ||
20 | + | ||
21 | + it "should create a new instance given valid attributes" do | ||
22 | + Flag.create!(@valid_attributes) | ||
23 | + end | ||
24 | +end |