Commit 73c400bbb76b8d7e7f02783fc4aa6b3165575008
1 parent
47e920d6
Exists in
master
and in
1 other branch
Refactoring skip and vote to use polymorphism in appearance
Showing
11 changed files
with
39 additions
and
15 deletions
Show diff stats
app/models/appearance.rb
... | ... | @@ -3,12 +3,9 @@ class Appearance < ActiveRecord::Base |
3 | 3 | belongs_to :prompt |
4 | 4 | belongs_to :question |
5 | 5 | |
6 | - #technically, an appearance should either one vote or one skip, not one of both objects, but these declarations provide some useful helper methods | |
7 | - # we could refactor this to use rails polymorphism, but currently the foreign key is stored in the vote and skip object | |
8 | - has_one :vote | |
9 | - has_one :skip | |
6 | + belongs_to :answerable, :polymorphic => true | |
10 | 7 | |
11 | 8 | def answered? |
12 | - vote || skip | |
9 | + !self.answerable_id.nil? | |
13 | 10 | end |
14 | 11 | end | ... | ... |
app/models/skip.rb
app/models/user.rb
... | ... | @@ -41,8 +41,7 @@ class User < ActiveRecord::Base |
41 | 41 | end |
42 | 42 | |
43 | 43 | def record_appearance(visitor, prompt) |
44 | - a = Appearance.create(:voter => visitor, :prompt => prompt, :question_id => prompt.question_id, | |
45 | - :lookup => Digest::MD5.hexdigest(rand(10000000000).to_s + visitor.id.to_s + prompt.id.to_s) ) | |
44 | + a = Appearance.create(:voter => visitor, :prompt => prompt, :question_id => prompt.question_id, :site_id => self.id, :lookup => Digest::MD5.hexdigest(rand(10000000000).to_s + visitor.id.to_s + prompt.id.to_s) ) | |
46 | 45 | end |
47 | 46 | |
48 | 47 | ... | ... |
app/models/visitor.rb
... | ... | @@ -25,7 +25,7 @@ class Visitor < ActiveRecord::Base |
25 | 25 | if options[:appearance_lookup] |
26 | 26 | @appearance = prompt.appearances.find_by_lookup(options.delete(:appearance_lookup)) |
27 | 27 | return nil unless @appearance # don't allow people to fake appearance lookups |
28 | - options.merge!(:appearance_id => @appearance.id) | |
28 | + options.merge!(:appearance => @appearance) | |
29 | 29 | end |
30 | 30 | |
31 | 31 | choice = prompt.choices[ordinality] #we need to guarantee that the choices are in the right order (by position) |
... | ... | @@ -45,7 +45,7 @@ class Visitor < ActiveRecord::Base |
45 | 45 | if options[:appearance_lookup] |
46 | 46 | @appearance = prompt.appearances.find_by_lookup(options.delete(:appearance_lookup)) |
47 | 47 | return nil unless @appearance |
48 | - options.merge!(:appearance_id => @appearance.id) | |
48 | + options.merge!(:appearance => @appearance) | |
49 | 49 | end |
50 | 50 | |
51 | 51 | options.merge!(:question_id => prompt.question_id, :prompt_id => prompt.id, :skipper_id => self.id) | ... | ... |
app/models/vote.rb
... | ... | @@ -11,7 +11,7 @@ class Vote < ActiveRecord::Base |
11 | 11 | belongs_to :prompt, :counter_cache => true |
12 | 12 | belongs_to :choice, :counter_cache => true |
13 | 13 | belongs_to :loser_choice, :class_name => "Choice", :foreign_key => "loser_choice_id" |
14 | - belongs_to :appearance | |
14 | + has_one :appearance, :as => :answerable | |
15 | 15 | |
16 | 16 | named_scope :recent, lambda { |*args| {:conditions => ["created_at > ?", (args.first || Date.today.beginning_of_day)]} } |
17 | 17 | named_scope :with_question, lambda { |*args| {:conditions => {:question_id => args.first }} } | ... | ... |
db/migrate/20100714160406_add_polymorphic_answerable_to_appearance.rb
0 → 100644
... | ... | @@ -0,0 +1,11 @@ |
1 | +class AddPolymorphicAnswerableToAppearance < ActiveRecord::Migration | |
2 | + def self.up | |
3 | + add_column :appearances, :answerable_id, :integer | |
4 | + add_column :appearances, :answerable_type, :string | |
5 | + end | |
6 | + | |
7 | + def self.down | |
8 | + remove_column :appearances, :answerable_id | |
9 | + remove_column :appearances, :answerable_type | |
10 | + end | |
11 | +end | ... | ... |
db/schema.rb
... | ... | @@ -9,7 +9,7 @@ |
9 | 9 | # |
10 | 10 | # It's strongly recommended to check this file into your version control system. |
11 | 11 | |
12 | -ActiveRecord::Schema.define(:version => 20100621164536) do | |
12 | +ActiveRecord::Schema.define(:version => 20100714160406) do | |
13 | 13 | |
14 | 14 | create_table "appearances", :force => true do |t| |
15 | 15 | t.integer "voter_id" |
... | ... | @@ -19,6 +19,8 @@ ActiveRecord::Schema.define(:version => 20100621164536) do |
19 | 19 | t.string "lookup" |
20 | 20 | t.datetime "created_at" |
21 | 21 | t.datetime "updated_at" |
22 | + t.integer "answerable_id" | |
23 | + t.string "answerable_type" | |
22 | 24 | end |
23 | 25 | |
24 | 26 | add_index "appearances", ["lookup"], :name => "index_appearances_on_lookup" | ... | ... |
lib/tasks/prune_db.rake
... | ... | @@ -62,5 +62,20 @@ namespace :prune_db do |
62 | 62 | end |
63 | 63 | end |
64 | 64 | end |
65 | + | |
66 | + task(:move_vote_and_skip_ids_to_appearance => :environment) do | |
67 | + Vote.find_each do |v| | |
68 | + @appearance = Appearance.find(v.appearance_id) | |
69 | + @appearance.answerable = v | |
70 | + @appearance.save | |
71 | + | |
72 | + end | |
73 | + Skip.find_each do |s| | |
74 | + @appearance = Appearance.find(s.appearance_id) | |
75 | + @appearance.answerable = s | |
76 | + @appearance.save | |
77 | + end | |
78 | + end | |
79 | + | |
65 | 80 | |
66 | 81 | end | ... | ... |
spec/models/appearance_spec.rb
... | ... | @@ -7,8 +7,7 @@ describe Appearance do |
7 | 7 | it {should belong_to :voter} |
8 | 8 | it {should belong_to :prompt} |
9 | 9 | it {should belong_to :question} |
10 | - it {should have_one :vote} | |
11 | - it {should have_one :skip} | |
10 | + it {should belong_to :answerable} | |
12 | 11 | |
13 | 12 | it "should create a new instance given valid attributes" do |
14 | 13 | Appearance.create!(@valid_attributes) | ... | ... |
spec/models/skip_spec.rb
spec/models/vote_spec.rb
... | ... | @@ -6,7 +6,7 @@ describe Vote do |
6 | 6 | it {should belong_to :prompt} |
7 | 7 | it {should belong_to :choice} |
8 | 8 | it {should belong_to :loser_choice} |
9 | - it {should belong_to :appearance} | |
9 | + it {should have_one :appearance} | |
10 | 10 | |
11 | 11 | before(:each) do |
12 | 12 | @question = Factory.create(:aoi_question) | ... | ... |