diff --git a/app/models/forum_post.rb b/app/models/forum_post.rb new file mode 100644 index 000000000..597dfb6fb --- /dev/null +++ b/app/models/forum_post.rb @@ -0,0 +1,12 @@ +class ForumPost < ActiveRecord::Base + attr_accessible :body, :topic_id + belongs_to :creator, :class_name => "User" + belongs_to :topic, :class_name => "ForumTopic" + after_save :update_topic_updated_at + validates_presence_of :body, :topic_id, :creator_id + scope :search_body, lambda {|body| where(["text_index @@ plainto_tsquery(?)", body])} + + def update_topic_updated_at + topic.touch + end +end diff --git a/app/models/forum_topic.rb b/app/models/forum_topic.rb new file mode 100644 index 000000000..f1e45aa14 --- /dev/null +++ b/app/models/forum_topic.rb @@ -0,0 +1,7 @@ +class ForumTopic < ActiveRecord::Base + attr_accessible :title + belongs_to :creator, :class_name => "User" + has_many :posts, :class_name => "ForumPost", :order => "forum_posts.id asc" + validates_presence_of :title, :creator_id + scope :search_title, lambda {|title| where(["text_index @@ plainto_tsquery(?)", title])} +end diff --git a/db/development_structure.sql b/db/development_structure.sql index fe2faece1..352a12a03 100644 --- a/db/development_structure.sql +++ b/db/development_structure.sql @@ -367,6 +367,7 @@ CREATE TABLE dmails ( body text NOT NULL, message_index tsvector NOT NULL, is_read boolean DEFAULT false NOT NULL, + is_deleted boolean DEFAULT false NOT NULL, created_at timestamp without time zone, updated_at timestamp without time zone ); @@ -691,6 +692,76 @@ CREATE SEQUENCE favorites_9_id_seq ALTER SEQUENCE favorites_9_id_seq OWNED BY favorites_9.id; +-- +-- Name: forum_posts; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE forum_posts ( + id integer NOT NULL, + topic_id integer NOT NULL, + creator_id integer NOT NULL, + body text NOT NULL, + text_index tsvector NOT NULL, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: forum_posts_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE forum_posts_id_seq + START WITH 1 + INCREMENT BY 1 + NO MAXVALUE + NO MINVALUE + CACHE 1; + + +-- +-- Name: forum_posts_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE forum_posts_id_seq OWNED BY forum_posts.id; + + +-- +-- Name: forum_topics; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE forum_topics ( + id integer NOT NULL, + creator_id integer NOT NULL, + title character varying(255) NOT NULL, + response_count integer DEFAULT 0 NOT NULL, + is_sticky boolean DEFAULT false NOT NULL, + is_locked boolean DEFAULT false NOT NULL, + text_index tsvector NOT NULL, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: forum_topics_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE forum_topics_id_seq + START WITH 1 + INCREMENT BY 1 + NO MAXVALUE + NO MINVALUE + CACHE 1; + + +-- +-- Name: forum_topics_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE forum_topics_id_seq OWNED BY forum_topics.id; + + -- -- Name: pool_versions; Type: TABLE; Schema: public; Owner: -; Tablespace: -- @@ -1360,6 +1431,20 @@ ALTER TABLE favorites_8 ALTER COLUMN id SET DEFAULT nextval('favorites_8_id_seq' ALTER TABLE favorites_9 ALTER COLUMN id SET DEFAULT nextval('favorites_9_id_seq'::regclass); +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE forum_posts ALTER COLUMN id SET DEFAULT nextval('forum_posts_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE forum_topics ALTER COLUMN id SET DEFAULT nextval('forum_topics_id_seq'::regclass); + + -- -- Name: id; Type: DEFAULT; Schema: public; Owner: - -- @@ -1610,6 +1695,22 @@ ALTER TABLE ONLY favorites_9 ADD CONSTRAINT favorites_9_pkey PRIMARY KEY (id); +-- +-- Name: forum_posts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY forum_posts + ADD CONSTRAINT forum_posts_pkey PRIMARY KEY (id); + + +-- +-- Name: forum_topics_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY forum_topics + ADD CONSTRAINT forum_topics_pkey PRIMARY KEY (id); + + -- -- Name: pool_versions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- @@ -2002,6 +2103,41 @@ CREATE INDEX index_favorites_9_on_post_id ON favorites_9 USING btree (post_id); CREATE INDEX index_favorites_9_on_user_id ON favorites_9 USING btree (user_id); +-- +-- Name: index_forum_posts_on_creator_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_forum_posts_on_creator_id ON forum_posts USING btree (creator_id); + + +-- +-- Name: index_forum_posts_on_text_index; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_forum_posts_on_text_index ON forum_posts USING gin (text_index); + + +-- +-- Name: index_forum_posts_on_topic_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_forum_posts_on_topic_id ON forum_posts USING btree (topic_id); + + +-- +-- Name: index_forum_topics_on_creator_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_forum_topics_on_creator_id ON forum_topics USING btree (creator_id); + + +-- +-- Name: index_forum_topics_on_text_index; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_forum_topics_on_text_index ON forum_topics USING gin (text_index); + + -- -- Name: index_pool_versions_on_pool_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- @@ -2235,6 +2371,26 @@ CREATE TRIGGER trigger_dmails_on_update EXECUTE PROCEDURE tsvector_update_trigger('message_index', 'pg_catalog.english', 'title', 'body'); +-- +-- Name: trigger_forum_posts_on_update; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER trigger_forum_posts_on_update + BEFORE INSERT OR UPDATE ON forum_posts + FOR EACH ROW + EXECUTE PROCEDURE tsvector_update_trigger('text_index', 'pg_catalog.english', 'body'); + + +-- +-- Name: trigger_forum_topics_on_update; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER trigger_forum_topics_on_update + BEFORE INSERT OR UPDATE ON forum_topics + FOR EACH ROW + EXECUTE PROCEDURE tsvector_update_trigger('text_index', 'pg_catalog.english', 'title'); + + -- -- Name: trigger_posts_on_tag_index_update; Type: TRIGGER; Schema: public; Owner: - -- @@ -2303,4 +2459,8 @@ INSERT INTO schema_migrations (version) VALUES ('20100215225710'); INSERT INTO schema_migrations (version) VALUES ('20100215230642'); -INSERT INTO schema_migrations (version) VALUES ('20100219230537'); \ No newline at end of file +INSERT INTO schema_migrations (version) VALUES ('20100219230537'); + +INSERT INTO schema_migrations (version) VALUES ('20100221003655'); + +INSERT INTO schema_migrations (version) VALUES ('20100221005812'); \ No newline at end of file diff --git a/db/migrate/20100221003655_create_forum_topics.rb b/db/migrate/20100221003655_create_forum_topics.rb new file mode 100644 index 000000000..9714dc422 --- /dev/null +++ b/db/migrate/20100221003655_create_forum_topics.rb @@ -0,0 +1,22 @@ +class CreateForumTopics < ActiveRecord::Migration + def self.up + create_table :forum_topics do |t| + t.column :creator_id, :integer, :null => false + t.column :title, :string, :null => false + t.column :response_count, :integer, :null => false, :default => 0 + t.column :is_sticky, :boolean, :null => false, :default => false + t.column :is_locked, :boolean, :null => false, :default => false + t.column :text_index, "tsvector", :null => false + t.timestamps + end + + add_index :forum_topics, :creator_id + + execute "CREATE INDEX index_forum_topics_on_text_index ON forum_topics USING GIN (text_index)" + execute "CREATE TRIGGER trigger_forum_topics_on_update BEFORE INSERT OR UPDATE ON forum_topics FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('text_index', 'pg_catalog.english', 'title')" + end + + def self.down + drop_table :forum_topics + end +end diff --git a/db/migrate/20100221005812_create_forum_posts.rb b/db/migrate/20100221005812_create_forum_posts.rb new file mode 100644 index 000000000..12d388d73 --- /dev/null +++ b/db/migrate/20100221005812_create_forum_posts.rb @@ -0,0 +1,20 @@ +class CreateForumPosts < ActiveRecord::Migration + def self.up + create_table :forum_posts do |t| + t.column :topic_id, :integer, :null => false + t.column :creator_id, :integer, :null => false + t.column :body, :text, :null => false + t.column :text_index, "tsvector", :null => false + t.timestamps + end + + add_index :forum_posts, :topic_id + add_index :forum_posts, :creator_id + execute "CREATE INDEX index_forum_posts_on_text_index ON forum_posts USING GIN (text_index)" + execute "CREATE TRIGGER trigger_forum_posts_on_update BEFORE INSERT OR UPDATE ON forum_posts FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('text_index', 'pg_catalog.english', 'body')" + end + + def self.down + drop_table :forum_posts + end +end diff --git a/test/factories/forum_post.rb b/test/factories/forum_post.rb new file mode 100644 index 000000000..2b491e82a --- /dev/null +++ b/test/factories/forum_post.rb @@ -0,0 +1,4 @@ +Factory.define(:forum_post) do |f| + f.creator {|x| x.association(:user)} + f.body {Faker::Lorem.sentences} +end diff --git a/test/factories/forum_topic.rb b/test/factories/forum_topic.rb new file mode 100644 index 000000000..ba053c9ff --- /dev/null +++ b/test/factories/forum_topic.rb @@ -0,0 +1,6 @@ +Factory.define(:forum_topic) do |f| + f.creator {|x| x.association(:user)} + f.title {Faker::Lorem.words} + f.is_sticky false + f.is_locked false +end diff --git a/test/fixtures/forum_posts.yml b/test/fixtures/forum_posts.yml new file mode 100644 index 000000000..289334110 --- /dev/null +++ b/test/fixtures/forum_posts.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/fixtures/forum_topics.yml b/test/fixtures/forum_topics.yml new file mode 100644 index 000000000..289334110 --- /dev/null +++ b/test/fixtures/forum_topics.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/unit/forum_post_test.rb b/test/unit/forum_post_test.rb new file mode 100644 index 000000000..54c0c3959 --- /dev/null +++ b/test/unit/forum_post_test.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class ForumPostTest < ActiveSupport::TestCase + context "A forum post" do + should "update its parent when saved" do + topic = Factory.create(:forum_topic) + sleep 2 + post = Factory.create(:forum_post, :topic_id => topic.id) + topic.reload + assert(topic.updated_at > 1.second.ago) + end + end +end diff --git a/test/unit/forum_topic_test.rb b/test/unit/forum_topic_test.rb new file mode 100644 index 000000000..2447a4e79 --- /dev/null +++ b/test/unit/forum_topic_test.rb @@ -0,0 +1,4 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class ForumTopicTest < ActiveSupport::TestCase +end