Commit 2359ad14 by tadyjp

Merge pull request #9 from tadyjp/wip/feat/0107_comments

[WIP] コメント機能
parents e9de798b 00834c01
#!/bin/sh
# SET YOUR ENV HERE.
export GOOGLE_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com"
export GOOGLE_SECRET="xxxxxxxxxxxxxxxxxxxxxxxx"
export DB_TEST_USER="user"
export DB_TEST_PASS="pass"
export DB_DEVELOPMENT_USER="user"
export DB_DEVELOPMENT_PASS="pass"
......@@ -15,8 +15,10 @@
/log/*.log
/tmp
/bin/set-env.sh
.env
/coverage/.*
*.bk
/db/*.sql
......@@ -19,3 +19,6 @@ IfUnlessModifier:
CyclomaticComplexity:
Max: 10
RaiseArgs:
Enabled: false
language: ruby
services:
- mysql
rvm:
- 2.0.0
- 2.0.0
before_script:
- mysql -e 'CREATE DATABASE rendezvous_test;'
env:
- DB_TEST_DATABASE=rendezvous_test DB_TEST_USER=travis
......@@ -14,6 +14,8 @@ gem 'uglifier'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails'
gem 'jquery-rails'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
......@@ -26,6 +28,8 @@ gem 'coffee-rails'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder'
gem 'i18n_generators'
group :doc do
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', require: false
......@@ -45,6 +49,9 @@ end
# gem 'bootstrap-sass-rails'
gem 'mysql2'
gem 'sqlite3'
gem 'devise'
gem 'omniauth-google-oauth2'
......@@ -57,8 +64,6 @@ gem 'coderay'
group :development do
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
gem 'better_errors'
gem 'binding_of_caller'
......@@ -74,24 +79,24 @@ group :development do
# rubocop
gem 'rubocop'
gem 'guard-rubocop'
gem 'guard-spring'
gem 'spring'
end
group :development, :test do
gem 'rspec-rails'
gem 'guard-rspec'
gem 'guard-spring'
gem 'factory_girl_rails'
gem 'spring'
end
# group :test do
# gem 'email_spec'
# end
# gem 'database_cleaner'
gem 'database_rewinder'
end
# group :production do
# gem 'rails_12factor'
# gem 'pg'
# end
group :test do
gem 'factory_girl_rails'
gem 'capybara'
gem 'launchy'
gem 'poltergeist'
gem 'coveralls', :require => false
end
# tree structure
gem 'ancestry'
......@@ -107,6 +112,5 @@ gem 'premailer'
gem 'faraday'
group :test do
gem 'coveralls', :require => false
end
# Check mail format
gem 'validates_email_format_of'
......@@ -9,7 +9,7 @@ GIT
GIT
remote: git://github.com/vmg/redcarpet.git
revision: 52c5fa3c5753d2125e827f235cdf4cb730484902
revision: 0c4cd0e7ea5f7f44e2953f3013fdf751af91162d
branch: master
specs:
redcarpet (3.0.0)
......@@ -54,8 +54,15 @@ GEM
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
builder (3.1.4)
capybara (2.2.1)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
celluloid (0.15.2)
timers (~> 1.1.0)
cliver (0.3.2)
coderay (1.1.0)
coffee-rails (4.0.1)
coffee-script (>= 2.2.0)
......@@ -73,6 +80,7 @@ GEM
css_parser (1.3.5)
addressable
daemons (1.1.9)
database_rewinder (0.0.2)
debug_inspector (0.0.2)
devise (3.2.2)
bcrypt-ruby (~> 3.0)
......@@ -81,7 +89,9 @@ GEM
thread_safe (~> 0.1)
warden (~> 1.2.3)
diff-lcs (1.2.5)
docile (1.1.1)
docile (1.1.2)
domain_name (0.5.15)
unf (>= 0.0.5, < 1.0.0)
erubis (2.7.0)
eventmachine (1.0.3)
execjs (2.0.2)
......@@ -90,8 +100,8 @@ GEM
factory_girl_rails (4.3.0)
factory_girl (~> 4.3.0)
railties (>= 3.0.0)
faraday (0.8.8)
multipart-post (~> 1.2.0)
faraday (0.9.0)
multipart-post (>= 1.2, < 3)
ffi (1.9.3)
formatador (0.2.4)
gmail_xoauth (0.4.1)
......@@ -102,10 +112,7 @@ GEM
lumberjack (~> 1.0)
pry (>= 0.9.12)
thor (>= 0.18.1)
guard-rspec (4.2.0)
guard (>= 2.1.1)
rspec (>= 2.14, < 4.0)
guard-rubocop (1.0.0)
guard-rubocop (1.0.1)
guard (~> 2.0)
rubocop (~> 0.10)
guard-spring (0.0.4)
......@@ -114,14 +121,24 @@ GEM
hashie (2.0.5)
hike (1.2.3)
htmlentities (4.3.1)
http-cookie (1.0.2)
domain_name (~> 0.5)
httpauth (0.2.0)
i18n (0.6.9)
jbuilder (2.0.1)
i18n_generators (1.2.1)
mechanize
rails (>= 3.0.0)
jbuilder (2.0.2)
activesupport (>= 3.0.0)
multi_json (>= 1.2.0)
jquery-rails (3.0.4)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
json (1.8.1)
jwt (0.1.8)
jwt (0.1.10)
multi_json (>= 1.5)
launchy (2.4.2)
addressable (~> 2.3)
listen (2.4.0)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3)
......@@ -130,14 +147,27 @@ GEM
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mechanize (2.7.2)
domain_name (~> 0.5, >= 0.5.1)
http-cookie (~> 1.0.0)
mime-types (~> 1.17, >= 1.17.2)
net-http-digest_auth (~> 1.1, >= 1.1.1)
net-http-persistent (~> 2.5, >= 2.5.2)
nokogiri (~> 1.4)
ntlm-http (~> 0.1, >= 0.1.1)
webrobots (>= 0.0.9, < 0.2)
method_source (0.8.2)
mime-types (1.25.1)
mini_portile (0.5.2)
minitest (4.7.5)
multi_json (1.8.2)
multipart-post (1.2.0)
multi_json (1.8.4)
multipart-post (2.0.0)
mysql2 (0.3.14)
net-http-digest_auth (1.4)
net-http-persistent (2.9)
nokogiri (1.6.1)
mini_portile (~> 0.5.0)
ntlm-http (0.1.1)
oauth (0.4.7)
oauth2 (0.8.1)
faraday (~> 0.8)
......@@ -145,23 +175,28 @@ GEM
jwt (~> 0.1.4)
multi_json (~> 1.0)
rack (~> 1.2)
omniauth (1.1.4)
omniauth (1.2.1)
hashie (>= 1.2, < 3)
rack
omniauth-google-oauth2 (0.2.1)
rack (~> 1.0)
omniauth-google-oauth2 (0.2.2)
omniauth (~> 1.0)
omniauth-oauth2
omniauth-oauth2 (1.1.1)
oauth2 (~> 0.8.0)
omniauth (~> 1.0)
orm_adapter (0.5.0)
parser (2.0.0)
parser (2.1.4)
ast (~> 1.1)
slop (~> 3.4, >= 3.4.5)
poltergeist (1.5.0)
capybara (~> 2.1)
cliver (~> 0.3.1)
multi_json (~> 1.0)
websocket-driver (>= 0.2.0)
polyglot (0.3.3)
powerpack (0.0.9)
premailer (1.7.9)
css_parser (>= 1.1.9)
premailer (1.8.0)
css_parser (>= 1.3.5)
htmlentities (>= 4.0.0)
pry (0.9.12.4)
coderay (~> 1.0)
......@@ -170,7 +205,7 @@ GEM
pry-rails (0.3.2)
pry (>= 0.9.10)
rack (1.5.2)
rack-mini-profiler (0.1.31)
rack-mini-profiler (0.9.0)
rack (>= 1.1.3)
rack-test (0.6.2)
rack (>= 1.0)
......@@ -187,32 +222,29 @@ GEM
activesupport (= 4.0.2)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (1.1.4)
rainbow (1.99.1)
rake (10.1.1)
rb-fsevent (0.9.3)
rb-fsevent (0.9.4)
rb-inotify (0.9.3)
ffi (>= 0.5.0)
rdoc (3.12.2)
rdoc (4.1.1)
json (~> 1.4)
rest-client (1.6.7)
mime-types (>= 1.16)
rspec (2.14.1)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
rspec-core (2.14.7)
rspec-expectations (2.14.4)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.14.4)
rspec-rails (2.14.0)
rspec-rails (2.14.1)
actionpack (>= 3.0)
activemodel (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
rubocop (0.15.0)
parser (~> 2.0)
rubocop (0.16.0)
parser (~> 2.1)
powerpack (~> 0.0.6)
rainbow (>= 1.1.4)
sass (3.2.13)
......@@ -220,9 +252,9 @@ GEM
railties (>= 4.0.0, < 5.0)
sass (>= 3.1.10)
sprockets-rails (~> 2.0.0)
sdoc (0.3.20)
json (>= 1.1.3)
rdoc (~> 3.10)
sdoc (0.4.0)
json (~> 1.8)
rdoc (~> 4.0, < 5.0)
simplecov (0.8.2)
docile (~> 1.1.0)
multi_json
......@@ -259,8 +291,16 @@ GEM
uglifier (2.4.0)
execjs (>= 0.3.0)
json (>= 1.8.0)
unf (0.1.3)
unf_ext
unf_ext (0.0.6)
validates_email_format_of (1.5.3)
warden (1.2.3)
rack (>= 1.0)
webrobots (0.1.1)
websocket-driver (0.3.2)
xpath (2.0.0)
nokogiri (~> 1.3)
PLATFORMS
ruby
......@@ -270,19 +310,25 @@ DEPENDENCIES
ancestry
better_errors
binding_of_caller
capybara
coderay
coffee-rails
coveralls
database_rewinder
devise
factory_girl_rails
faraday
guard-rspec
guard-rubocop
guard-spring
i18n_generators
jbuilder
jquery-rails
launchy
mail
mysql2
nokogiri
omniauth-google-oauth2
poltergeist
premailer
pry-rails
rack-mini-profiler
......@@ -296,3 +342,4 @@ DEPENDENCIES
sqlite3
thin
uglifier
validates_email_format_of
guard :rspec, all_after_pass: true, spring: true do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { 'spec' }
# guard :rspec, all_after_pass: true do
# watch(%r{^spec/.+_spec\.rb$})
# watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
# watch('spec/spec_helper.rb') { 'spec' }
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
watch(%r{^spec/factories/(.+)\.rb$}) { 'spec/factories_spec.rb' }
watch(%r{^spec/support/(.+)\.rb$}) { 'spec' }
watch('config/routes.rb') { 'spec/routing' }
watch('app/controllers/application_controller.rb') { 'spec/controllers' }
end
# watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
# watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
# watch(%r{^app/(.*)(\.erb|\.haml)$}) { 'spec/features' }
# watch(%r{^spec/factories/(.+)\.rb$}) { 'spec/factories_spec.rb' }
# watch(%r{^spec/support/(.+)\.rb$}) { 'spec' }
# watch('config/routes.rb') { 'spec/routing' }
# watch('app/controllers/application_controller.rb') { 'spec/controllers' }
# end
# guard :rubocop, all_after_pass: true, cli: ['--rails', '--auto-correct'] do
# watch(%r{.+\.rb$})
# watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
# end
guard :rubocop, all_after_pass: true, cli: ['--rails', '--auto-correct'] do
guard :rubocop do
watch(%r{.+\.rb$})
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
end
guard :rspec do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^spec/spec_helper\.rb$}) { |m| 'spec' }
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) do |m|
%W(spec/routing/#{m[1]}_routing_spec.rb spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb spec/requests/#{m[1]}_spec.rb)
end
end
rendezvous
==========
A simple markdown-based wiki system for term.
## Badge
[![Build Status](https://travis-ci.org/tadyjp/rendezvous.png)](https://travis-ci.org/tadyjp/rendezvous)
[![Coverage Status](https://coveralls.io/repos/tadyjp/rendezvous/badge.png)](https://coveralls.io/r/tadyjp/rendezvous)
[![Code Climate](https://codeclimate.com/github/tadyjp/rendezvous.png)](https://codeclimate.com/github/tadyjp/rendezvous)
[![Dependency Status](https://gemnasium.com/tadyjp/rendezvous.png)](https://gemnasium.com/tadyjp/rendezvous)
## ENVの設定
# How to install and use.
Get code and install gems.
```
$ git clone git@github.com:tadyjp/rendezvous.git
$ cd rendezvous
$ bundle install
```
Create YOUR .ENV file.
```
. ./bin/set-env.sh
$ cp .env.example .env
$ vim .env
```
Setup DB (Default: mysql).
```
$ bundle exec rake db:migrate
$ bundle exec rake db:seed
```
Set ENV before start server.
```
$ source .env
$ bundle exec rails s
```
And have fun with your team !
......@@ -12,7 +12,7 @@
//
//= require_self
// require jquery
// require jquery_ujs
//= require jquery_ujs
// require turbolinks
//= require_tree ./lib
//= require_tree .
......
......@@ -11,22 +11,32 @@ if window.location.pathname.match /^\/posts\/?$/
$this.addClass('active')
id = $this.data('postId')
$.get('/posts/show_fragment', { id: id })
$.get("/posts/#{id}", {
fragment: 1
})
.done (data) ->
$('#list_post').html(data)
prettyPrint()
# 初期に詳細を表示
# open post when `id` parameter set.
id_param = RV.tools.getQueryParams()["id"]
if id_param?
$(".post-list[data-post-id='#{id_param}']").addClass('active')
$.get('/posts/show_fragment', {
'id': id_param,
$("a.post-list[data-post-id='#{id_param}']").addClass('active')
$.get("/posts/#{id_param}", {
fragment: 1
})
.done (data) ->
$('#list_post').html(data)
prettyPrint()
else
$el = $("a.post-list:eq(0)")
$el.addClass('active')
$.get("/posts/#{$el.data('postId')}", {
fragment: 1
})
.done (data) ->
$('#list_post').html(data)
prettyPrint()
......@@ -4,8 +4,6 @@
.app {
padding-top: 70px;
.navbar-default .navbar-brand {
background-color: #428bca;
color: #fff;
......@@ -51,9 +49,15 @@
width: 200px;
}
/* side tree view
-------------------------------------------------- */
/* ul {
padding-left: 1em;
}
*/
/* home#show
-------------------------------------------------- */
.text-box {
/* .text-box {
padding: 9px 14px;
border: 1px solid #e1e1e8;
border-radius: 4px;
......@@ -81,7 +85,7 @@
border-top-left-radius: 0px;
border-top-right-radius: 0px;
}
*/
/* posts#new
-------------------------------------------------- */
......
body[class^="posts-"] {
padding-top: 70px;
}
......@@ -9,4 +9,8 @@ class ApplicationController < ActionController::Base
redirect_to root_path
end
end
rescue_from(ActionController::ParameterMissing) do |parameter_missing_exception|
render text: "Required parameter missing: #{parameter_missing_exception.param}", status: :bad_request
end
end
......@@ -5,12 +5,17 @@ require 'premailer'
module RV::Mailer
include ApplicationHelper
def compose_mail(post, user)
def compose_mail(post, opts = {})
fail ArgumentError.new('post missing') unless post.present?
fail ArgumentError.new('user missing') unless opts[:user].present? && opts[:user].is_a?(User)
fail ArgumentError.new('to missing') unless opts[:to].present?
fail ArgumentError.new('to mail format invalid') unless ValidatesEmailFormatOf.validate_email_format(opts[:to]).nil?
html_body = generate_html_mail(post.body)
mail = Mail.new do
from user.email
to user.email
from opts[:user].email
to opts[:to]
subject post.title
body post.body
......@@ -22,8 +27,8 @@ module RV::Mailer
# set ActionGmailer
config = {
oauth2_token: user.google_auth_token,
account: user.email
oauth2_token: opts[:user].google_auth_token,
account: opts[:user].email
}.merge(Rendezvous::Application.config.action_mailer.smtp_settings)
mail.delivery_method(ActionGmailer::DeliveryMethod, config)
......
......@@ -21,14 +21,14 @@ class PostsController < ApplicationController
render text: h_application_format_markdown(params[:text])
end
def show_fragment
@post = Post.find(params[:id])
render layout: false, partial: 'posts/show_fragment'
end
# GET /posts/1
# GET /posts/1.json
def show
if params[:fragment].present?
render layout: false, partial: 'posts/show_fragment'
else
render
end
end
# GET /posts/new
......@@ -47,10 +47,12 @@ class PostsController < ApplicationController
# refresh google oauth token if expired
current_user.google_oauth_token_refresh! if current_user.google_oauth_token_expired?
compose_mail(@post, current_user).deliver
redirect_to root_path(id: @post.id)
compose_mail(@post, user: current_user, to: mail_params[:to]).deliver
redirect_to root_path(id: @post.id), flash: { success: 'Mail has sent!' }
rescue ActionGmailer::DeliveryError
redirect_to root_path(id: @post.id), flash: { notice: 'Gmail authentication expired.' }
rescue ArgumentError => err
redirect_to root_path(id: @post.id), flash: { alert: 'Mail format is invalid: ' + err.to_s }
end
# GET /posts/1/edit
......@@ -65,7 +67,7 @@ class PostsController < ApplicationController
respond_to do |format|
if @post.save
format.html { redirect_to root_path(id: @post.id), notice: 'Post was successfully created.' }
format.html { redirect_to root_path(id: @post.id), flash: { notice: 'Post was successfully created.' } }
format.json { render action: 'show', status: :created, location: @post }
else
format.html { render action: 'new' }
......@@ -81,7 +83,7 @@ class PostsController < ApplicationController
respond_to do |format|
if @post.update(post_params)
format.html { redirect_to root_path(id: @post.id), notice: 'Post was successfully updated.' }
format.html { redirect_to root_path(id: @post.id), flash: { notice: 'Post was successfully updated.' } }
format.json { head :no_content }
else
format.html { render action: 'edit' }
......@@ -95,11 +97,26 @@ class PostsController < ApplicationController
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.html { redirect_to posts_url, flash: { success: 'Post successfully deleted.' } }
format.json { head :no_content }
end
end
# POST /posts/1/comment
def comment
@post = set_post
@comment = @post.comments.build(comment_params.merge(author: current_user))
respond_to do |format|
if @comment.save
format.html { redirect_to posts_path(id: @post.id) }
format.json { render json: { status: 'ok', comment: @comment }, status: :created }
else
format.html { redirect_to posts_path(id: @post.id), flash: { alert: 'Comment is not saved.' } }
format.json { render json: @comment.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
......@@ -123,4 +140,12 @@ class PostsController < ApplicationController
_param_hash
end
end
def mail_params
params.require(:mail).permit(:to).to_hash.symbolize_keys
end
def comment_params
params.require(:comment).permit(:body).to_hash
end
end
......@@ -3,7 +3,7 @@ module PostsHelper
def h_display_tree(node)
_html = '<ul>'
if node.posts.count > 0
_html << %Q{<li><a href="#{ root_path(q: '#' + node.name) }">#{node.name} <span class="badge">#{node.posts.count}</span></a></li>}
_html << %Q{<li><a href="#{ posts_path(q: '#' + node.name) }">#{node.name} <span class="badge">#{node.posts.count}</span></a></li>}
end
node.children.each do |_child|
_html << h_display_tree(_child)
......
module StyleHelper
## Store style
# Usage:
# <% style do %>
# div {
# color: red;
# }
# <% end %>
def style(&block)
content_for(content_key, capture(&block))
end
## Render all style
def render_style
return if content_for(content_key).nil?
html_buf = '<style type="text/css">'
html_buf << content_for(content_key)
html_buf << '</style>'
html_buf.html_safe
end
private
# Use for `content_for`
def content_key
:style_addon
end
end
class Comment < ActiveRecord::Base
belongs_to :author, class_name: 'User'
belongs_to :post
validates :author_id, presence: true
validates :post_id, presence: true
validates :body, presence: true
end
......@@ -2,6 +2,7 @@ class Post < ActiveRecord::Base
has_many :post_tags
has_many :tags, through: :post_tags
belongs_to :author, class_name: 'User'
has_many :comments
# Named scope
scope :search, (lambda do |query|
......@@ -13,15 +14,15 @@ class Post < ActiveRecord::Base
query_list.each do |_query|
case _query
when /^id:(.+)/
_where_list = _where_list.where('id = ?', Regexp.last_match[1])
_where_list = _where_list.where(id: Regexp.last_match[1])
when /^title:(.+)/
_where_list = _where_list.where('title LIKE ?', "%#{Regexp.last_match[1]}%")
when /^body:(.+)/
_where_list = _where_list.where('body LIKE ?', "%#{Regexp.last_match[1]}%")
when /^@(.+)/
_where_list = _where_list.where('users.name = ?', Regexp.last_match[1])
_where_list = _where_list.where(users: { name: Regexp.last_match[1] })
when /^#(.+)/
_where_list = _where_list.where('tags.name = ?', Regexp.last_match[1])
_where_list = _where_list.where(tags: { name: Regexp.last_match[1] })
when /^date:(\d+)-(\d+)-(\d+)/
_date = Time.new(Regexp.last_match[1], Regexp.last_match[2], Regexp.last_match[3])
_where_list = _where_list.where('updated_at > ? AND updated_at < ?', _date, _date + 1.day)
......
......@@ -8,6 +8,7 @@ class User < ActiveRecord::Base
devise :omniauthable, omniauth_providers: [:google_oauth2]
has_many :posts
has_many :comments
# Device
def self.find_for_google_oauth2(access_token, signed_in_resource = nil)
......
......@@ -9,23 +9,13 @@
<!-- Optional theme -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap-theme.min.css">
<%= render_style %>
<%= csrf_meta_tags %>
</head>
<body>
<body class="<%= params[:controller] %>-<%= params[:action] %>">
<% if notice %>
<script type="text/javascript">
alert('<%= notice %>');
</script>
<!-- <p class="notice"><%= notice %></p> -->
<% end %>
<% if alert %>
<script type="text/javascript">
alert('<%= alert %>');
</script>
<!-- <p class="notice"><%= notice %></p> -->
<p class="alert"><%= alert %></p>
<% end %>
<%= render partial: 'partials/header_notifications' %>
<%= yield %>
......
......@@ -18,13 +18,17 @@
<div class="input-group">
<input type="text" name="q" class="form-control" value="<%= params[:q] %>" placeholder="Search">
<span class="input-group-btn">
<button type="submit" class="btn btn-default">
<button type="submit" class="btn btn-default" data-disable-with="Searching...">
<span class="glyphicon glyphicon-search"></span>
</button>
</span>
</div>
</form>
<p class="navbar-text" id="header-search-hint">
<a href="#"><span class="glyphicon glyphicon-question-sign" data-toggle="modal" data-target="#header-search-description"></span></a>
</p>
<%= form_tag(destroy_user_session_path, :method => :delete, class: 'navbar-form navbar-right') do %>
<%= submit_tag 'SignOut', class: 'btn btn-default' %>
<% end %>
......@@ -41,3 +45,42 @@
</div><!-- /.navbar-collapse -->
</div><!-- /.container -->
</nav>
<!-- Modal #header-search-description -->
<div class="modal fade" id="header-search-description" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="myModalLabel">Search command</h4>
</div>
<div class="modal-body">
<dl class="dl-horizontal">
<dt>Search by title</dt>
<dd><pre><a href="<%= posts_path(q: 'title:ruby') %>">title:ruby</a></pre></dd>
<dt>Search by id</dt>
<dd><pre><a href="<%= posts_path(q: 'id:123') %>">id:123</a></pre></dd>
<dt>Search by body</dt>
<dd><pre><a href="<%= posts_path(q: 'body:ruby') %>">body:ruby</a></pre></dd>
<dt>Search by author</dt>
<dd><pre><a href="<%= posts_path(q: '@taro') %>">@taro</a></pre></dd>
<dt>Search by tag</dt>
<dd><pre><a href="<%= posts_path(q: '#ruby') %>">#ruby</a></pre></dd>
<dt>Search by date</dt>
<dd><pre><a href="<%= posts_path(q: 'date:2013-12-16') %>">date:2013-12-16</a></pre></dd>
<dt>Search by title or body</dt>
<dd><pre><a href="<%= posts_path(q: 'ruby') %>">ruby</a></pre></dd>
</dl>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<% style do %>
#header-search-hint{
margin-left: 0;
}
<% end %>
<% if flash[:success] %>
<div class="alert alert-success fade in">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<strong>Success</strong> <%= flash[:success] %>
</div>
<% end %>
<% if flash[:notice] %>
<div class="alert alert-warning fade in">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<strong>Notice</strong> <%= flash[:notice] %>
</div>
<% end %>
<% if flash[:alert] %>
<div class="alert alert-danger fade in">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<strong>Alert</strong> <%= flash[:alert] %>
</div>
<% end %>
<div style="text-align:right">
<a href="<%= mail_post_path(@post) %>" class="btn navbar-btn" style!="position:absolute;right:0;top:0;margin-top:2px;margin-top:3px;margin-right:3px;">
Mail
</a>
<a href="<%= fork_post_path(@post) %>" class="btn navbar-btn" style!="position:absolute;right:0;top:0;margin-top:2px;margin-top:3px;margin-right:3px;">
Fork
</a>
<a href="<%= edit_post_path(@post) %>" class="btn btn-primary navbar-btn" style!="position:absolute;right:0;top:0;margin-top:2px;margin-top:3px;margin-right:3px;">
<span class="glyphicon glyphicon-pencil"></span>
</a>
</div>
<div class="text-box title" style!="position:relative;">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
<a href="<%= post_path(@post) %>"><%= @post.title %></a>
</div>
<div class="text-box meta">
</h3>
</div>
<ul class="list-group">
<li class="list-group-item">
<%### Post meta ###%>
<% @post.tags.each do |tag| %>
<span class="label label-info">
<a href="<%= root_path(q: "##{tag.name}") %>">#<%= tag.name %></a>
<a href="<%= posts_path(q: "##{tag.name}") %>">#<%= tag.name %></a>
</span>
<% end %>
<span class="label label-success">
<a href="<%= root_path(q: "@#{@post.author.name}") %>">@<%= @post.author.name %></a>
<a href="<%= posts_path(q: "@#{@post.author.name}") %>">@<%= @post.author.name %></a>
</span>
<span class="label label-danger">
<a href="<%= root_path(q: "date:#{@post.updated_at.strftime('%Y-%m-%d')}") %>"><%= @post.updated_at.strftime('%Y-%m-%d') %></a>
<a href="<%= posts_path(q: "date:#{@post.updated_at.strftime('%Y-%m-%d')}") %>"><%= @post.updated_at.strftime('%Y-%m-%d') %></a>
</span>
</div>
<div class="text-box body viewer github">
<!-- Split button -->
<div class="btn-group pull-right" style="margin: -7px -12px 0 0;">
<button type="button" class="btn btn-primary">
<span class="glyphicon glyphicon-pencil"></span>
</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="<%= fork_post_path(@post) %>">Fork</a></li>
<li><a href="#" data-toggle="modal" data-target="#myModal">Mail to...</a></li>
<li class="divider"></li>
<li><%= link_to 'Delete', post_path(@post), method: :delete, data: { confirm: 'Are you sure?' } %></li>
</ul>
</div>
<%### /Post meta ###%>
</li>
</ul>
<div class="panel-body viewer github">
<%= h_application_format_markdown(@post.body) %>
</div>
</div>
<%### Comments ###%>
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">Comments</h3>
</div>
<div class="panel-body">
<ul class="media-list">
<% @post.comments.each do |comment| %>
<li class="media">
<a class="pull-left" href="#">
<img class="media-object" src="<%= comment.author.image_url %>">
</a>
<div class="media-body">
<h4 class="media-heading"><%= comment.author.name %></h4>
<%= comment.body %>
</div>
</li>
<% end %>
<%= form_tag(comment_post_path, method: :post, data: { 'form-id' => "comment_#{@post.id}" }) do %>
<li class="media">
<a class="pull-left" href="#">
<img class="media-object" src="<%= current_user.image_url %>">
</a>
<div class="media-body">
<h4 class="media-heading"><%= current_user.name %></h4>
<%= text_area :comment, :body, class: 'form-control', placeholder: 'コメントする...' %>
<%= submit_tag 'Comment', class: 'btn btn-primary', data: { 'disable-with' => '...' } %>
</div>
</li>
<% end %>
<script type="text/javascript">
$("form[data-form-id='comment_<%= @post.id %>']").on('ajax:success', function(event, data, xhr) {
});
</script>
</ul>
</div>
</div>
<%### /Comments ###%>
<!-- Button trigger modal -->
<!-- <button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
Launch demo modal
</button>
-->
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<%= form_tag mail_post_path(@post), method: :post, class: 'form-horizontal', role: 'form' do %>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="myModalLabel">Mail this post to...</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label class="col-sm-2 control-label">Title</label>
<div class="col-sm-10">
<input type="text" class="form-control" value="<%= @post.title %>" readonly>
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">To</label>
<div class="col-sm-10">
<input type="email" name="mail[to]" class="form-control" id="inputEmail3" placeholder="Email">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">From</label>
<div class="col-sm-10">
<input type="text" class="form-control" value="<%= current_user.email %>" readonly>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" data-disable-with="Sending...">Send</button>
</div>
</div><!-- /.modal-content -->
<% end %><%# form %>
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
......@@ -9,12 +9,20 @@
<div class="col-xs-6 col-md-4" id="sidebar" role="navigation">
<ul class="nav nav-tabs">
<li class="active"><a href="#tab-list" data-toggle="tab">List</a></li>
<li><a href="#tab-tree" data-toggle="tab">Tag Tree</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab-list">
<div class="list-group">
<% @posts.each do |post| %>
<% @posts.each_with_index do |post, i| %>
<a href="#" data-post-id="<%= post.id %>" class="list-group-item post-list"><%= post.title %></a>
<% end %>
</div>
</div><!-- /.tab-pane -->
<div class="tab-pane" id="tab-tree">
<% cache('tag-tree', :expires_in => 1.hour) do %>
<div class="list-group">
<% Tag.roots.each do |root| %>
......@@ -22,13 +30,15 @@
<% end %>
</div>
<% end %>
</div><!-- /.tab-pane -->
</div><!-- /.tab-content -->
</div><!--/span-->
<div class="col-xs-12 col-sm-6 col-md-8">
<div id="list_post">
<p style="color:#aaa;font-size:30px">&lt;-- Select a post...</p>
<p id="posts-placeholder" style="color:#aaa;font-size:30px">&lt;-- Select a post...</p>
</div>
</div><!--/span-->
......@@ -38,6 +48,9 @@
<hr>
<footer>
<a href="https://github.com/tadyjp/rendezvous">Github</a>
|
<a href="https://twitter.com/tady_jp">@tady_jp</a>
</footer>
</div><!--/.container-->
......
......@@ -6,22 +6,13 @@
<div class="container">
<div class="row">
<div class="col-xs-12 col-md-12">
<div id="xxxxxxxx">
<%= render partial: 'posts/show_fragment' %>
</div>
</div><!--/span-->
</div><!--/row-->
<hr>
<footer>
</footer>
</div><!--/.container-->
</div>
#! /usr/bin/env python
import sys
def main():
print "SET sql_mode='NO_BACKSLASH_ESCAPES';"
lines = sys.stdin.read().splitlines()
for line in lines:
processLine(line)
def processLine(line):
if (
line.startswith("PRAGMA") or
line.startswith("BEGIN TRANSACTION;") or
line.startswith("COMMIT;") or
line.startswith("DELETE FROM sqlite_sequence;") or
line.startswith("INSERT INTO \"sqlite_sequence\"")
):
return
line = line.replace("AUTOINCREMENT", "AUTO_INCREMENT")
line = line.replace("DEFAULT 't'", "DEFAULT '1'")
line = line.replace("DEFAULT 'f'", "DEFAULT '0'")
line = line.replace(",'t'", ",'1'")
line = line.replace(",'f'", ",'0'")
in_string = False
newLine = ''
for c in line:
if not in_string:
if c == "'":
in_string = True
elif c == '"':
newLine = newLine + '`'
continue
elif c == "'":
in_string = False
newLine = newLine + c
print newLine
if __name__ == "__main__":
main()
......@@ -20,7 +20,8 @@ module Rendezvous
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
config.i18n.default_locale = :ja
I18n.enforce_available_locales = true
config.i18n.default_locale = 'ja'
# config.action_mailer.delivery_method = :action_gmailer
config.action_mailer.smtp_settings = {
......
......@@ -4,19 +4,32 @@
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem 'sqlite3'
development:
adapter: sqlite3
database: db/development.sqlite3
adapter: mysql2
encoding: utf8
reconnect: false
database: <%= ENV['DB_DEVELOPMENT_DATABASE'] %>
pool: 5
timeout: 5000
username: <%= ENV['DB_DEVELOPMENT_USER'] %>
password: <%= ENV['DB_DEVELOPMENT_PASS'] %>
host: <%= ENV['DB_DEVELOPMENT_HOST'] %>
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
# test:
# adapter: sqlite3
# database: db/test.sqlite3
# pool: 5
# timeout: 5000
test:
adapter: sqlite3
database: db/test.sqlite3
adapter: mysql2
encoding: utf8
reconnect: false
database: <%= ENV['DB_TEST_DATABASE'] %>
pool: 5
timeout: 5000
username: <%= ENV['DB_TEST_USER'] %>
password: <%= ENV['DB_TEST_PASS'] %>
host: <%= ENV['DB_TEST_HOST'] %>
production:
adapter: sqlite3
......
# Be sure to restart your server when you modify this file.
Rendezvous::Application.config.session_store :cookie_store, key: '_rendezvous_session'
Rendezvous::Application.config.session_store :cookie_store,
key: '__rv__'
ja:
date:
abbr_day_names:
-
-
-
-
-
-
-
abbr_month_names:
-
- 1月
- 2月
- 3月
- 4月
- 5月
- 6月
- 7月
- 8月
- 9月
- 10月
- 11月
- 12月
day_names:
- 日曜日
- 月曜日
- 火曜日
- 水曜日
- 木曜日
- 金曜日
- 土曜日
formats:
default: ! '%Y/%m/%d'
long: ! '%Y年%m月%d日(%a)'
short: ! '%m/%d'
month_names:
-
- 1月
- 2月
- 3月
- 4月
- 5月
- 6月
- 7月
- 8月
- 9月
- 10月
- 11月
- 12月
order:
- :year
- :month
- :day
datetime:
distance_in_words:
about_x_hours:
one: 約1時間
other: 約%{count}時間
about_x_months:
one: 約1ヶ月
other: 約%{count}ヶ月
about_x_years:
one: 約1年
other: 約%{count}年
almost_x_years:
one: 1年弱
other: ! '%{count}年弱'
half_a_minute: 30秒前後
less_than_x_minutes:
one: 1分以内
other: ! '%{count}分未満'
less_than_x_seconds:
one: 1秒以内
other: ! '%{count}秒未満'
over_x_years:
one: 1年以上
other: ! '%{count}年以上'
x_days:
one: 1日
other: ! '%{count}日'
x_minutes:
one: 1分
other: ! '%{count}分'
x_months:
one: 1ヶ月
other: ! '%{count}ヶ月'
x_seconds:
one: 1秒
other: ! '%{count}秒'
prompts:
day:
hour:
minute:
month:
second:
year:
errors: &errors
format: ! '%{attribute}%{message}'
messages:
accepted: を受諾してください。
blank: を入力してください。
present: は入力しないでください。
confirmation: と%{attribute}の入力が一致しません。
empty: を入力してください。
equal_to: は%{count}にしてください。
even: は偶数にしてください。
exclusion: は予約されています。
greater_than: は%{count}より大きい値にしてください。
greater_than_or_equal_to: は%{count}以上の値にしてください。
inclusion: は一覧にありません。
invalid: は不正な値です。
less_than: は%{count}より小さい値にしてください。
less_than_or_equal_to: は%{count}以下の値にしてください。
not_a_number: は数値で入力してください。
not_an_integer: は整数で入力してください。
odd: は奇数にしてください。
record_invalid: バリデーションに失敗しました。 %{errors}
restrict_dependent_destroy: ! '%{record}が存在しているので削除できません。'
taken: はすでに存在します。
too_long: は%{count}文字以内で入力してください。
too_short: は%{count}文字以上で入力してください。
wrong_length: は%{count}文字で入力してください。
other_than: "は%{count}以外の値にしてください。"
template:
body: 次の項目を確認してください。
header:
one: ! '%{model}にエラーが発生しました。'
other: ! '%{model}に%{count}個のエラーが発生しました。'
helpers:
select:
prompt: 選択してください。
submit:
create: 登録する
submit: 保存する
update: 更新する
number:
currency:
format:
delimiter: ! ','
format: ! '%n%u'
precision: 0
separator: .
significant: false
strip_insignificant_zeros: false
unit:
format:
delimiter: ! ','
precision: 3
separator: .
significant: false
strip_insignificant_zeros: false
human:
decimal_units:
format: ! '%n %u'
units:
billion: 十億
million: 百万
quadrillion: 千兆
thousand:
trillion:
unit: ''
format:
delimiter: ''
precision: 3
significant: true
strip_insignificant_zeros: true
storage_units:
format: ! '%n%u'
units:
byte: バイト
gb: ギガバイト
kb: キロバイト
mb: メガバイト
tb: テラバイト
percentage:
format:
delimiter: ''
format: "%n%"
precision:
format:
delimiter: ''
support:
array:
last_word_connector:
two_words_connector:
words_connector:
time:
am: 午前
formats:
default: ! '%Y/%m/%d %H:%M:%S'
long: ! '%Y年%m月%d日(%a) %H時%M分%S秒 %z'
short: ! '%y/%m/%d %H:%M'
pm: 午後
# remove these aliases after 'activemodel' and 'activerecord' namespaces are removed from Rails repository
activemodel:
errors:
<<: *errors
activerecord:
errors:
<<: *errors
devise:
confirmations:
confirmed: アカウントを登録しました。
send_instructions: 登録方法を数分以内にメールでご連絡します。
send_paranoid_instructions: メールアドレスが登録されていれば、数分以内にアカウントを確認する方法が記載されているメールが届きます。
failure:
already_authenticated: 既にログインしています。
inactive: アカウントが有効化されていません。
invalid: メールアドレスまたはパスワードが違います。
last_attempt: あと一回間違えるとアカウントが凍結されます。
locked: アカウントが凍結されています。
not_found_in_database: メールアドレスまたはパスワードが違います。
timeout: セッションがタイムアウトしました。もう一度ログインしてください。
unauthenticated: 続けるにはログインまたはアカウントを登録してください。
unconfirmed: 本登録を行ってください。
mailer:
confirmation_instructions:
subject: アカウントの登録方法
reset_password_instructions:
subject: パスワードの再設定
unlock_instructions:
subject: アカウントの凍結解除
omniauth_callbacks:
failure: 「%{reason}」のため、%{kind}による認証ができませんでした。
success: '%{kind}による認証に成功しました。'
passwords:
no_token: パスワード再設定のメール以外からこのページへアクセスする事はできません。もしパスワード再設定のメールに記載されたリンクをクリックしてこのページへ訪れた場合、不完全なURLのリンクをクリックしていないか確認してください。メーラーによっては、リンクのURLが途中で切れる可能性があります。
send_instructions: パスワードの再設定方法を数分以内にメールでご連絡します。
send_paranoid_instructions: メールアドレスが登録されていれば、数分以内にパスワード再設定のメールが届きます。
updated: パスワードを変更し、ログインしました。
updated_not_active: パスワードを変更しました。
registrations:
destroyed: アカウントを削除しました。またのご利用をお待ちしております。
signed_up: アカウント登録を受け付けました。
signed_up_but_inactive: 登録に成功しました。しかし、アカウントが有効になっていないためログインできません。
signed_up_but_locked: 登録に成功しました。しかし、アカウントがロックされているためログインできません。
signed_up_but_unconfirmed: アカウント確認のリンクが入っているメールを送りました。 メール内のリンクでアカウントを有効にしてください。
update_needs_confirmation: アカウント情報を変更しました。しかし、メールアドレスを確認する必要があります。メール内のリンクで新しいメールアドレスを確認してください。
updated: アカウント情報を更新しました。
sessions:
signed_in: ログインしました。
signed_out: ログアウトしました。
unlocks:
send_instructions: アカウントの凍結解除方法を数分以内にメールでご連絡します。
send_paranoid_instructions: アカウントが登録されていれば、数分以内にアカウントの凍結解除方法が登録しているアドレスに届きます。
unlocked: アカウントを凍結解除しました。続けるにはログインしてください。
errors:
messages:
already_confirmed: は既に登録済みです
confirmation_period_expired: は%{period}以内に確認が必要です。もう一度要求してください。
expired: は期限が切れたため、新しく取得する必要があります
not_found: は見つかりませんでした
not_locked: は凍結されていません
not_saved: '%{count}個のエラーにより%{resource}を保存することができませんでした。'
ja:
activerecord:
models:
post: post #g
post_tag: post_tag #g
tag: tag #g
user: user #g
attributes:
post:
author: :activerecord.models.author #g
body: body #g
post_tags: post_tags #g
tags: tags #g
title: title #g
post_tag:
post: :activerecord.models.post #g
tag: :activerecord.models.tag #g
tag:
ancestry: ancestry #g
name: name #g
post_tags: post_tags #g
posts: posts #g
user:
current_sign_in_at: current_sign_in_at #g
current_sign_in_ip: current_sign_in_ip #g
email: email #g
encrypted_password: encrypted_password #g
google_auth_token: google_auth_token #g
google_refresh_token: google_refresh_token #g
google_token_expires_at: google_token_expires_at #g
image_url: image_url #g
last_sign_in_at: last_sign_in_at #g
last_sign_in_ip: last_sign_in_ip #g
name: name #g
posts: posts #g
remember_created_at: remember_created_at #g
reset_password_sent_at: reset_password_sent_at #g
reset_password_token: reset_password_token #g
......@@ -3,9 +3,10 @@ Rendezvous::Application.routes.draw do
root 'home#top', as: 'root'
post 'posts/preview' => 'posts#preview'
get 'posts/show_fragment' => 'posts#show_fragment'
# get 'posts/show_fragment' => 'posts#show_fragment'
get 'posts/:id/fork' => 'posts#fork', as: 'fork_post'
get 'posts/:id/mail' => 'posts#mail', as: 'mail_post'
post 'posts/:id/mail' => 'posts#mail', as: 'mail_post'
post 'posts/:id/comment' => 'posts#comment', as: 'comment_post'
resources :posts
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
......
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.integer :author_id
t.integer :post_id
t.text :body
t.timestamps
end
add_index :comments, [:author_id, :updated_at]
add_index :comments, [:post_id, :updated_at]
end
end
......@@ -11,7 +11,18 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20131228110818) do
ActiveRecord::Schema.define(version: 20140106160129) do
create_table 'comments', force: true do |t|
t.integer 'author_id'
t.integer 'post_id'
t.text 'body'
t.datetime 'created_at'
t.datetime 'updated_at'
end
add_index 'comments', ['author_id', 'updated_at'], name: 'index_comments_on_author_id_and_updated_at', using: :btree
add_index 'comments', ['post_id', 'updated_at'], name: 'index_comments_on_post_id_and_updated_at', using: :btree
create_table 'post_tags', force: true do |t|
t.integer 'post_id', null: false
......@@ -20,8 +31,8 @@ ActiveRecord::Schema.define(version: 20131228110818) do
t.datetime 'updated_at'
end
add_index 'post_tags', ['post_id'], name: 'index_post_tags_on_post_id'
add_index 'post_tags', ['tag_id'], name: 'index_post_tags_on_tag_id'
add_index 'post_tags', ['post_id'], name: 'index_post_tags_on_post_id', using: :btree
add_index 'post_tags', ['tag_id'], name: 'index_post_tags_on_tag_id', using: :btree
create_table 'posts', force: true do |t|
t.string 'title'
......@@ -38,7 +49,7 @@ ActiveRecord::Schema.define(version: 20131228110818) do
t.string 'ancestry'
end
add_index 'tags', ['ancestry'], name: 'index_tags_on_ancestry'
add_index 'tags', ['ancestry'], name: 'index_tags_on_ancestry', using: :btree
create_table 'users', force: true do |t|
t.string 'name'
......@@ -60,7 +71,7 @@ ActiveRecord::Schema.define(version: 20131228110818) do
t.datetime 'google_token_expires_at'
end
add_index 'users', ['email'], name: 'index_users_on_email', unique: true
add_index 'users', ['reset_password_token'], name: 'index_users_on_reset_password_token', unique: true
add_index 'users', ['email'], name: 'index_users_on_email', unique: true, using: :btree
add_index 'users', ['reset_password_token'], name: 'index_users_on_reset_password_token', unique: true, using: :btree
end
......@@ -39,12 +39,12 @@ _tag_tree.each do |_parent, _child|
end
# User
User.find_or_create_by(name: '山田太郎') do |_u|
user_1 = User.find_or_create_by(name: '山田太郎') do |_u|
_u.email = "#{Devise.friendly_token[0, 20]}@example.com"
_u.password = Devise.friendly_token[0, 20]
end
User.find_or_create_by(name: '鈴木二郎') do |_u|
user_2 = User.find_or_create_by(name: '鈴木二郎') do |_u|
_u.email = "#{Devise.friendly_token[0, 20]}@example.com"
_u.password = Devise.friendly_token[0, 20]
end
......@@ -57,13 +57,20 @@ end
# Post
users = User.all
Post.delete_all
Dir.glob(Rails.root.join('db', 'seeds').to_s + '/*').each do |file_name|
Rails.logger.debug "[Post Tag] #{file_name}"
title = file_name.split('/').last
post = Post.find_or_initialize_by(title: title)
post = Post.new(title: title)
post.body = File.read(file_name)
post.author = users.sample
post.tags = [tags.sample, tags.sample]
post.save!
end
# rubocop:disable LineLength
Post.first.comments.create(author: user_1, body: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.')
Post.first.comments.create(author: user_2, body: 'Hooooooo....')
Post.first.comments.create(author: user_1, body: 'It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.')
# rubocop:enable LineLength
![Screen Shot 2013-11-20 at 12.23.19 AM.png](https://qiita-image-store.s3.amazonaws.com/0/10272/474c4435-35b5-60ee-18ef-dd11e2bbce3c.png "Screen Shot 2013-11-20 at 12.23.19 AM.png")
### 最終更新日
- 2013-12-10
......
require 'spec_helper'
class DummyClass; end
describe RV::Mailer do
let(:klass) { DummyClass.new.extend(RV::Mailer) }
let(:alice) { FactoryGirl.create(:alice) }
let(:post) { Post.create title: 'ruby rspec', body: 'This is first espec test: ruby' }
it 'valid' do
expect { klass.compose_mail(post, user: alice, to: 'dummy@example.com') }.not_to raise_error(ArgumentError)
end
it 'missing post' do
expect { klass.compose_mail(nil, user: alice, to: 'dummy@example.com') }.to raise_error(ArgumentError)
end
it 'missing user' do
expect { klass.compose_mail(post, user: nil, to: 'dummy@example.com') }.to raise_error(ArgumentError)
end
it 'missing to' do
expect { klass.compose_mail(post, user: alice, to: nil) }.to raise_error(ArgumentError)
end
it 'invalid to' do
expect { klass.compose_mail(post, user: alice, to: 'invalid.email') }.to raise_error(ArgumentError)
end
end
# FactoryGirl.define do
# factory :comment_1, class: Comment do
# body 'ruby'
# end
# end
require 'spec_helper'
include Warden::Test::Helpers
Warden.test_mode!
describe 'Request via js', js: true do
let(:user) { FactoryGirl.create(:login_user_1) }
before do
@post1 = Post.create title: 'ruby rspec', body: 'This is first espec test: ruby', author_id: user.id
@post2 = Post.create title: 'php test', body: 'PHP is very easy', author_id: user.id
@post3 = Post.create title: 'java java...', body: 'Java is not ruby...', author_id: user.id
end
before :each do
login_as user, scope: :user
visit '/posts'
end
it 'show first post' do
page.save_screenshot(Rails.root.join('tmp', 'screenshots', "a-#{Time.now.strftime('%Y-%m-%d %H%M%S')}.png"))
expect(page.find('.panel-title a').text).to include('ruby rspec')
end
it 'click post and show' do
find('.post-list:nth-child(3)').click
page.save_screenshot(Rails.root.join('tmp', 'screenshots', "b-#{Time.now.strftime('%Y-%m-%d %H%M%S')}.png"))
expect(page.find('.panel-title a').text).to include('java java...')
end
after :each do
page.driver.reset!
Warden.test_reset!
end
end
require 'spec_helper'
describe Comment do
describe 'validations' do
it 'blank author_id' do
expect(Comment.new(post_id: 1, body: 'test')).not_to be_valid
end
it 'blank post_id' do
expect(Comment.new(author_id: 1, body: 'test')).not_to be_valid
end
it 'blank body' do
expect(Comment.new(post_id: 1, author_id: 2)).not_to be_valid
end
end
end
......@@ -3,19 +3,18 @@ require 'spec_helper'
describe User do
describe 'Instance method' do
before :each do
@alice = create(:alice)
@bob = create(:bob)
end
let(:alice) { create(:alice) }
let(:bob) { create(:bob) }
describe '#google_oauth_token_expired?' do
it 'not expired' do
expect(@alice.google_oauth_token_expired?).to be_false
expect(alice.google_oauth_token_expired?).to be_false
end
it 'expired' do
expect(@bob.google_oauth_token_expired?).to be_true
expect(bob.google_oauth_token_expired?).to be_true
end
end
......
......@@ -10,6 +10,19 @@ require 'rspec/autorun'
# require 'email_spec'
require 'factory_girl'
require 'capybara'
require 'capybara/rspec'
## Setting for polterguist.
require 'capybara/poltergeist'
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, timeout: 30)
end
Capybara.javascript_driver = :poltergeist
# Set capybara wait time (default: 2)
Capybara.default_wait_time = 10
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
......@@ -33,7 +46,7 @@ RSpec.configure do |config|
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
config.use_transactional_fixtures = false
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
......@@ -54,4 +67,17 @@ RSpec.configure do |config|
config.before(:all) do
FactoryGirl.reload
end
config.include Capybara::DSL
config.before :suite do
DatabaseRewinder.clean_all
end
# config.before :each do
# end
config.after :each do
DatabaseRewinder.clean
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment