sechat 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. data/lib/sechat.rb +11 -0
  2. data/lib/sechat/controllers/questions_controller.rb +56 -0
  3. data/lib/sechat/controllers/replies_controller.rb +65 -0
  4. data/lib/sechat/models/question.rb +16 -0
  5. data/lib/sechat/models/reply.rb +21 -0
  6. data/lib/sechat/routes.rb +16 -0
  7. data/test/question_test.rb +30 -0
  8. data/test/questions_controller_test.rb +69 -0
  9. data/test/rails_app/app/controllers/application_controller.rb +3 -0
  10. data/test/rails_app/app/controllers/questions_controller.rb +3 -0
  11. data/test/rails_app/app/controllers/replies_controller.rb +4 -0
  12. data/test/rails_app/app/helpers/application_helper.rb +2 -0
  13. data/test/rails_app/app/models/question.rb +3 -0
  14. data/test/rails_app/app/models/reply.rb +3 -0
  15. data/test/rails_app/config/application.rb +42 -0
  16. data/test/rails_app/config/boot.rb +6 -0
  17. data/test/rails_app/config/environment.rb +5 -0
  18. data/test/rails_app/config/environments/development.rb +26 -0
  19. data/test/rails_app/config/environments/production.rb +49 -0
  20. data/test/rails_app/config/environments/test.rb +35 -0
  21. data/test/rails_app/config/initializers/secret_token.rb +7 -0
  22. data/test/rails_app/config/initializers/session_store.rb +8 -0
  23. data/test/rails_app/config/routes.rb +4 -0
  24. data/test/rails_app/db/migrate/20110603130737_create_questions.rb +15 -0
  25. data/test/rails_app/db/migrate/20110603130957_create_replies.rb +16 -0
  26. data/test/rails_app/db/schema.rb +32 -0
  27. data/test/rails_app/db/seeds.rb +7 -0
  28. data/test/replies_controller_test.rb +130 -0
  29. data/test/reply_test.rb +15 -0
  30. data/test/test_helper.rb +15 -0
  31. metadata +134 -0
@@ -0,0 +1,11 @@
1
+ require 'sechat/routes.rb'
2
+
3
+ module Sechat
4
+ autoload :QuestionsController, 'sechat/controllers/questions_controller'
5
+ autoload :RepliesController, 'sechat/controllers/replies_controller'
6
+
7
+ module Models
8
+ autoload :Question, 'sechat/models/question'
9
+ autoload :Reply, 'sechat/models/reply'
10
+ end
11
+ end
@@ -0,0 +1,56 @@
1
+ module Sechat
2
+ class QuestionsController < ApplicationController
3
+ def index
4
+ @questions = resource_class.latest
5
+ respond_with(@questions)
6
+ end
7
+
8
+ def unanswered
9
+ @questions = resource_class.unanswered.latest
10
+
11
+ respond_with(@questions) do |format|
12
+ format.html { render 'index' }
13
+ end
14
+ end
15
+
16
+ def show
17
+ @question = resource_class.find(params[:id])
18
+ respond_with(@question)
19
+ end
20
+
21
+ def new
22
+ @question = build_question
23
+ respond_with(@question)
24
+ end
25
+
26
+ def edit
27
+ @question = resource_class.find(params[:id])
28
+ end
29
+
30
+ def create
31
+ @question = build_question(params[:question])
32
+ @question.save
33
+ respond_with(@question, :location => { :action => 'show', :id => @question.to_param })
34
+ end
35
+
36
+ def update
37
+ @question = resource_class.find(params[:id])
38
+ @question.update_attributes(params[:question])
39
+ respond_with(@question, :location => { :action => 'show', :id => @question.to_param })
40
+ end
41
+
42
+ def destroy
43
+ @question = resource_class.find(params[:id])
44
+ @question.destroy
45
+ respond_with(@question, :location => { :action => 'index' })
46
+ end
47
+
48
+ def resource_class
49
+ Question
50
+ end
51
+
52
+ def build_question(params = nil)
53
+ resource_class.new(params)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,65 @@
1
+ module Sechat
2
+ class RepliesController < ApplicationController
3
+ before_filter :load_question
4
+
5
+ def index
6
+ @replies = @question.replies.all
7
+ respond_with(@question, @replies)
8
+ end
9
+
10
+ def show
11
+ @reply = @question.replies.find(params[:id])
12
+ respond_with(@question, @reply)
13
+ end
14
+
15
+ def new
16
+ @reply = @question.replies.build
17
+ respond_with(@question, @reply)
18
+ end
19
+
20
+ def edit
21
+ @reply = @question.replies.find(params[:id])
22
+ end
23
+
24
+ def create
25
+ @reply = @question.replies.build(params[:reply])
26
+ @reply.save
27
+
28
+ respond_with(@question, @reply) do |format|
29
+ format.html do
30
+ if @reply.persisted?
31
+ redirect_to question_path(@question, :anchor => "A#{@reply.to_param}")
32
+ else
33
+ render 'new'
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def update
40
+ @reply = @question.replies.find(params[:id])
41
+ @reply.update_attributes(params[:reply])
42
+
43
+ respond_with(@question, @reply,
44
+ :location => question_path(@question, :anchor => "A#{@reply.to_param}"))
45
+ end
46
+
47
+ def answer
48
+ @reply = @question.replies.find(params[:id])
49
+ @reply.toggle!(:answer)
50
+
51
+ respond_with(@question, @reply,
52
+ :location => question_path(@question, :anchor => "A#{@reply.to_param}"))
53
+ end
54
+
55
+ def destroy
56
+ @reply = @question.replies.find(params[:id])
57
+ @reply.destroy
58
+ respond_with(@question, @reply)
59
+ end
60
+
61
+ def load_question
62
+ @question = Question.find(params[:question_id])
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,16 @@
1
+ module Sechat
2
+ module Models # :nodoc:
3
+ module Question
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ has_many :replies, :order => :created_at, :dependent => :delete_all
8
+ validates_presence_of :subject, :body
9
+
10
+ scope :latest, order("created_at DESC")
11
+ scope :answered, where(:answered => true)
12
+ scope :unanswered, where(:answered => false)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ module Sechat
2
+ module Models # :nodoc:
3
+ module Reply
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ belongs_to :question, :counter_cache => true
8
+ attr_protected :question_id
9
+ validates_presence_of :question_id, :body
10
+ after_save :update_question_status, :if => :answer_changed?
11
+ end
12
+
13
+ # Updates the answered column of associated question. This is called
14
+ # automatically on save if the answer status changed.
15
+ def update_question_status
16
+ question.answered = answer || self.class.where(:question_id => question_id, :answer => true).any?
17
+ question.save
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ module ActionDispatch # :nodoc:
2
+ module Routing # :nodoc:
3
+ class Mapper
4
+ def sechat
5
+ resources :questions do
6
+ get :unanswered, :on => :collection
7
+
8
+ resources :replies do
9
+ put :answer, :on => :member
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+
3
+ class QuestionTest < ActiveSupport::TestCase
4
+ test "should validate subject" do
5
+ assert Question.create(:subject => "").errors[:subject].any?
6
+ end
7
+
8
+ test "should validate body" do
9
+ assert Question.create(:body => "").errors[:body].any?
10
+ end
11
+
12
+ test "should create" do
13
+ assert Question.create(:subject => "lorem", :body => "ipsum").errors.empty?
14
+ end
15
+
16
+ test "latest scope" do
17
+ assert_equal [questions(:replied), questions(:multi_answered), questions(:unreplied), questions(:answered)],
18
+ Question.latest
19
+ end
20
+
21
+ test "answered scope" do
22
+ assert_equal [questions(:multi_answered), questions(:answered)],
23
+ Question.answered.latest
24
+ end
25
+
26
+ test "unanswered scope" do
27
+ assert_equal [questions(:replied), questions(:unreplied)],
28
+ Question.unanswered.latest
29
+ end
30
+ end
@@ -0,0 +1,69 @@
1
+ require 'test_helper'
2
+
3
+ class QuestionsControllerTest < ActionController::TestCase
4
+ test "should get index" do
5
+ get :index
6
+ assert_response :ok
7
+ assert_select "a[href=#{new_question_path}]"
8
+ assert_select "#questions article.question", Question.count
9
+ end
10
+
11
+ test "should get unanswered" do
12
+ get :unanswered
13
+ assert_response :ok
14
+ assert_template 'questions/index'
15
+ assert_select "#questions article.question", Question.unanswered.count
16
+ end
17
+
18
+ test "should get show for unreplied question" do
19
+ get :show, :id => questions(:unreplied).to_param
20
+ assert_response :ok
21
+ assert_select 'h1', questions(:unreplied).subject
22
+ end
23
+
24
+ test "should get show for replied question" do
25
+ get :show, :id => questions(:replied).to_param
26
+ assert_response :ok
27
+ assert_select 'h1', questions(:replied).subject
28
+ assert_select '#replies article.reply', questions(:replied).replies.count
29
+
30
+ questions(:replied).replies.each do |reply|
31
+ assert_select "#A#{reply.to_param}", 1
32
+ assert_select "a[href=#{answer_question_reply_path(questions(:replied), reply)}]", 1
33
+ end
34
+ end
35
+
36
+ test "should get new" do
37
+ get :new
38
+ assert_response :ok
39
+ assert_select "form[action=#{questions_path}]"
40
+ end
41
+
42
+ test "should get edit" do
43
+ get :edit, :id => questions(:replied).to_param
44
+ assert_response :ok
45
+ assert_select "form[action=#{question_path(questions(:replied).to_param)}] input[value=put]"
46
+ end
47
+
48
+ test "should create" do
49
+ assert_difference('Question.count') do
50
+ post :create, :question => { :subject => "lorem ipsum", :body => "dolor sit amet" }
51
+ assert_redirected_to question_url(assigns(:question))
52
+ end
53
+ end
54
+
55
+ test "should update" do
56
+ put :update, :question => { :subject => "dolor sit amet" }, :id => questions(:unreplied).to_param
57
+ assert_redirected_to question_url(questions(:unreplied))
58
+ assert_equal "dolor sit amet", questions(:unreplied).reload.subject
59
+ end
60
+
61
+ test "should destroy" do
62
+ assert_difference('Question.count', -1) do
63
+ assert_difference('Reply.count', -questions(:replied).replies.count) do
64
+ delete :destroy, :id => questions(:replied).to_param
65
+ assert_redirected_to questions_url
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,3 @@
1
+ class QuestionsController < Sechat::QuestionsController
2
+ respond_to :html
3
+ end
@@ -0,0 +1,4 @@
1
+ class RepliesController < Sechat::RepliesController
2
+ respond_to :html, :except => [:index, :show]
3
+ respond_to :xml
4
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,3 @@
1
+ class Question < ActiveRecord::Base
2
+ include Sechat::Models::Question
3
+ end
@@ -0,0 +1,3 @@
1
+ class Reply < ActiveRecord::Base
2
+ include Sechat::Models::Reply
3
+ end
@@ -0,0 +1,42 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require 'rails/all'
4
+
5
+ # If you have a Gemfile, require the gems listed there, including any gems
6
+ # you've limited to :test, :development, or :production.
7
+ Bundler.require(:default, Rails.env) if defined?(Bundler)
8
+
9
+ module RailsApp
10
+ class Application < Rails::Application
11
+ # Settings in config/environments/* take precedence over those specified here.
12
+ # Application configuration should go into files in config/initializers
13
+ # -- all .rb files in that directory are automatically loaded.
14
+
15
+ # Custom directories with classes and modules you want to be autoloadable.
16
+ # config.autoload_paths += %W(#{config.root}/extras)
17
+
18
+ # Only load the plugins named here, in the order given (default is alphabetical).
19
+ # :all can be used as a placeholder for all plugins not explicitly named.
20
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
21
+
22
+ # Activate observers that should always be running.
23
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
24
+
25
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
26
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
27
+ # config.time_zone = 'Central Time (US & Canada)'
28
+
29
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
30
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
31
+ # config.i18n.default_locale = :de
32
+
33
+ # JavaScript files you want as :defaults (application.js is always included).
34
+ config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
35
+
36
+ # Configure the default encoding used in templates for Ruby 1.9.
37
+ config.encoding = "utf-8"
38
+
39
+ # Configure sensitive parameters which will be filtered from the log file.
40
+ config.filter_parameters += [:password]
41
+ end
42
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+
3
+ # Set up gems listed in the Gemfile.
4
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5
+
6
+ require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
@@ -0,0 +1,5 @@
1
+ # Load the rails application
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the rails application
5
+ RailsApp::Application.initialize!
@@ -0,0 +1,26 @@
1
+ RailsApp::Application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb
3
+
4
+ # In the development environment your application's code is reloaded on
5
+ # every request. This slows down response time but is perfect for development
6
+ # since you don't have to restart the webserver when you make code changes.
7
+ config.cache_classes = false
8
+
9
+ # Log error messages when you accidentally call methods on nil.
10
+ config.whiny_nils = true
11
+
12
+ # Show full error reports and disable caching
13
+ config.consider_all_requests_local = true
14
+ config.action_view.debug_rjs = true
15
+ config.action_controller.perform_caching = false
16
+
17
+ # Don't care if the mailer can't send
18
+ config.action_mailer.raise_delivery_errors = false
19
+
20
+ # Print deprecation notices to the Rails logger
21
+ config.active_support.deprecation = :log
22
+
23
+ # Only use best-standards-support built into browsers
24
+ config.action_dispatch.best_standards_support = :builtin
25
+ end
26
+
@@ -0,0 +1,49 @@
1
+ RailsApp::Application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb
3
+
4
+ # The production environment is meant for finished, "live" apps.
5
+ # Code is not reloaded between requests
6
+ config.cache_classes = true
7
+
8
+ # Full error reports are disabled and caching is turned on
9
+ config.consider_all_requests_local = false
10
+ config.action_controller.perform_caching = true
11
+
12
+ # Specifies the header that your server uses for sending files
13
+ config.action_dispatch.x_sendfile_header = "X-Sendfile"
14
+
15
+ # For nginx:
16
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
17
+
18
+ # If you have no front-end server that supports something like X-Sendfile,
19
+ # just comment this out and Rails will serve the files
20
+
21
+ # See everything in the log (default is :info)
22
+ # config.log_level = :debug
23
+
24
+ # Use a different logger for distributed setups
25
+ # config.logger = SyslogLogger.new
26
+
27
+ # Use a different cache store in production
28
+ # config.cache_store = :mem_cache_store
29
+
30
+ # Disable Rails's static asset server
31
+ # In production, Apache or nginx will already do this
32
+ config.serve_static_assets = false
33
+
34
+ # Enable serving of images, stylesheets, and javascripts from an asset server
35
+ # config.action_controller.asset_host = "http://assets.example.com"
36
+
37
+ # Disable delivery errors, bad email addresses will be ignored
38
+ # config.action_mailer.raise_delivery_errors = false
39
+
40
+ # Enable threaded mode
41
+ # config.threadsafe!
42
+
43
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
44
+ # the I18n.default_locale when a translation can not be found)
45
+ config.i18n.fallbacks = true
46
+
47
+ # Send deprecation notices to registered listeners
48
+ config.active_support.deprecation = :notify
49
+ end
@@ -0,0 +1,35 @@
1
+ RailsApp::Application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb
3
+
4
+ # The test environment is used exclusively to run your application's
5
+ # test suite. You never need to work with it otherwise. Remember that
6
+ # your test database is "scratch space" for the test suite and is wiped
7
+ # and recreated between test runs. Don't rely on the data there!
8
+ config.cache_classes = true
9
+
10
+ # Log error messages when you accidentally call methods on nil.
11
+ config.whiny_nils = true
12
+
13
+ # Show full error reports and disable caching
14
+ config.consider_all_requests_local = true
15
+ config.action_controller.perform_caching = false
16
+
17
+ # Raise exceptions instead of rendering exception templates
18
+ config.action_dispatch.show_exceptions = false
19
+
20
+ # Disable request forgery protection in test environment
21
+ config.action_controller.allow_forgery_protection = false
22
+
23
+ # Tell Action Mailer not to deliver emails to the real world.
24
+ # The :test delivery method accumulates sent emails in the
25
+ # ActionMailer::Base.deliveries array.
26
+ config.action_mailer.delivery_method = :test
27
+
28
+ # Use SQL instead of Active Record's schema dumper when creating the test database.
29
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
30
+ # like if you have constraints or database-specific column types
31
+ # config.active_record.schema_format = :sql
32
+
33
+ # Print deprecation notices to the stderr
34
+ config.active_support.deprecation = :stderr
35
+ end
@@ -0,0 +1,7 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Your secret key for verifying the integrity of signed cookies.
4
+ # If you change this key, all old signed cookies will become invalid!
5
+ # Make sure the secret is at least 30 characters and all random,
6
+ # no regular words or you'll be exposed to dictionary attacks.
7
+ RailsApp::Application.config.secret_token = 'd02d44431970edceef6bc7746a41b876e1e828e48c0fa76fb94f2e8d068bdc6ae4f0ee129adeb69e8649b4840ba8e7d83894f9be0567eb0151da9b2478dc393d'
@@ -0,0 +1,8 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ RailsApp::Application.config.session_store :cookie_store, :key => '_rails_app_session'
4
+
5
+ # Use the database for sessions instead of the cookie-based default,
6
+ # which shouldn't be used to store highly confidential information
7
+ # (create the session table with "rails generate session_migration")
8
+ # RailsApp::Application.config.session_store :active_record_store
@@ -0,0 +1,4 @@
1
+ RailsApp::Application.routes.draw do
2
+ sechat
3
+ root :to => redirect("/questions")
4
+ end
@@ -0,0 +1,15 @@
1
+ class CreateQuestions < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :questions do |t|
4
+ t.string :subject, :null => false
5
+ t.text :body, :null => false
6
+ t.boolean :answered, :default => false
7
+ t.integer :replies_count, :default => 0
8
+ t.datetime :created_at
9
+ end
10
+ end
11
+
12
+ def self.down
13
+ drop_table :questions
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ class CreateReplies < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :replies do |t|
4
+ t.references :question, :null => false
5
+ t.text :body, :null => false
6
+ t.boolean :answer, :default => false
7
+ t.datetime :created_at
8
+ end
9
+
10
+ add_index :replies, :question_id
11
+ end
12
+
13
+ def self.down
14
+ drop_table :replies
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # Note that this schema.rb definition is the authoritative source for your
6
+ # database schema. If you need to create the application database on another
7
+ # system, you should be using db:schema:load, not running all the migrations
8
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
10
+ #
11
+ # It's strongly recommended to check this file into your version control system.
12
+
13
+ ActiveRecord::Schema.define(:version => 20110603130957) do
14
+
15
+ create_table "questions", :force => true do |t|
16
+ t.string "subject", :null => false
17
+ t.text "body", :null => false
18
+ t.boolean "answered", :default => false
19
+ t.integer "replies_count", :default => 0
20
+ t.datetime "created_at"
21
+ end
22
+
23
+ create_table "replies", :force => true do |t|
24
+ t.integer "question_id", :null => false
25
+ t.text "body", :null => false
26
+ t.boolean "answer", :default => false
27
+ t.datetime "created_at"
28
+ end
29
+
30
+ add_index "replies", ["question_id"], :name => "index_replies_on_question_id"
31
+
32
+ end
@@ -0,0 +1,7 @@
1
+ # This file should contain all the record creation needed to seed the database with its default values.
2
+ # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3
+ #
4
+ # Examples:
5
+ #
6
+ # cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
7
+ # Mayor.create(:name => 'Daley', :city => cities.first)
@@ -0,0 +1,130 @@
1
+ require 'test_helper'
2
+
3
+ class RepliesControllerTest < ActionController::TestCase
4
+ setup do
5
+ @question = questions(:replied)
6
+ @reply = replies(:replied_1)
7
+ end
8
+
9
+ test "should get index as xml" do
10
+ get :index, :question_id => @question.to_param, :format => 'xml'
11
+ assert_response :ok
12
+ assert_select "replies reply", @question.replies.count
13
+ end
14
+
15
+ test "should get show as xml" do
16
+ get :show, :question_id => @question.to_param, :id => @reply.to_param, :format => 'xml'
17
+ assert_response :ok
18
+ assert_select 'reply', 1
19
+ end
20
+
21
+ test "should get new" do
22
+ get :new, :question_id => @question.to_param
23
+ assert_response :ok
24
+ assert_select "form[action=#{question_replies_path(@question)}]"
25
+ end
26
+
27
+ test "should get new as xml" do
28
+ get :new, :question_id => @question.to_param, :format => 'xml'
29
+ assert_response :ok
30
+ assert_select "reply", 1
31
+ end
32
+
33
+ test "should get edit" do
34
+ get :edit, :question_id => @question.to_param, :id => @reply.to_param
35
+ assert_response :ok
36
+ assert_select "form[action=#{question_reply_path(@question, @reply)}] input[value=put]"
37
+ end
38
+
39
+ test "should create" do
40
+ assert_difference('@question.replies.count') do
41
+ post :create, :question_id => @question.to_param, :reply => { :body => "lorem ipsum" }
42
+ assert_redirected_to question_url(@question, :anchor => "A#{assigns(:reply).to_param}")
43
+ end
44
+ end
45
+
46
+ test "should create as xml" do
47
+ assert_difference('@question.replies.count') do
48
+ post :create, :question_id => @question.to_param,
49
+ :reply => { :body => "lorem ipsum" }, :format => 'xml'
50
+ assert_response :created
51
+ assert_equal question_reply_url(@question, assigns(:reply)), response.headers['Location']
52
+ end
53
+ end
54
+
55
+ test "should update" do
56
+ put :update, :question_id => @question.to_param,
57
+ :reply => { :body => "dolor sit amet" }, :id => @reply.to_param
58
+ assert_redirected_to question_url(@question, :anchor => "A#{@reply.to_param}")
59
+ assert_equal "dolor sit amet", @reply.reload.body
60
+ end
61
+
62
+ test "should update as xml" do
63
+ put :update, :question_id => @question.to_param, :id => @reply.to_param,
64
+ :reply => { :body => "dolor sit amet" }, :format => 'xml'
65
+ assert_response :ok
66
+ assert_nil response.headers['Location']
67
+ end
68
+
69
+ test "should set answer" do
70
+ assert_difference('Question.answered.count') do
71
+ assert_difference('Reply.where(:answer => true).count') do
72
+ put :answer, :question_id => @question.to_param, :id => @reply.to_param
73
+ assert_redirected_to question_url(@question, :anchor => "A#{@reply.to_param}")
74
+ end
75
+ end
76
+ end
77
+
78
+ test "should set answer as xml" do
79
+ assert_difference('Question.answered.count') do
80
+ assert_difference('Reply.where(:answer => true).count') do
81
+ put :answer, :question_id => @question.to_param, :id => @reply.to_param, :format => 'xml'
82
+ assert_response :ok
83
+ assert_nil response.headers['Location']
84
+ end
85
+ end
86
+ end
87
+
88
+ test "should unset answer" do
89
+ assert_difference('Question.answered.count', -1) do
90
+ assert_difference('Reply.where(:answer => true).count', -1) do
91
+ put :answer, :question_id => questions(:answered).to_param, :id => replies(:answer).to_param
92
+ assert_redirected_to question_url(questions(:answered), :anchor => "A#{replies(:answer).to_param}")
93
+ end
94
+ end
95
+ end
96
+
97
+ test "should unset answer should not affect multi-answered question" do
98
+ assert_no_difference('Question.answered.count') do
99
+ assert_difference('Reply.where(:answer => true).count', -1) do
100
+ put :answer, :question_id => questions(:multi_answered).to_param,
101
+ :id => replies(:multi_answered_1).to_param
102
+ assert_redirected_to question_url(questions(:multi_answered), :anchor => "A#{replies(:multi_answered_1).to_param}")
103
+ end
104
+ end
105
+ end
106
+
107
+ test "should unset answer as xml" do
108
+ assert_difference('Question.answered.count', -1) do
109
+ assert_difference('Reply.where(:answer => true).count', -1) do
110
+ put :answer, :question_id => questions(:answered), :id => replies(:answer).to_param, :format => 'xml'
111
+ assert_response :ok
112
+ assert_nil response.headers['Location']
113
+ end
114
+ end
115
+ end
116
+
117
+ test "should destroy" do
118
+ assert_difference('@question.replies.count', -1) do
119
+ delete :destroy, :question_id => @question.to_param, :id => @reply.to_param
120
+ assert_redirected_to question_replies_url
121
+ end
122
+ end
123
+
124
+ test "should destroy as xml" do
125
+ delete :destroy, :question_id => @question.to_param, :id => @reply.to_param,
126
+ :format => 'xml'
127
+ assert_response :ok
128
+ assert_nil response.headers['Location']
129
+ end
130
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ class ReplyTest < ActiveSupport::TestCase
4
+ test "should validate question" do
5
+ assert Reply.create.errors[:question_id].any?
6
+ end
7
+
8
+ test "should validate body" do
9
+ assert Reply.create(:body => "").errors[:body].any?
10
+ end
11
+
12
+ test "should create" do
13
+ assert questions(:unreplied).replies.create(:body => "ipsum").errors.empty?
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+
3
+ require File.expand_path('../rails_app/config/environment', __FILE__)
4
+ require 'rails/test_help'
5
+ require 'capybara/rails'
6
+
7
+ class ActiveSupport::TestCase
8
+ self.fixture_path = File.expand_path('../fixtures', __FILE__)
9
+ fixtures :all
10
+ end
11
+
12
+ class ActionDispatch::IntegrationTest
13
+ self.fixture_path = File.expand_path('../fixtures', __FILE__)
14
+ include Capybara
15
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sechat
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
+ platform: ruby
12
+ authors:
13
+ - Julien Portalier
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-17 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rails
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 9
30
+ segments:
31
+ - 3
32
+ - 0
33
+ - 7
34
+ version: 3.0.7
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: Q&A engine for Ruby on Rails.
38
+ email: ysbaddaden@gmail.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - lib/sechat.rb
47
+ - lib/sechat/controllers/questions_controller.rb
48
+ - lib/sechat/controllers/replies_controller.rb
49
+ - lib/sechat/models/question.rb
50
+ - lib/sechat/models/reply.rb
51
+ - lib/sechat/routes.rb
52
+ - test/question_test.rb
53
+ - test/questions_controller_test.rb
54
+ - test/rails_app/app/controllers/application_controller.rb
55
+ - test/rails_app/app/controllers/questions_controller.rb
56
+ - test/rails_app/app/controllers/replies_controller.rb
57
+ - test/rails_app/app/helpers/application_helper.rb
58
+ - test/rails_app/app/models/question.rb
59
+ - test/rails_app/app/models/reply.rb
60
+ - test/rails_app/config/application.rb
61
+ - test/rails_app/config/boot.rb
62
+ - test/rails_app/config/environment.rb
63
+ - test/rails_app/config/environments/development.rb
64
+ - test/rails_app/config/environments/production.rb
65
+ - test/rails_app/config/environments/test.rb
66
+ - test/rails_app/config/initializers/secret_token.rb
67
+ - test/rails_app/config/initializers/session_store.rb
68
+ - test/rails_app/config/routes.rb
69
+ - test/rails_app/db/migrate/20110603130737_create_questions.rb
70
+ - test/rails_app/db/migrate/20110603130957_create_replies.rb
71
+ - test/rails_app/db/schema.rb
72
+ - test/rails_app/db/seeds.rb
73
+ - test/replies_controller_test.rb
74
+ - test/reply_test.rb
75
+ - test/test_helper.rb
76
+ has_rdoc: true
77
+ homepage: http://github.com/ysbaddaden/sechat
78
+ licenses: []
79
+
80
+ post_install_message:
81
+ rdoc_options: []
82
+
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ requirements: []
104
+
105
+ rubyforge_project:
106
+ rubygems_version: 1.6.2
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: Q&A engine for Ruby on Rails.
110
+ test_files:
111
+ - test/question_test.rb
112
+ - test/questions_controller_test.rb
113
+ - test/rails_app/app/controllers/application_controller.rb
114
+ - test/rails_app/app/controllers/questions_controller.rb
115
+ - test/rails_app/app/controllers/replies_controller.rb
116
+ - test/rails_app/app/helpers/application_helper.rb
117
+ - test/rails_app/app/models/question.rb
118
+ - test/rails_app/app/models/reply.rb
119
+ - test/rails_app/config/application.rb
120
+ - test/rails_app/config/boot.rb
121
+ - test/rails_app/config/environment.rb
122
+ - test/rails_app/config/environments/development.rb
123
+ - test/rails_app/config/environments/production.rb
124
+ - test/rails_app/config/environments/test.rb
125
+ - test/rails_app/config/initializers/secret_token.rb
126
+ - test/rails_app/config/initializers/session_store.rb
127
+ - test/rails_app/config/routes.rb
128
+ - test/rails_app/db/migrate/20110603130737_create_questions.rb
129
+ - test/rails_app/db/migrate/20110603130957_create_replies.rb
130
+ - test/rails_app/db/schema.rb
131
+ - test/rails_app/db/seeds.rb
132
+ - test/replies_controller_test.rb
133
+ - test/reply_test.rb
134
+ - test/test_helper.rb