├── .gitignore ├── Gemfile ├── Gemfile.lock ├── README.rdoc ├── Rakefile ├── app ├── assets │ ├── images │ │ ├── .keep │ │ ├── baby.jpg │ │ ├── backgound.png │ │ ├── bg-site.png │ │ ├── bg.jpg │ │ ├── car_1.jpg │ │ ├── car_2.jpg │ │ ├── car_3.jpg │ │ ├── daniel.jpg │ │ ├── demo.png │ │ ├── matt.jpg │ │ └── r.png │ ├── javascripts │ │ └── application.js │ └── stylesheets │ │ ├── application.css │ │ ├── application.css.scss │ │ ├── bootstrap.css │ │ ├── bootstrap_and_overrides.css.less │ │ ├── core.css.scss │ │ └── red.css ├── controllers │ ├── application_controller.rb │ ├── articles_controller.rb │ ├── callbacks_controller.rb │ ├── comments_controller.rb │ └── concerns │ │ └── .keep ├── helpers │ ├── application_helper.rb │ ├── articles_helper.rb │ └── comments_helper.rb ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── ability.rb │ ├── article.rb │ ├── comment.rb │ ├── concerns │ │ └── .keep │ ├── role.rb │ ├── settings.rb │ └── user.rb ├── uploaders │ └── avatar_uploader.rb └── views │ ├── application │ ├── _footer.html.erb │ └── _header.html.erb │ ├── articles │ ├── _form.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── index.rss.erb │ ├── new.html.erb │ └── show.html.erb │ ├── comments │ └── _comments.html.erb │ ├── layouts │ ├── application.html.erb │ └── blog.html.erb │ └── users │ ├── confirmations │ └── new.html.erb │ ├── mailer │ ├── confirmation_instructions.html.erb │ ├── reset_password_instructions.html.erb │ └── unlock_instructions.html.erb │ ├── passwords │ ├── edit.html.erb │ └── new.html.erb │ ├── registrations │ ├── edit.html.erb │ └── new.html.erb │ ├── sessions │ └── new.html.erb │ ├── shared │ └── _links.html.erb │ └── unlocks │ └── new.html.erb ├── bin ├── bundle ├── rails ├── rake └── setup ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── cookies_serializer.rb │ ├── default_settings.rb │ ├── devise.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── rails_admin.rb │ ├── rails_settings_ui.rb │ ├── rolify.rb │ ├── session_store.rb │ ├── simple_form.rb │ ├── simple_form_bootstrap.rb │ └── wrap_parameters.rb ├── locales │ ├── devise.en.yml │ ├── en.bootstrap.yml │ ├── en.yml │ ├── pagination.yml │ └── simple_form.en.yml ├── puma.rb ├── routes.rb └── secrets.yml ├── db ├── migrate │ ├── 20150303150726_devise_create_users.rb │ ├── 20150303150952_add_columns_to_users.rb │ ├── 20150307065926_create_articles.rb │ ├── 20150307074427_create_comments.rb │ ├── 20150315103101_add_view_count_to_articles.rb │ ├── 20150315112806_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb │ ├── 20150315112807_add_missing_unique_indices.acts_as_taggable_on_engine.rb │ ├── 20150315112808_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb │ ├── 20150315112809_add_missing_taggable_index.acts_as_taggable_on_engine.rb │ ├── 20150315112810_change_collation_for_tag_names.acts_as_taggable_on_engine.rb │ ├── 20150315142442_rolify_create_roles.rb │ ├── 20150318150436_add_avatar_to_users.rb │ └── 20150321020003_create_settings.rb ├── schema.rb └── seeds.rb ├── lib ├── assets │ └── .keep ├── tasks │ └── .keep └── templates │ └── haml │ └── scaffold │ └── _form.html.haml ├── log └── .keep ├── public ├── 404.html ├── 422.html ├── 500.html ├── favicon.ico └── robots.txt ├── test ├── controllers │ ├── .keep │ ├── articles_controller_test.rb │ ├── comments_controller_test.rb │ └── products_controller_test.rb ├── fixtures │ ├── .keep │ ├── articles.yml │ ├── comments.yml │ ├── products.yml │ ├── roles.yml │ └── users.yml ├── helpers │ └── .keep ├── integration │ └── .keep ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── article_test.rb │ ├── comment_test.rb │ ├── product_test.rb │ ├── role_test.rb │ └── user_test.rb └── test_helper.rb └── vendor └── assets ├── javascripts └── .keep └── stylesheets └── .keep /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | /db/*.sqlite3-journal 13 | 14 | # Ignore all logfiles and tempfiles. 15 | /log/* 16 | !/log/.keep 17 | /tmp 18 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | #source 'http://gems.ruby-china.org/' 2 | source 'https://rubygems.org' 3 | 4 | 5 | gem 'simple_form' 6 | gem 'rails-settings-ui', '~> 0.3.0' 7 | 8 | gem "rails-settings-cached", "0.4.1" 9 | gem 'kaminari' 10 | gem 'bootstrap-kaminari-views' 11 | 12 | gem 'mini_magick' 13 | gem 'carrierwave' 14 | gem 'rolify' 15 | gem 'cancancan', '~> 1.10' 16 | gem 'acts-as-taggable-on', '~> 3.4' 17 | gem "less-rails" #Sprockets (what Rails 3.1 uses for its asset pipeline) supports LESS 18 | gem "twitter-bootstrap-rails" 19 | gem 'rucaptcha' 20 | 21 | gem 'redcarpet' 22 | gem 'coderay' 23 | 24 | gem 'therubyracer' 25 | gem 'devise' 26 | gem 'omniauth' 27 | gem 'omniauth-github' 28 | gem 'omniauth-qq' 29 | gem 'omniauth-weibo-oauth2' 30 | 31 | gem 'rails_admin', '~> 0.6.6' 32 | 33 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 34 | gem 'rails', '4.2.0' 35 | # Use SCSS for stylesheets 36 | #gem 'sass-rails', '~> 5.0' 37 | # Use Uglifier as compressor for JavaScript assets 38 | gem 'uglifier', '>= 1.3.0' 39 | # Use CoffeeScript for .coffee assets and views 40 | gem 'coffee-rails', '~> 4.1.0' 41 | # See https://github.com/sstephenson/execjs#readme for more supported runtimes 42 | # gem 'therubyracer', platforms: :ruby 43 | 44 | # Use jquery as the JavaScript library 45 | gem 'jquery-rails' 46 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks 47 | gem 'turbolinks' 48 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 49 | gem 'jbuilder', '~> 2.0' 50 | # bundle exec rake doc:rails generates the API under doc/api. 51 | gem 'sdoc', '~> 0.4.0', group: :doc 52 | 53 | # Use ActiveModel has_secure_password 54 | # gem 'bcrypt', '~> 3.1.7' 55 | 56 | # Use Unicorn as the app server 57 | # gem 'unicorn' 58 | 59 | # Use Capistrano for deployment 60 | # gem 'capistrano-rails', group: :development 61 | 62 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 63 | gem 'spring' 64 | gem 'puma' 65 | 66 | group :development, :test do 67 | gem "better_errors" 68 | gem "binding_of_caller" 69 | 70 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 71 | gem 'byebug' 72 | 73 | # Access an IRB console on exception pages or by using <%= console %> in views 74 | gem 'web-console', '~> 2.0' 75 | 76 | # Use sqlite3 as the database for Active Record 77 | gem 'sqlite3' 78 | end 79 | 80 | group :production do 81 | # gem 'pg' 82 | gem 'sqlite3' 83 | gem 'rails_12factor' 84 | end 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://ruby.taobao.org/ 3 | specs: 4 | actionmailer (4.2.0) 5 | actionpack (= 4.2.0) 6 | actionview (= 4.2.0) 7 | activejob (= 4.2.0) 8 | mail (~> 2.5, >= 2.5.4) 9 | rails-dom-testing (~> 1.0, >= 1.0.5) 10 | actionpack (4.2.0) 11 | actionview (= 4.2.0) 12 | activesupport (= 4.2.0) 13 | rack (~> 1.6.0) 14 | rack-test (~> 0.6.2) 15 | rails-dom-testing (~> 1.0, >= 1.0.5) 16 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 17 | actionview (4.2.0) 18 | activesupport (= 4.2.0) 19 | builder (~> 3.1) 20 | erubis (~> 2.7.0) 21 | rails-dom-testing (~> 1.0, >= 1.0.5) 22 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 23 | activejob (4.2.0) 24 | activesupport (= 4.2.0) 25 | globalid (>= 0.3.0) 26 | activemodel (4.2.0) 27 | activesupport (= 4.2.0) 28 | builder (~> 3.1) 29 | activerecord (4.2.0) 30 | activemodel (= 4.2.0) 31 | activesupport (= 4.2.0) 32 | arel (~> 6.0) 33 | activesupport (4.2.0) 34 | i18n (~> 0.7) 35 | json (~> 1.7, >= 1.7.7) 36 | minitest (~> 5.1) 37 | thread_safe (~> 0.3, >= 0.3.4) 38 | tzinfo (~> 1.1) 39 | acts-as-taggable-on (3.5.0) 40 | activerecord (>= 3.2, < 5) 41 | arel (6.0.0) 42 | bcrypt (3.1.10) 43 | better_errors (2.0.0) 44 | coderay (>= 1.0.0) 45 | erubis (>= 2.6.6) 46 | rack (>= 0.9.0) 47 | binding_of_caller (0.7.2) 48 | debug_inspector (>= 0.0.1) 49 | bootstrap-kaminari-views (0.0.5) 50 | kaminari (>= 0.13) 51 | rails (>= 3.1) 52 | bootstrap-sass (3.2.0.2) 53 | sass (~> 3.2) 54 | builder (3.2.2) 55 | byebug (3.5.1) 56 | columnize (~> 0.8) 57 | debugger-linecache (~> 1.2) 58 | slop (~> 3.6) 59 | cancancan (1.10.1) 60 | carrierwave (0.10.0) 61 | activemodel (>= 3.2.0) 62 | activesupport (>= 3.2.0) 63 | json (>= 1.7) 64 | mime-types (>= 1.16) 65 | coderay (1.1.0) 66 | coffee-rails (4.1.0) 67 | coffee-script (>= 2.2.0) 68 | railties (>= 4.0.0, < 5.0) 69 | coffee-script (2.3.0) 70 | coffee-script-source 71 | execjs 72 | coffee-script-source (1.9.1) 73 | columnize (0.9.0) 74 | commonjs (0.2.7) 75 | debug_inspector (0.0.2) 76 | debugger-linecache (1.2.0) 77 | devise (3.4.1) 78 | bcrypt (~> 3.0) 79 | orm_adapter (~> 0.1) 80 | railties (>= 3.2.6, < 5) 81 | responders 82 | thread_safe (~> 0.1) 83 | warden (~> 1.2.3) 84 | erubis (2.7.0) 85 | execjs (2.3.0) 86 | faraday (0.9.1) 87 | multipart-post (>= 1.2, < 3) 88 | font-awesome-rails (4.3.0.0) 89 | railties (>= 3.2, < 5.0) 90 | globalid (0.3.3) 91 | activesupport (>= 4.1.0) 92 | haml (4.0.6) 93 | tilt 94 | haml-rails (0.9.0) 95 | actionpack (>= 4.0.1) 96 | activesupport (>= 4.0.1) 97 | haml (>= 4.0.6, < 5.0) 98 | html2haml (>= 1.0.1) 99 | railties (>= 4.0.1) 100 | hashie (3.4.0) 101 | hike (1.2.3) 102 | html2haml (2.0.0) 103 | erubis (~> 2.7.0) 104 | haml (~> 4.0.0) 105 | nokogiri (~> 1.6.0) 106 | ruby_parser (~> 3.5) 107 | i18n (0.7.0) 108 | jbuilder (2.2.9) 109 | activesupport (>= 3.0.0, < 5) 110 | multi_json (~> 1.2) 111 | jquery-rails (4.0.3) 112 | rails-dom-testing (~> 1.0) 113 | railties (>= 4.2.0) 114 | thor (>= 0.14, < 2.0) 115 | jquery-ui-rails (5.0.3) 116 | railties (>= 3.2.16) 117 | json (1.8.2) 118 | jwt (1.3.0) 119 | kaminari (0.16.3) 120 | actionpack (>= 3.0.0) 121 | activesupport (>= 3.0.0) 122 | less (2.6.0) 123 | commonjs (~> 0.2.7) 124 | less-rails (2.6.0) 125 | actionpack (>= 3.1) 126 | less (~> 2.6.0) 127 | libv8 (3.16.14.7) 128 | loofah (2.0.1) 129 | nokogiri (>= 1.5.9) 130 | mail (2.6.3) 131 | mime-types (>= 1.16, < 3) 132 | mime-types (2.4.3) 133 | mini_magick (4.0.1) 134 | mini_portile (0.6.2) 135 | minitest (5.5.1) 136 | multi_json (1.10.1) 137 | multi_xml (0.5.5) 138 | multipart-post (2.0.0) 139 | nested_form (0.3.2) 140 | nokogiri (1.6.6.2) 141 | mini_portile (~> 0.6.0) 142 | oauth (0.4.7) 143 | oauth2 (1.0.0) 144 | faraday (>= 0.8, < 0.10) 145 | jwt (~> 1.0) 146 | multi_json (~> 1.3) 147 | multi_xml (~> 0.5) 148 | rack (~> 1.2) 149 | omniauth (1.2.2) 150 | hashie (>= 1.2, < 4) 151 | rack (~> 1.0) 152 | omniauth-github (1.1.2) 153 | omniauth (~> 1.0) 154 | omniauth-oauth2 (~> 1.1) 155 | omniauth-oauth (1.0.1) 156 | oauth 157 | omniauth (~> 1.0) 158 | omniauth-oauth2 (1.2.0) 159 | faraday (>= 0.8, < 0.10) 160 | multi_json (~> 1.3) 161 | oauth2 (~> 1.0) 162 | omniauth (~> 1.2) 163 | omniauth-qq (0.3.0) 164 | multi_json 165 | omniauth (~> 1.0) 166 | omniauth-oauth (~> 1.0) 167 | omniauth-oauth2 (~> 1.0) 168 | omniauth-weibo-oauth2 (0.4.0) 169 | omniauth (~> 1.0) 170 | omniauth-oauth2 (~> 1.0) 171 | orm_adapter (0.5.0) 172 | pg (0.18.1) 173 | rack (1.6.0) 174 | rack-pjax (0.8.0) 175 | nokogiri (~> 1.5) 176 | rack (~> 1.1) 177 | rack-test (0.6.3) 178 | rack (>= 1.0) 179 | rails (4.2.0) 180 | actionmailer (= 4.2.0) 181 | actionpack (= 4.2.0) 182 | actionview (= 4.2.0) 183 | activejob (= 4.2.0) 184 | activemodel (= 4.2.0) 185 | activerecord (= 4.2.0) 186 | activesupport (= 4.2.0) 187 | bundler (>= 1.3.0, < 2.0) 188 | railties (= 4.2.0) 189 | sprockets-rails 190 | rails-deprecated_sanitizer (1.0.3) 191 | activesupport (>= 4.2.0.alpha) 192 | rails-dom-testing (1.0.5) 193 | activesupport (>= 4.2.0.beta, < 5.0) 194 | nokogiri (~> 1.6.0) 195 | rails-deprecated_sanitizer (>= 1.0.1) 196 | rails-html-sanitizer (1.0.1) 197 | loofah (~> 2.0) 198 | rails-settings-cached (0.4.1) 199 | rails (>= 4.0.0) 200 | rails-settings-ui (0.3.1) 201 | bootstrap-sass (~> 3.2.0) 202 | haml-rails 203 | i18n 204 | rails (>= 3.0) 205 | sass-rails (>= 4.0.0) 206 | rails_12factor (0.0.3) 207 | rails_serve_static_assets 208 | rails_stdout_logging 209 | rails_admin (0.6.6) 210 | builder (~> 3.1) 211 | coffee-rails (~> 4.0) 212 | font-awesome-rails (>= 3.0, < 5) 213 | haml (~> 4.0) 214 | jquery-rails (>= 3.0, < 5) 215 | jquery-ui-rails (~> 5.0) 216 | kaminari (~> 0.14) 217 | nested_form (~> 0.3) 218 | rack-pjax (~> 0.7) 219 | rails (~> 4.0) 220 | remotipart (~> 1.0) 221 | safe_yaml (~> 1.0) 222 | sass-rails (>= 4.0, < 6) 223 | rails_serve_static_assets (0.0.2) 224 | rails_stdout_logging (0.0.3) 225 | railties (4.2.0) 226 | actionpack (= 4.2.0) 227 | activesupport (= 4.2.0) 228 | rake (>= 0.8.7) 229 | thor (>= 0.18.1, < 2.0) 230 | rake (10.4.2) 231 | rdoc (4.2.0) 232 | json (~> 1.4) 233 | redcarpet (3.2.2) 234 | ref (1.0.5) 235 | remotipart (1.2.1) 236 | responders (2.1.0) 237 | railties (>= 4.2.0, < 5) 238 | rolify (4.0.0) 239 | ruby_parser (3.6.5) 240 | sexp_processor (~> 4.1) 241 | safe_yaml (1.0.4) 242 | sass (3.4.13) 243 | sass-rails (5.0.1) 244 | railties (>= 4.0.0, < 5.0) 245 | sass (~> 3.1) 246 | sprockets (>= 2.8, < 4.0) 247 | sprockets-rails (>= 2.0, < 4.0) 248 | tilt (~> 1.1) 249 | sdoc (0.4.1) 250 | json (~> 1.7, >= 1.7.7) 251 | rdoc (~> 4.0) 252 | sexp_processor (4.5.0) 253 | simple_form (3.1.0) 254 | actionpack (~> 4.0) 255 | activemodel (~> 4.0) 256 | slop (3.6.0) 257 | spring (1.3.3) 258 | sprockets (2.12.3) 259 | hike (~> 1.2) 260 | multi_json (~> 1.0) 261 | rack (~> 1.0) 262 | tilt (~> 1.1, != 1.3.0) 263 | sprockets-rails (2.2.4) 264 | actionpack (>= 3.0) 265 | activesupport (>= 3.0) 266 | sprockets (>= 2.8, < 4.0) 267 | sqlite3 (1.3.10) 268 | therubyracer (0.12.1) 269 | libv8 (~> 3.16.14.0) 270 | ref 271 | thor (0.19.1) 272 | thread_safe (0.3.4) 273 | tilt (1.4.1) 274 | turbolinks (2.5.3) 275 | coffee-rails 276 | twitter-bootstrap-rails (3.2.0) 277 | actionpack (~> 4.1) 278 | execjs (~> 2.2) 279 | rails (~> 4.1) 280 | railties (~> 4.1) 281 | tzinfo (1.2.2) 282 | thread_safe (~> 0.1) 283 | uglifier (2.7.1) 284 | execjs (>= 0.3.0) 285 | json (>= 1.8.0) 286 | warden (1.2.3) 287 | rack (>= 1.0) 288 | web-console (2.1.0) 289 | activemodel (>= 4.0) 290 | binding_of_caller (>= 0.7.2) 291 | railties (>= 4.0) 292 | sprockets-rails (>= 2.0, < 4.0) 293 | 294 | PLATFORMS 295 | ruby 296 | 297 | DEPENDENCIES 298 | acts-as-taggable-on (~> 3.4) 299 | better_errors 300 | binding_of_caller 301 | bootstrap-kaminari-views 302 | byebug 303 | cancancan (~> 1.10) 304 | carrierwave 305 | coderay 306 | coffee-rails (~> 4.1.0) 307 | devise 308 | jbuilder (~> 2.0) 309 | jquery-rails 310 | kaminari 311 | less-rails 312 | mini_magick 313 | omniauth 314 | omniauth-github 315 | omniauth-qq 316 | omniauth-weibo-oauth2 317 | pg 318 | rails (= 4.2.0) 319 | rails-settings-cached (= 0.4.1) 320 | rails-settings-ui (~> 0.3.0) 321 | rails_12factor 322 | rails_admin (~> 0.6.6) 323 | redcarpet 324 | rolify 325 | sdoc (~> 0.4.0) 326 | simple_form 327 | spring 328 | sqlite3 329 | therubyracer 330 | turbolinks 331 | twitter-bootstrap-rails 332 | uglifier (>= 1.3.0) 333 | web-console (~> 2.0) 334 | -------------------------------------------------------------------------------- /README.rdoc: -------------------------------------------------------------------------------- 1 | Rails4[Wordpress Style BLog] 2 | ========== 3 | 4 | Detail Introduction: https://ruby-china.org/topics/24666 5 | 6 | 7 | Heroku Demo Link: 8 | https://wilsonsblog.herokuapp.com/ 9 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/images/baby.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/baby.jpg -------------------------------------------------------------------------------- /app/assets/images/backgound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/backgound.png -------------------------------------------------------------------------------- /app/assets/images/bg-site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/bg-site.png -------------------------------------------------------------------------------- /app/assets/images/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/bg.jpg -------------------------------------------------------------------------------- /app/assets/images/car_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/car_1.jpg -------------------------------------------------------------------------------- /app/assets/images/car_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/car_2.jpg -------------------------------------------------------------------------------- /app/assets/images/car_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/car_3.jpg -------------------------------------------------------------------------------- /app/assets/images/daniel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/daniel.jpg -------------------------------------------------------------------------------- /app/assets/images/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/demo.png -------------------------------------------------------------------------------- /app/assets/images/matt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/matt.jpg -------------------------------------------------------------------------------- /app/assets/images/r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/assets/images/r.png -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require jquery 14 | //= require jquery_ujs 15 | //= require twitter/bootstrap 16 | //= require turbolinks 17 | //= require_tree . 18 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This is a manifest file that'll automatically include all the stylesheets available in this directory 4 | * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at 5 | * the top of the compiled file, but it's generally better to create a new file per style scope. 6 | *= require_self 7 | *= require_tree . 8 | */ 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css.scss: -------------------------------------------------------------------------------- 1 | @import "bootstrap-sprockets"; 2 | @import "bootstrap"; 3 | 4 | body { 5 | padding-top: 60px; 6 | } 7 | 8 | .footer { 9 | padding: 70px 0; 10 | margin-top: 70px; 11 | border-top: 1px solid #e5e5e5; 12 | background-color: #f5f5f5; 13 | } 14 | 15 | .footer p { 16 | margin-bottom: 0; 17 | color: #777; 18 | } 19 | 20 | .footer-links { 21 | margin: 10px 0; 22 | padding: 0; 23 | } 24 | 25 | .footer-links li { 26 | display: inline; 27 | padding: 0 2px; 28 | } 29 | 30 | .footer-links li:first-child { 31 | padding-left: 0; 32 | } 33 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bootstrap_and_overrides.css.less: -------------------------------------------------------------------------------- 1 | 2 | // Set the correct sprite paths 3 | @iconSpritePath: image-url("twitter/bootstrap/glyphicons-halflings.png"); 4 | @iconWhiteSpritePath: image-url("twitter/bootstrap/glyphicons-halflings-white.png"); 5 | 6 | // Set the Font Awesome (Font Awesome is default. You can disable by commenting below lines) 7 | @fontAwesomeEotPath: font-url("fontawesome-webfont.eot"); 8 | @fontAwesomeEotPath_iefix: font-url("fontawesome-webfont.eot?#iefix"); 9 | @fontAwesomeWoffPath: font-url("fontawesome-webfont.woff"); 10 | @fontAwesomeTtfPath: font-url("fontawesome-webfont.ttf"); 11 | @fontAwesomeSvgPath: font-url("fontawesome-webfont.svg#fontawesomeregular"); 12 | 13 | // Font Awesome 14 | @import "fontawesome/font-awesome"; 15 | 16 | // Glyphicons 17 | //@import "twitter/bootstrap/glyphicons.less"; 18 | 19 | // Your custom LESS stylesheets goes here 20 | // 21 | // Since bootstrap was imported above you have access to its mixins which 22 | // you may use and inherit here 23 | // 24 | // If you'd like to override bootstrap's own variables, you can do so here as well 25 | // See http://twitter.github.com/bootstrap/customize.html#variables for their names and documentation 26 | // 27 | // Example: 28 | @link-color: #ff0000; 29 | -------------------------------------------------------------------------------- /app/assets/stylesheets/core.css.scss: -------------------------------------------------------------------------------- 1 | ::selection { 2 | background: #d9534f; 3 | color: white; 4 | } 5 | body { 6 | background-color: #f0f0f0; 7 | background: image-url("bg.jpg"); 8 | word-wrap: break-word; 9 | } 10 | body.nav-fixed { 11 | position: relative; 12 | padding-top: 54px; 13 | } 14 | @media (min-width: 768px) and (max-width: 991px) { 15 | body.nav-fixed { 16 | padding-top: 94px; 17 | } 18 | } 19 | a:hover { 20 | text-decoration: none; 21 | } 22 | h1, 23 | h2, 24 | h3, 25 | h4, 26 | h5 { 27 | font-weight: 100; 28 | } 29 | ul { 30 | list-style-type: none; 31 | } 32 | .ad { 33 | margin-bottom: 30px; 34 | } 35 | .ad * { 36 | max-width: 100%; 37 | } 38 | .zan-radius { 39 | border-radius: 4px; 40 | } 41 | .inline-block { 42 | display: inline-block; 43 | *display: inline; 44 | *zoom: 1; 45 | } 46 | .zan-opacity-5 { 47 | filter: alpha(opacity=50); 48 | -khtml-opacity: 0.5; 49 | -moz-opacity: 0.5; 50 | opacity: 0.5; 51 | } 52 | .white-space { 53 | white-space: nowrap; 54 | text-overflow: ellipsis; 55 | overflow: hidden; 56 | } 57 | .zan-transition { 58 | -webkit-transition: all .3s ease; 59 | -moz-transition: all .3s ease; 60 | -o-transition: all .3s ease; 61 | transition: all .3s ease; 62 | } 63 | .transform-scale { 64 | -webkit-transform: scale(1.25); 65 | -moz-transform: scale(1.25); 66 | -o-transform: scale(1.25); 67 | transform: scale(1.25); 68 | } 69 | .transform-rotate { 70 | -webkit-transform: rotate(360deg); 71 | -moz-transform: rotate(360deg); 72 | transform: rotate(360deg); 73 | } 74 | @keyframes pined { 75 | from { 76 | top: -10px; 77 | } 78 | to { 79 | top: -3px; 80 | } 81 | } 82 | @-webkit-keyframes pined { 83 | from { 84 | top: -10px; 85 | } 86 | to { 87 | top: -3px; 88 | } 89 | } 90 | 91 | 92 | div[class*="danger"] a { 93 | color: #d9534f; 94 | } 95 | div[class*="danger"] a:hover { 96 | color: #b94a48; 97 | } 98 | div[class*="success"] a { 99 | color: #5cb85c; 100 | } 101 | div[class*="success"] a:hover { 102 | color: #468847; 103 | } 104 | div[class*="warning"] a { 105 | color: #f0ad4e; 106 | } 107 | div[class*="warning"] a:hover { 108 | color: #c09853; 109 | } 110 | div[class*="info"] a { 111 | color: #5bc0de; 112 | } 113 | div[class*="info"] a:hover { 114 | color: #3a87ad; 115 | } 116 | div[class*="danger"] .badge { 117 | background-color: #d9534f; 118 | } 119 | div[class*="success"] .badge { 120 | background-color: #5cb85c; 121 | } 122 | /* =========================== 颜色样å¼�结æ�Ÿ =========================== */ 123 | /* =========================== 自定义BootStrapæ ·å¼� =========================== */ 124 | .label { 125 | margin-right: 5px; 126 | font-size: 90%; 127 | } 128 | .alert { 129 | padding: 15px; 130 | margin-bottom: 20px; 131 | border: 1px solid transparent; 132 | border-radius: 4px; 133 | overflow: auto; 134 | } 135 | .alert.alert-dismissable { 136 | padding-right: 35px; 137 | } 138 | .alert-zan { 139 | color: #666666; 140 | background-color: #eeeeee; 141 | border: 1px solid #eeeeee; 142 | } 143 | .alert-info { 144 | color: #3a87ad; 145 | background-color: #d9edf7; 146 | border-color: #bce8f1; 147 | } 148 | .panel-zan a { 149 | color: #666666; 150 | } 151 | .panel-zan a:hover { 152 | color: #b94a48; 153 | } 154 | .panel-zan > .panel-heading { 155 | color: white; 156 | background-color: #3d4450; 157 | border-color: #000; 158 | } 159 | .panel-zan > .panel-heading + .panel-collapse .panel-body { 160 | border-top-color: #000; 161 | } 162 | .panel-zan > .panel-footer + .panel-collapse .panel-body { 163 | border-bottom-color: #000; 164 | } 165 | .panel-zan .tab-content a:hover, 166 | .panel-zan .nav-pills a:hover { 167 | color: white; 168 | } 169 | .panel-zan .badge { 170 | background-color: #d9534f; 171 | } 172 | .pagination-zan { 173 | margin: 0; 174 | border-radius: 4px; 175 | } 176 | .pagination-zan li > a, 177 | .pagination-zan li > span { 178 | color: #d9534f; 179 | border: 2px solid #d9534f; 180 | background-color: transparent; 181 | margin-left: 10px; 182 | border-radius: 4px; 183 | } 184 | .pagination-zan li > a:hover, 185 | .pagination-zan li > span:hover { 186 | color: white; 187 | border: 2px solid #d9534f; 188 | background-color: #d9534f; 189 | -webkit-transition: all .3s ease; 190 | -moz-transition: all .3s ease; 191 | -o-transition: all .3s ease; 192 | transition: all .3s ease; 193 | } 194 | .pagination-zan .active a, 195 | .pagination-zan .active span { 196 | color: white; 197 | border: 2px solid #d9534f; 198 | background-color: #d9534f; 199 | -webkit-transition: all .3s ease; 200 | -moz-transition: all .3s ease; 201 | -o-transition: all .3s ease; 202 | transition: all .3s ease; 203 | } 204 | .pagination-zan .active a:hover, 205 | .pagination-zan .active span:hover { 206 | color: white; 207 | border: 2px solid #d9534f; 208 | background-color: #d9534f; 209 | -webkit-transition: all .3s ease; 210 | -moz-transition: all .3s ease; 211 | -o-transition: all .3s ease; 212 | transition: all .3s ease; 213 | cursor: not-allowed; 214 | } 215 | .btn-zan-solid-pp { 216 | color: #d9534f; 217 | background-color: transparent; 218 | border: 2px solid #d9534f; 219 | -webkit-transition: all .3s ease; 220 | -moz-transition: all .3s ease; 221 | -o-transition: all .3s ease; 222 | transition: all .3s ease; 223 | } 224 | .btn-zan-solid-pp .badge { 225 | color: #d9534f; 226 | background-color: transparent; 227 | border: 2px solid #d9534f; 228 | -webkit-transition: all .3s ease; 229 | -moz-transition: all .3s ease; 230 | -o-transition: all .3s ease; 231 | transition: all .3s ease; 232 | } 233 | .btn-zan-solid-pp:hover { 234 | color: white; 235 | background-color: #d9534f; 236 | border: 2px solid #d9534f; 237 | -webkit-transition: all .3s ease; 238 | -moz-transition: all .3s ease; 239 | -o-transition: all .3s ease; 240 | transition: all .3s ease; 241 | } 242 | .btn-zan-solid-pp:hover .badge { 243 | color: white; 244 | background-color: #d9534f; 245 | border: 2px solid white; 246 | -webkit-transition: all .3s ease; 247 | -moz-transition: all .3s ease; 248 | -o-transition: all .3s ease; 249 | transition: all .3s ease; 250 | } 251 | .btn-zan-solid-wp { 252 | background-color: white; 253 | border-color: #eeeeee; 254 | color: #b94a48; 255 | font-size: 21px; 256 | margin-bottom: 5px; 257 | margin-top: 5px; 258 | padding: 18px 24px; 259 | } 260 | .btn-zan-solid-wp:hover { 261 | background-color: #b94a48; 262 | border-color: #b94a48; 263 | color: white; 264 | } 265 | .btn-inverse-primary { 266 | color: white !important; 267 | background-color: #3d4450; 268 | border-color: #3d4450; 269 | -webkit-transition: all .3s ease; 270 | -moz-transition: all .3s ease; 271 | -o-transition: all .3s ease; 272 | transition: all .3s ease; 273 | } 274 | .btn-inverse-primary:hover { 275 | -webkit-transition: all .3s ease; 276 | -moz-transition: all .3s ease; 277 | -o-transition: all .3s ease; 278 | transition: all .3s ease; 279 | color: white !important; 280 | background-color: #d9534f; 281 | border-color: #d9534f; 282 | } 283 | @media (min-width: 768px) { 284 | .navbar-nav { 285 | float: none; 286 | } 287 | } 288 | 289 | 290 | #ie-warning { 291 | display: none; 292 | } 293 | html.ie #ie-warning { 294 | display: block; 295 | } 296 | html.ie .row { 297 | margin: 0; 298 | } 299 | html.ie #bdshare a { 300 | display: none; 301 | } 302 | html.ie #ds-thread .ds-no-transition#ds-reset .ds-post-button { 303 | background: #d9534f !important; 304 | } 305 | .flex-direction-nav a { 306 | filter: alpha(opacity=0); 307 | } 308 | .flex-control-thumbs img { 309 | filter: alpha(opacity=70); 310 | } 311 | .flexslider:hover .flex-next, 312 | .flexslider:hover .flex-prev { 313 | filter: alpha(opacity=80); 314 | } 315 | .flexslider:hover .flex-next:hover, 316 | .flexslider:hover .flex-prev:hover, 317 | .flex-control-thumbs img:hover, 318 | .flex-control-thumbs .flex-active { 319 | filter: alpha(opacity=100); 320 | } 321 | 322 | 323 | @media (min-width: 1200px) { 324 | .random .visible-lg, 325 | .recent .visible-lg, 326 | .hot .visible-lg.visible-sm { 327 | display: inline-block !important; 328 | } 329 | } 330 | @media (min-width: 992px) and (max-width: 1199px) { 331 | .random .visible-md, 332 | .recent .visible-md, 333 | .hot .visible-xs.visible-md { 334 | display: inline-block !important; 335 | } 336 | } 337 | @media (min-width: 768px) and (max-width: 991px) { 338 | .hot .visible-lg.visible-sm { 339 | display: inline-block !important; 340 | } 341 | .navbar-brand { 342 | margin-right: auto !important; 343 | margin-left: auto !important; 344 | display: block; 345 | float: none !important; 346 | } 347 | .navbar-nav { 348 | width: 100%; 349 | text-align: center; 350 | } 351 | .navbar-nav > li { 352 | float: none !important; 353 | display: inline-block !important; 354 | } 355 | .navbar-nav > li > a { 356 | padding: 10px !important; 357 | } 358 | #load-more { 359 | margin-bottom: 30px; 360 | } 361 | .navbar-header { 362 | float: none; 363 | } 364 | } 365 | @media (max-width: 767px) { 366 | .hot .visible-xs.visible-md { 367 | display: inline-block !important; 368 | } 369 | #zan-bodyer { 370 | font-size: 12px !important; 371 | } 372 | .bs-masthead { 373 | margin: 0; 374 | padding: 10px; 375 | } 376 | .bs-masthead h1 { 377 | font-size: 16px; 378 | } 379 | .bs-masthead .btn { 380 | font-size: 12px; 381 | padding: 6px 12px; 382 | } 383 | .bs-masthead p { 384 | font-size: 12px; 385 | } 386 | #zan-footer { 387 | padding: 20px; 388 | } 389 | #load-more { 390 | margin-bottom: 30px; 391 | } 392 | } 393 | /* =========================== å“�应å¼�结æ�Ÿ =========================== */ 394 | /* =========================== å°�工具样å¼� =========================== */ 395 | #sidebar aside > div { 396 | margin-bottom: 30px; 397 | } 398 | /*æ�œç´¢æ¡†*/ 399 | div.search { 400 | margin-bottom: 20px; 401 | border: 2px solid white; 402 | padding: 8px; 403 | border-radius: 4px; 404 | background-color: #3d4450; 405 | } 406 | div.search input[type="text"] { 407 | width: 85%; 408 | float: left; 409 | margin-right: 10px; 410 | } 411 | @media (max-width: 1199px) and (min-width: 992px) { 412 | div.search input[type="text"] { 413 | width: 82%; 414 | } 415 | } 416 | @media (max-width: 991px) and (min-width: 768px) { 417 | div.search input[type="text"] { 418 | width: 93%; 419 | } 420 | } 421 | @media (max-width: 767px) { 422 | div.search input[type="text"] { 423 | width: 82%; 424 | } 425 | } 426 | div.search button { 427 | float: left; 428 | margin-top: 2px; 429 | } 430 | /*å¹»ç�¯ç‰‡*/ 431 | .metaslider { 432 | border-radius: 4px; 433 | margin-bottom: 40px !important; 434 | -webkit-box-shadow: 0 0px 5px #999999; 435 | -moz-box-shadow: 0 0px 5px #999999; 436 | box-shadow: 0 0px 5px #999999; 437 | } 438 | @media (max-width: 767px) { 439 | .metaslider { 440 | margin-bottom: 20px; 441 | } 442 | } 443 | .metaslider img { 444 | border-radius: 4px; 445 | } 446 | .metaslider .flex-direction-nav a { 447 | width: 40px; 448 | height: 40px; 449 | margin: -20px 0 0; 450 | display: block; 451 | background: url(../images/arrow.png) no-repeat 0 0; 452 | position: absolute; 453 | top: 50%; 454 | z-index: 10; 455 | cursor: pointer; 456 | text-indent: -9999px; 457 | -webkit-transition: all .3s ease; 458 | -moz-transition: all .3s ease; 459 | -o-transition: all .3s ease; 460 | transition: all .3s ease; 461 | } 462 | .metaslider .flex-direction-nav a:hover { 463 | background: url(../images/arrow_hover.png) no-repeat 0 0; 464 | } 465 | .metaslider .flex-direction-nav .flex-next { 466 | background-position: 0 100%; 467 | } 468 | .metaslider .flex-direction-nav .flex-next:hover { 469 | background-position: 0 100%; 470 | } 471 | .panel-heading { 472 | border-bottom: none; 473 | font-size: 14px; 474 | line-height: 14px; 475 | font-weight: normal; 476 | } 477 | .panel-toggle, 478 | .panel-remove { 479 | float: right; 480 | margin: 0px 0px 0px 5px; 481 | cursor: pointer; 482 | } 483 | .panel-toggle:hover, 484 | .panel-remove:hover { 485 | color: #d9534f; 486 | -webkit-transition: all .3s ease; 487 | -moz-transition: all .3s ease; 488 | -o-transition: all .3s ease; 489 | transition: all .3s ease; 490 | } 491 | .panel.toggled { 492 | -webkit-box-shadow: none; 493 | -moz-box-shadow: none; 494 | box-shadow: none; 495 | -webkit-transition: all .3s ease; 496 | -moz-transition: all .3s ease; 497 | -o-transition: all .3s ease; 498 | transition: all .3s ease; 499 | } 500 | .panel ul.list-group { 501 | max-height: 500px; 502 | overflow: hidden; 503 | width: 100%; 504 | -webkit-transition: all .3s ease; 505 | -moz-transition: all .3s ease; 506 | -o-transition: all .3s ease; 507 | transition: all .3s ease; 508 | } 509 | .panel.toggled ul.list-group { 510 | overflow: hidden; 511 | max-height: 0px; 512 | width: 100%; 513 | -webkit-transition: all .3s ease; 514 | -moz-transition: all .3s ease; 515 | -o-transition: all .3s ease; 516 | transition: all .3s ease; 517 | } 518 | .panel.toggled .panel-heading { 519 | border-bottom-right-radius: 3px; 520 | border-bottom-left-radius: 3px; 521 | -webkit-transition: all .3s ease; 522 | -moz-transition: all .3s ease; 523 | -o-transition: all .3s ease; 524 | transition: all .3s ease; 525 | } 526 | ul.pills-zan { 527 | padding: 10px; 528 | } 529 | ul.pills-zan li { 530 | margin-left: 5px; 531 | } 532 | #sidebar-tags a:hover { 533 | color: #d9534f; 534 | } 535 | .pills-danger li.active > a, 536 | .pills-danger li.active > a:hover { 537 | background-color: #d9534f !important; 538 | border-color: #d43f3a !important; 539 | } 540 | .tab-content { 541 | border-top: 1px solid #eeeeee; 542 | padding: 10px; 543 | } 544 | .tagcloud { 545 | padding: 10px 20px 20px 20px; 546 | } 547 | .tagcloud a { 548 | background-color: #5bc0de; 549 | color: white; 550 | border-radius: 4px; 551 | padding: 2px 5px; 552 | font-size: 14px !important; 553 | margin-right: 15px; 554 | margin-bottom: 10px; 555 | display: inline-block; 556 | *display: inline; 557 | *zoom: 1; 558 | } 559 | .tag-article a, 560 | .tag-article a:hover { 561 | color: white; 562 | } 563 | .panel.archive > a .panel-heading { 564 | background-color: #d9534f; 565 | border-radius: 4px; 566 | color: white; 567 | text-align: center; 568 | -webkit-transition: all .3s ease; 569 | -moz-transition: all .3s ease; 570 | -o-transition: all .3s ease; 571 | transition: all .3s ease; 572 | } 573 | .panel.archive > a:hover { 574 | text-decoration: none !important; 575 | } 576 | .panel.archive > a:hover .panel-heading { 577 | background-color: #3d4450; 578 | -webkit-transition: all .3s ease; 579 | -moz-transition: all .3s ease; 580 | -o-transition: all .3s ease; 581 | transition: all .3s ease; 582 | } 583 | .comment-log { 584 | line-height: 20px; 585 | background-color: #eeeeee; 586 | border-color: #eeeeee; 587 | border-radius: 4px; 588 | display: inline-block; 589 | *display: inline; 590 | *zoom: 1; 591 | padding: 8px; 592 | margin-left: 10px; 593 | white-space: nowrap; 594 | text-overflow: ellipsis; 595 | overflow: hidden; 596 | width: 80%; 597 | } 598 | .author-avatar .avatar { 599 | border-radius: 50%; 600 | border: 1px solid #eeeeee; 601 | position: relative; 602 | z-index: 99; 603 | float: left; 604 | display: block; 605 | -webkit-transition: all .3s ease; 606 | -moz-transition: all .3s ease; 607 | -o-transition: all .3s ease; 608 | transition: all .3s ease; 609 | } 610 | .author-avatar .avatar:hover { 611 | -webkit-transform: scale(1.25); 612 | -moz-transform: scale(1.25); 613 | -o-transform: scale(1.25); 614 | transform: scale(1.25); 615 | -webkit-transition: all .3s ease; 616 | -moz-transition: all .3s ease; 617 | -o-transition: all .3s ease; 618 | transition: all .3s ease; 619 | } 620 | /*ä¾§è¾¹æ �-广告*/ 621 | .host img { 622 | display: block; 623 | width: 100%; 624 | height: auto; 625 | -webkit-transition: all .3s ease; 626 | -moz-transition: all .3s ease; 627 | -o-transition: all .3s ease; 628 | transition: all .3s ease; 629 | } 630 | .host img:hover { 631 | filter: alpha(opacity=50); 632 | -khtml-opacity: 0.5; 633 | -moz-opacity: 0.5; 634 | opacity: 0.5; 635 | -webkit-transition: all .3s ease; 636 | -moz-transition: all .3s ease; 637 | -o-transition: all .3s ease; 638 | transition: all .3s ease; 639 | } 640 | /*å�‹æƒ…链接*/ 641 | .blogroll li { 642 | margin-bottom: 10px; 643 | } 644 | .panel .post-title { 645 | display: inline-block; 646 | *display: inline; 647 | *zoom: 1; 648 | width: 75%; 649 | white-space: nowrap; 650 | text-overflow: ellipsis; 651 | overflow: hidden; 652 | } 653 | .login-form { 654 | background-color: white; 655 | padding: 30px 20px; 656 | } 657 | .login-form .input-group-addon { 658 | background-color: #d9534f; 659 | color: white; 660 | border: 2px solid #d9534f; 661 | } 662 | .login-form .input-group-addon i { 663 | width: 15px; 664 | } 665 | .login-form .form-control { 666 | display: inline-block; 667 | *display: inline; 668 | *zoom: 1; 669 | padding: 10px 5px; 670 | border-left: none; 671 | } 672 | .login-form .btn { 673 | width: 48%; 674 | padding: 10px; 675 | } 676 | .login-form img { 677 | border: 3px solid #d9534f; 678 | border-radius: 50%; 679 | padding: 3px; 680 | } 681 | .login-panel { 682 | height: 100px; 683 | padding: 20px 0px; 684 | } 685 | @media (min-width: 992px) and (max-width: 1199px) { 686 | .login-panel { 687 | padding: 20px 0; 688 | } 689 | } 690 | .login-panel img { 691 | margin-right: 20px; 692 | border-radius: 50%; 693 | border: 2px solid white; 694 | background-color: white; 695 | -webkit-transition: all .3s ease; 696 | -moz-transition: all .3s ease; 697 | -o-transition: all .3s ease; 698 | transition: all .3s ease; 699 | } 700 | .login-panel img:hover { 701 | -webkit-transition: all .3s ease; 702 | -moz-transition: all .3s ease; 703 | -o-transition: all .3s ease; 704 | transition: all .3s ease; 705 | -webkit-transform: rotate(360deg); 706 | -moz-transform: rotate(360deg); 707 | transform: rotate(360deg); 708 | } 709 | .login-panel a:hover { 710 | color: #d9534f; 711 | } 712 | .login-panel .user-name { 713 | margin-right: 20px; 714 | } 715 | /* =========================== å°�工具样å¼�结æ�Ÿ =========================== */ 716 | /* =========================== 页é�¢å¤´éƒ¨æ ·å¼� =========================== */ 717 | #zan-header.navbar { 718 | border-radius: 0; 719 | font-size: 14px; 720 | } 721 | #if-fixed { 722 | position: absolute; 723 | top: 15px; 724 | right: 20px; 725 | } 726 | #if-fixed input { 727 | opacity: 0; 728 | } 729 | #if-fixed i { 730 | position: relative; 731 | top: -3px; 732 | right: 5px; 733 | color: white; 734 | } 735 | .navbar-fixed-top #if-fixed i { 736 | color: #d9534f; 737 | -webkit-transition: all .3s ease; 738 | -moz-transition: all .3s ease; 739 | -o-transition: all .3s ease; 740 | transition: all .3s ease; 741 | -webkit-animation: pined .5s; 742 | animation: pined .5s; 743 | } 744 | .navbar-brand { 745 | background: image-url("logo.png") no-repeat; 746 | width: 200px; 747 | height: 50px; 748 | display: block; 749 | } 750 | .nav.navbar-nav > li > .dropdown-menu > li { 751 | position: relative; 752 | } 753 | .nav.navbar-nav > li > .dropdown-menu .dropdown-menu { 754 | left: 100%; 755 | top: 0; 756 | } 757 | .dropdown-menu > li > a:hover, 758 | .dropdown-menu > li > a:focus { 759 | color: #ffffff; 760 | text-decoration: none; 761 | background-color: #d9534f !important; 762 | -webkit-transition: all .3s ease; 763 | -moz-transition: all .3s ease; 764 | -o-transition: all .3s ease; 765 | transition: all .3s ease; 766 | } 767 | /* =========================== 页é�¢å¤´éƒ¨æ ·å¼�结æ�Ÿ =========================== */ 768 | /* =========================== 主体样å¼� =========================== */ 769 | #zan-bodyer { 770 | padding: 30px 0; 771 | } 772 | .zan-breadcrumb { 773 | background-color: white; 774 | box-shadow: 0 0px 5px #c2c2c2; 775 | margin-bottom: 40px; 776 | } 777 | #article-list { 778 | margin-top: 20px; 779 | } 780 | .article iframe, 781 | .article embed { 782 | width: 100%; 783 | height: 500px; 784 | } 785 | @media (max-width: 1199px) { 786 | .article iframe, 787 | .article embed { 788 | height: 350px; 789 | } 790 | } 791 | @media (max-width: 767px) { 792 | .article iframe, 793 | .article embed { 794 | height: 200px; 795 | } 796 | } 797 | /*文章*/ 798 | .article { 799 | position: relative; 800 | margin-bottom: 30px; 801 | padding-bottom: 20px; 802 | } 803 | /*文章-置顶*/ 804 | .article-stick { 805 | position: absolute; 806 | top: -10px; 807 | right: 5%; 808 | font-size: 40px; 809 | color: #d9534f; 810 | } 811 | /*文章ï¼�日期*/ 812 | .data-article { 813 | background-color: #d9534f; 814 | border-color: #d43f3a; 815 | position: absolute; 816 | height: 70px; 817 | width: 70px; 818 | border-radius: 100px; 819 | left: -20px; 820 | top: -20px; 821 | color: white; 822 | padding-top: 10px; 823 | } 824 | .data-article span.month, 825 | .data-article span.day { 826 | text-align: center; 827 | display: block; 828 | } 829 | .data-article span.month { 830 | margin: 0; 831 | } 832 | .data-article span.day { 833 | font-size: 30px; 834 | font-weight: bold; 835 | margin-top: -5px; 836 | } 837 | /*文章ï¼�标题*/ 838 | .title-article { 839 | padding: 20px 15px 0px 15px; 840 | } 841 | @media (max-width: 767px) { 842 | .title-article { 843 | padding: 0px; 844 | } 845 | } 846 | .title-article h1 { 847 | font-size: 32px; 848 | margin: 0 auto; 849 | text-align: center; 850 | } 851 | .title-article h1 a { 852 | color: #3d4450; 853 | } 854 | .title-article h1 a:hover { 855 | color: #d9534f; 856 | text-decoration: none; 857 | -webkit-transition: all .3s ease; 858 | -moz-transition: all .3s ease; 859 | -o-transition: all .3s ease; 860 | transition: all .3s ease; 861 | } 862 | /*文章ï¼�标签*/ 863 | .label-zan:hover { 864 | background-color: #d9534f; 865 | -webkit-transition: all .3s ease; 866 | -moz-transition: all .3s ease; 867 | -o-transition: all .3s ease; 868 | transition: all .3s ease; 869 | } 870 | .tag-article { 871 | text-align: center; 872 | line-height: 24px; 873 | margin: 20px; 874 | } 875 | /*文章ï¼�内容*/ 876 | .centent-article .thumbnail { 877 | margin-bottom: 20px; 878 | } 879 | .centent-article img { 880 | margin: 10px auto; 881 | display: block; 882 | } 883 | /*文章ï¼�更多*/ 884 | .read-more .badge { 885 | background-color: white; 886 | color: #d9534f; 887 | padding: 2px 5px; 888 | margin-left: 3px; 889 | } 890 | /* 文章ï¼�分页*/ 891 | .zan-page .pager li > a, 892 | .zan-page .pager li > span { 893 | border-radius: 4px; 894 | } 895 | /*相关文章*/ 896 | #post-related { 897 | padding: 0 19px 19px 19px; 898 | } 899 | #post-related .thumbnail { 900 | border: 1px solid #eeeeee; 901 | } 902 | #post-related .post-related-title { 903 | white-space: nowrap; 904 | text-overflow: ellipsis; 905 | overflow: hidden; 906 | } 907 | #post-related .post-related-content { 908 | height: 100px; 909 | } 910 | /*异步加载*/ 911 | #infscr-loading img { 912 | display: none !important; 913 | } 914 | /* =========================== 主体样å¼�结æ�Ÿ =========================== */ 915 | /* =========================== 页脚样å¼� =========================== */ 916 | #zan-footer { 917 | display: block; 918 | text-align: center; 919 | color: #eeeeee; 920 | padding: 50px; 921 | background-color: #3d4450; 922 | } 923 | #zan-footer a { 924 | color: #eeeeee; 925 | } 926 | #zan-footer a:hover { 927 | color: #d9534f; 928 | } 929 | #zan-gotop { 930 | position: fixed; 931 | bottom: 20px; 932 | right: 20px; 933 | height: 40px; 934 | width: 40px; 935 | border-radius: 50%; 936 | border: 2px solid white; 937 | background-color: #3d4450; 938 | top: auto; 939 | display: block; 940 | cursor: pointer; 941 | z-index: 999; 942 | color: white; 943 | } 944 | #zan-gotop i { 945 | font-size: 30px; 946 | line-height: 36px; 947 | text-align: center; 948 | display: block; 949 | } 950 | #zan-gotop:hover { 951 | border-color: #d9534f; 952 | color: #d9534f; 953 | -webkit-transition: all .3s ease; 954 | -moz-transition: all .3s ease; 955 | -o-transition: all .3s ease; 956 | transition: all .3s ease; 957 | } 958 | /* 百度统计 */ 959 | embed[name*="Holmes"] { 960 | padding-top: 10px; 961 | } 962 | /* =========================== 页脚样å¼�结æ�Ÿ =========================== */ 963 | /* =========================== 评论样å¼� =========================== */ 964 | .comments-header { 965 | text-align: center; 966 | font-size: 14px; 967 | } 968 | #loading-comments { 969 | font-size: 30px; 970 | display: none; 971 | color: #d9534f; 972 | text-align: center; 973 | } 974 | .commentlist { 975 | padding: 0; 976 | } 977 | .commentlist #loading, 978 | .commentlist #error { 979 | margin-bottom: 10px; 980 | color: #d9534f; 981 | } 982 | .commentlist .comment-awaiting-moderation { 983 | color: #5bc0de; 984 | } 985 | .commentlist a { 986 | color: #3d4450; 987 | } 988 | .commentlist a:hover { 989 | color: #d9534f; 990 | } 991 | .commentlist ol { 992 | padding-left: 20px; 993 | } 994 | @media (max-width: 767px) { 995 | .commentlist ol { 996 | padding-left: 5px; 997 | } 998 | } 999 | .commentlist li { 1000 | margin: 10px 0px 10px 0px; 1001 | list-style: none; 1002 | border: 2px solid #f1f5f8; 1003 | padding: 2px; 1004 | background-color: white; 1005 | border-radius: 4px; 1006 | } 1007 | .commentlist .comment-body { 1008 | position: relative; 1009 | } 1010 | .commentlist .comment-body .comment-meta { 1011 | background: #f1f5f8; 1012 | position: relative; 1013 | height: auto; 1014 | min-height: 37px; 1015 | line-height: 37px; 1016 | padding-left: 45px; 1017 | } 1018 | @media (max-width: 767px) { 1019 | .commentlist .comment-body .comment-meta { 1020 | padding-left: 30px; 1021 | } 1022 | } 1023 | .commentlist .comment-body .comment-meta .comment-author { 1024 | float: left; 1025 | } 1026 | .commentlist .comment-body .comment-meta .comment-author .says { 1027 | margin-left: 10px; 1028 | } 1029 | .commentlist .comment-body .comment-meta img { 1030 | background-color: white; 1031 | border: 4px solid white; 1032 | border-radius: 50%; 1033 | position: absolute; 1034 | display: block; 1035 | left: -40px; 1036 | top: 10px; 1037 | margin: 0; 1038 | -webkit-transition: all .3s ease; 1039 | -moz-transition: all .3s ease; 1040 | -o-transition: all .3s ease; 1041 | transition: all .3s ease; 1042 | } 1043 | @media (max-width: 767px) { 1044 | .commentlist .comment-body .comment-meta img { 1045 | left: -25px; 1046 | width: 50px; 1047 | height: 50px; 1048 | } 1049 | } 1050 | .commentlist .comment-body .comment-meta img:hover { 1051 | -webkit-transition: all .3s ease; 1052 | -moz-transition: all .3s ease; 1053 | -o-transition: all .3s ease; 1054 | transition: all .3s ease; 1055 | -webkit-transform: rotate(360deg); 1056 | -moz-transform: rotate(360deg); 1057 | transform: rotate(360deg); 1058 | } 1059 | .commentlist .comment-body .comment-metadata { 1060 | text-transform: uppercase; 1061 | float: right; 1062 | margin-right: 10px; 1063 | font-size: 12px; 1064 | text-decoration: none; 1065 | font-weight: bold; 1066 | border-radius: 4px; 1067 | } 1068 | @media (max-width: 767px) { 1069 | .commentlist .comment-body .comment-metadata { 1070 | display: none; 1071 | } 1072 | } 1073 | .commentlist .comment-body .comment-content { 1074 | padding: 20px 55px 30px 45px; 1075 | position: relative; 1076 | } 1077 | @media (max-width: 767px) { 1078 | .commentlist .comment-body .comment-content { 1079 | padding: 10px 10px 20px 30px; 1080 | } 1081 | } 1082 | .commentlist .comment-body .comment-reply-link, 1083 | .commentlist .comment-body .comment-reply-login { 1084 | position: absolute; 1085 | bottom: 3px; 1086 | right: 12px; 1087 | font-size: 12px; 1088 | text-transform: uppercase; 1089 | display: block; 1090 | } 1091 | #comment-nav { 1092 | margin-top: 20px; 1093 | } 1094 | .page-numbers { 1095 | border-radius: 4px; 1096 | color: #d9534f; 1097 | background-color: transparent; 1098 | border: 2px solid #d9534f; 1099 | -webkit-transition: all .3s ease; 1100 | -moz-transition: all .3s ease; 1101 | -o-transition: all .3s ease; 1102 | transition: all .3s ease; 1103 | display: inline-block; 1104 | *display: inline; 1105 | *zoom: 1; 1106 | margin: 0 0 10px 10px; 1107 | padding: 5px 10px; 1108 | } 1109 | .page-numbers .badge { 1110 | color: #d9534f; 1111 | background-color: transparent; 1112 | border: 2px solid #d9534f; 1113 | -webkit-transition: all .3s ease; 1114 | -moz-transition: all .3s ease; 1115 | -o-transition: all .3s ease; 1116 | transition: all .3s ease; 1117 | } 1118 | .page-numbers:hover { 1119 | color: white; 1120 | background-color: #d9534f; 1121 | border: 2px solid #d9534f; 1122 | -webkit-transition: all .3s ease; 1123 | -moz-transition: all .3s ease; 1124 | -o-transition: all .3s ease; 1125 | transition: all .3s ease; 1126 | } 1127 | .page-numbers:hover .badge { 1128 | color: white; 1129 | background-color: #d9534f; 1130 | border: 2px solid white; 1131 | -webkit-transition: all .3s ease; 1132 | -moz-transition: all .3s ease; 1133 | -o-transition: all .3s ease; 1134 | transition: all .3s ease; 1135 | } 1136 | .page-numbers.current { 1137 | color: white; 1138 | background-color: #d9534f; 1139 | cursor: not-allowed; 1140 | } 1141 | .page-numbers.dots { 1142 | border: none; 1143 | } 1144 | .page-numbers.dots:hover { 1145 | color: #d9534f; 1146 | background-color: transparent; 1147 | } 1148 | #reply-title { 1149 | padding: 15px; 1150 | margin-bottom: 20px; 1151 | border: 1px solid transparent; 1152 | border-radius: 4px; 1153 | overflow: auto; 1154 | color: #3a87ad; 1155 | background-color: #d9edf7; 1156 | border-color: #bce8f1; 1157 | margin: 10px auto; 1158 | text-align: center; 1159 | font-size: 14px; 1160 | } 1161 | #reply-title.alert-dismissable { 1162 | padding-right: 35px; 1163 | } 1164 | #reply-title a:hover { 1165 | color: white; 1166 | } 1167 | #reply-title #cancel-comment-reply-link { 1168 | padding: 2px 5px; 1169 | background-color: #d9534f; 1170 | color: white; 1171 | border-radius: 4px; 1172 | } 1173 | #smilelink { 1174 | cursor: pointer; 1175 | margin-bottom: 10px; 1176 | } 1177 | #smilelink img:hover { 1178 | filter: alpha(opacity=50); 1179 | -khtml-opacity: 0.5; 1180 | -moz-opacity: 0.5; 1181 | opacity: 0.5; 1182 | } 1183 | #commentform .input-group label.error { 1184 | display: block; 1185 | } 1186 | #commentform label.error { 1187 | margin-right: 1px; 1188 | font-size: 12px; 1189 | color: white; 1190 | background-color: #d9534f; 1191 | padding: 10px; 1192 | margin-bottom: 0; 1193 | box-shadow: 0 0 1px rgba(0, 0, 0, 0); 1194 | -webkit-transform: translateZ(0); 1195 | transform: translateZ(0); 1196 | -webkit-animation: wobble-horizontal 1s ease-in-out; 1197 | animation: wobble-horizontal 1s ease-in-out; 1198 | } 1199 | @media (max-width: 1199px) and (min-width: 992px) { 1200 | #commentform label.error { 1201 | margin-right: 0; 1202 | } 1203 | } 1204 | @media (max-width: 991px) { 1205 | #commentform label.error { 1206 | margin-right: 2px; 1207 | } 1208 | } 1209 | @media (max-width: 767px) { 1210 | #commentform label.error { 1211 | margin-right: 0; 1212 | } 1213 | } 1214 | #commentform .logged-in-as { 1215 | display: none; 1216 | } 1217 | #commentform .form-allowed-tags { 1218 | margin-top: 10px; 1219 | } 1220 | @media (max-width: 767px) { 1221 | #commentform .form-allowed-tags { 1222 | display: none; 1223 | } 1224 | } 1225 | #commentform .input-group { 1226 | margin-bottom: 20px; 1227 | } 1228 | #commentform .input-group .input-group-addon { 1229 | background-color: #d9534f; 1230 | color: white; 1231 | border: 2px solid #d9534f; 1232 | } 1233 | #commentform .input-group .input-group-addon i { 1234 | width: 15px; 1235 | } 1236 | #commentform input { 1237 | padding: 10px 25px; 1238 | background-color: transparent; 1239 | border: 2px solid #d9534f; 1240 | } 1241 | @media (max-width: 1199px) and (min-width: 992px) { 1242 | #commentform input { 1243 | padding: 10px 5px; 1244 | } 1245 | } 1246 | @media (max-width: 991px) { 1247 | #commentform input { 1248 | padding: 10px 20px; 1249 | } 1250 | } 1251 | @media (max-width: 767px) { 1252 | #commentform input { 1253 | width: 100%; 1254 | } 1255 | } 1256 | #commentform textarea { 1257 | margin: 0; 1258 | margin-bottom: 10px; 1259 | padding: 10px 15px; 1260 | width: 100%; 1261 | border-radius: 4px; 1262 | background-color: transparent; 1263 | border: 2px solid #c1c1c1; 1264 | } 1265 | #commentform textarea:focus { 1266 | border: 2px solid #d9534f; 1267 | } 1268 | #commentform input:focus, 1269 | #commentform textarea:focus { 1270 | outline: 0; 1271 | -webkit-transition: all .3s ease; 1272 | -moz-transition: all .3s ease; 1273 | -o-transition: all .3s ease; 1274 | transition: all .3s ease; 1275 | } 1276 | #commentform #submit { 1277 | margin-top: 10px; 1278 | margin-bottom: 10px; 1279 | border-radius: 4px; 1280 | width: 100%; 1281 | color: #d9534f; 1282 | background-color: transparent; 1283 | border: 2px solid #d9534f; 1284 | -webkit-transition: all .3s ease; 1285 | -moz-transition: all .3s ease; 1286 | -o-transition: all .3s ease; 1287 | transition: all .3s ease; 1288 | } 1289 | #commentform #submit .badge { 1290 | color: #d9534f; 1291 | background-color: transparent; 1292 | border: 2px solid #d9534f; 1293 | -webkit-transition: all .3s ease; 1294 | -moz-transition: all .3s ease; 1295 | -o-transition: all .3s ease; 1296 | transition: all .3s ease; 1297 | } 1298 | #commentform #submit:hover { 1299 | color: white; 1300 | background-color: #d9534f; 1301 | border: 2px solid #d9534f; 1302 | -webkit-transition: all .3s ease; 1303 | -moz-transition: all .3s ease; 1304 | -o-transition: all .3s ease; 1305 | transition: all .3s ease; 1306 | } 1307 | #commentform #submit:hover .badge { 1308 | color: white; 1309 | background-color: #d9534f; 1310 | border: 2px solid white; 1311 | -webkit-transition: all .3s ease; 1312 | -moz-transition: all .3s ease; 1313 | -o-transition: all .3s ease; 1314 | transition: all .3s ease; 1315 | } 1316 | 1317 | #ds-thread #ds-reset .ds-post-button { 1318 | background: #d9534f !important; 1319 | border-color: #d9534f !important; 1320 | color: white !important; 1321 | text-shadow: none !important; 1322 | } 1323 | #ds-thread #ds-reset .ds-post-button:hover { 1324 | background: #d9534f !important; 1325 | border-color: #d43f3a !important; 1326 | } 1327 | #ds-thread #ds-reset .ds-powered-by { 1328 | display: none; 1329 | } 1330 | /* =========================== 评论样å¼�结æ�Ÿ =========================== */ 1331 | /* =========================== 下载页é�¢æ ·å¼� =========================== */ 1332 | .bs-masthead { 1333 | margin-bottom: 20px; 1334 | position: relative; 1335 | text-align: center; 1336 | } 1337 | @media (max-width: 1199px) { 1338 | .bs-masthead { 1339 | padding: 0; 1340 | } 1341 | } 1342 | .bs-masthead h1 { 1343 | font-size: 80px; 1344 | line-height: 1; 1345 | } 1346 | @media (max-width: 1199px) { 1347 | .bs-masthead h1 { 1348 | font-size: 40px; 1349 | } 1350 | } 1351 | .bs-masthead p { 1352 | font-size: 20px; 1353 | margin-left: 15%; 1354 | margin-right: 15%; 1355 | } 1356 | @media (max-width: 1199px) { 1357 | .bs-masthead p { 1358 | margin-right: 5%; 1359 | margin-left: 5%; 1360 | } 1361 | } 1362 | -------------------------------------------------------------------------------- /app/assets/stylesheets/red.css: -------------------------------------------------------------------------------- 1 | /* iCheck plugin Flat skin, red 2 | ----------------------------------- */ 3 | .icheckbox_flat-red, 4 | .iradio_flat-red { 5 | display: inline-block; 6 | margin: 0; 7 | padding: 0; 8 | width: 20px; 9 | height: 20px; 10 | background: url(red.png) no-repeat; 11 | border: none; 12 | cursor: pointer; 13 | } 14 | 15 | .icheckbox_flat-red { 16 | background-position: 0 0; 17 | } 18 | .icheckbox_flat-red.checked { 19 | background-position: -22px 0; 20 | } 21 | .icheckbox_flat-red.disabled { 22 | background-position: -44px 0; 23 | cursor: default; 24 | } 25 | .icheckbox_flat-red.checked.disabled { 26 | background-position: -66px 0; 27 | } 28 | 29 | .iradio_flat-red { 30 | background-position: -88px 0; 31 | } 32 | .iradio_flat-red.checked { 33 | background-position: -110px 0; 34 | } 35 | .iradio_flat-red.disabled { 36 | background-position: -132px 0; 37 | cursor: default; 38 | } 39 | .iradio_flat-red.checked.disabled { 40 | background-position: -154px 0; 41 | } 42 | 43 | /* Retina support */ 44 | @media only screen and (-webkit-min-device-pixel-ratio: 1.5), 45 | only screen and (-moz-min-device-pixel-ratio: 1.5), 46 | only screen and (-o-min-device-pixel-ratio: 3/2), 47 | only screen and (min-device-pixel-ratio: 1.5) { 48 | .icheckbox_flat-red, 49 | .iradio_flat-red { 50 | background-image: url(red@2x.png); 51 | -webkit-background-size: 176px 22px; 52 | background-size: 176px 22px; 53 | } 54 | } -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Prevent CSRF attacks by raising an exception. 3 | # For APIs, you may want to use :null_session instead. 4 | protect_from_forgery with: :exception 5 | before_action :authenticate_user! 6 | before_action :queryArticles 7 | before_filter :configure_permitted_parameters, if: :devise_controller? 8 | 9 | def queryArticles 10 | @key_word = params[:key_word] 11 | @tag = params[:tag] 12 | 13 | if (@key_word) 14 | @articles = Article.where("text like ? or title like ?", "%" + params[:key_word] + "%", "%" + params[:key_word] + "%").order(updated_at: :desc).page(params[:page]).per(Settings.page_size) 15 | elsif(@tag) 16 | @articles = Article.tagged_with(@tag).page(params[:page]).per(Settings.page_size) 17 | else 18 | @articles = Article.page(params[:page]).per(Settings.page_size).order(updated_at: :desc) 19 | end 20 | @hot_comments = Comment.order(updated_at: :desc).limit(Settings.hot_comments_size) 21 | 22 | @hot_articles = Article.order(view_count: :desc).limit(Settings.hot_articles_size) 23 | end 24 | 25 | def after_sign_in_path_for(resource) 26 | if resource.is_a?(User) 27 | if User.count == 1 28 | resource.add_role 'admin' 29 | end 30 | resource 31 | end 32 | root_path 33 | end 34 | 35 | protected 36 | 37 | def configure_permitted_parameters 38 | devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, 39 | :password_confirmation, :remember_me, :avatar, :avatar_cache) } 40 | devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:username, :email, :password, 41 | :password_confirmation, :current_password, :avatar, :avatar_cache) } 42 | end 43 | 44 | end 45 | -------------------------------------------------------------------------------- /app/controllers/articles_controller.rb: -------------------------------------------------------------------------------- 1 | class ArticlesController < ApplicationController 2 | load_and_authorize_resource 3 | layout 'blog' 4 | 5 | def index 6 | respond_to do |format| 7 | format.html 8 | format.rss { @articles = Article.all() } 9 | end 10 | end 11 | 12 | def new 13 | @article = Article.new 14 | end 15 | 16 | def create 17 | #render plain: params[:article].inspect 18 | @article = Article.new(article_params) 19 | 20 | if @article.save 21 | redirect_to @article 22 | else 23 | render 'new' 24 | end 25 | end 26 | 27 | def edit 28 | @article = Article.find(params[:id]) 29 | end 30 | 31 | def update 32 | @article = Article.find(params[:id]) 33 | 34 | if @article.update(article_params) 35 | redirect_to @article 36 | else 37 | render 'edit' 38 | end 39 | end 40 | def show 41 | @article = Article.find(params[:id]) 42 | currentViewCount = @article.view_count || 0 43 | 44 | logger.info "currentViewCount: " + currentViewCount.to_s 45 | @article.update(view_count: currentViewCount+1) 46 | end 47 | 48 | def destroy 49 | @article = Article.find(params[:id]) 50 | @article.destroy 51 | 52 | redirect_to articles_path 53 | end 54 | 55 | private 56 | def article_params 57 | params.require(:article).permit(:title, :text, :tag_list, :tag_list => []) 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /app/controllers/callbacks_controller.rb: -------------------------------------------------------------------------------- 1 | class CallbacksController < Devise::OmniauthCallbacksController 2 | def github 3 | processResponse 4 | end 5 | 6 | def weibo 7 | processResponse 8 | end 9 | 10 | def qq_connect 11 | processResponse 12 | end 13 | 14 | def processResponse 15 | @user = User.from_omniauth(request.env["omniauth.auth"]) 16 | sign_in_and_redirect @user 17 | end 18 | 19 | def sign_out 20 | sign_out @user 21 | end 22 | end -------------------------------------------------------------------------------- /app/controllers/comments_controller.rb: -------------------------------------------------------------------------------- 1 | class CommentsController < ApplicationController 2 | def create 3 | @article = Article.find(params[:article_id]) 4 | 5 | requestParams = comment_params() 6 | requestParams[:commenter] = current_user.email 7 | 8 | @comment = @article.comments.create(requestParams) 9 | redirect_to article_path(@article) 10 | end 11 | 12 | def destroy 13 | @article = Article.find(params[:article_id]) 14 | @comment = @article.comments.find(params[:id]) 15 | @comment.destroy 16 | redirect_to article_path(@article) 17 | end 18 | 19 | private 20 | def comment_params 21 | params.require(:comment).permit(:commenter, :body) 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | def markdown(text) 3 | options = { 4 | :autolink => true, 5 | :space_after_headers => true, 6 | :fenced_code_blocks => true, 7 | :no_intra_emphasis => true, 8 | :hard_wrap => true, 9 | :strikethrough =>true 10 | } 11 | markdown = Redcarpet::Markdown.new(HTMLwithCodeRay,options) 12 | markdown.render(h(text)).html_safe 13 | end 14 | 15 | class HTMLwithCodeRay < Redcarpet::Render::HTML 16 | def block_code(code, language) 17 | CodeRay.scan(code, language).div(:tab_width=>2) 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /app/helpers/articles_helper.rb: -------------------------------------------------------------------------------- 1 | module ArticlesHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/comments_helper.rb: -------------------------------------------------------------------------------- 1 | module CommentsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/mailers/.keep -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/models/.keep -------------------------------------------------------------------------------- /app/models/ability.rb: -------------------------------------------------------------------------------- 1 | class Ability 2 | include CanCan::Ability 3 | 4 | def initialize(user) 5 | # Define abilities for the passed in user here. For example: 6 | 7 | user ||= User.new # guest user (not logged in) 8 | p user 9 | if user.has_role? :admin 10 | p "admin" 11 | #can :manage, Article 12 | can :manage, :all 13 | else 14 | p "user" 15 | can :read, :all 16 | end 17 | 18 | # 19 | # The first argument to `can` is the action you are giving the user 20 | # permission to do. 21 | # If you pass :manage it will apply to every action. Other common actions 22 | # here are :read, :create, :update and :destroy. 23 | # 24 | # The second argument is the resource the user can perform the action on. 25 | # If you pass :all it will apply to every resource. Otherwise pass a Ruby 26 | # class of the resource. 27 | # 28 | # The third argument is an optional hash of conditions to further filter the 29 | # objects. 30 | # For example, here the user can only update published articles. 31 | # 32 | # can :update, Article, :published => true 33 | # 34 | # See the wiki for details: 35 | # https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /app/models/article.rb: -------------------------------------------------------------------------------- 1 | class Article < ActiveRecord::Base 2 | acts_as_taggable 3 | acts_as_taggable_on :tags 4 | 5 | has_many :comments, dependent: :destroy 6 | 7 | validates :title, presence: true, 8 | length: { minimum: 5 } 9 | validates :text, presence: true, 10 | length: { minimum: 5 } 11 | 12 | end 13 | -------------------------------------------------------------------------------- /app/models/comment.rb: -------------------------------------------------------------------------------- 1 | class Comment < ActiveRecord::Base 2 | belongs_to :article 3 | end 4 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/models/role.rb: -------------------------------------------------------------------------------- 1 | class Role < ActiveRecord::Base 2 | has_and_belongs_to_many :users, :join_table => :users_roles 3 | belongs_to :resource, :polymorphic => true 4 | 5 | validates :resource_type, 6 | :inclusion => { :in => Rolify.resource_types }, 7 | :allow_nil => true 8 | 9 | scopify 10 | end 11 | -------------------------------------------------------------------------------- /app/models/settings.rb: -------------------------------------------------------------------------------- 1 | class Settings < RailsSettings::CachedSettings 2 | end 3 | -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ActiveRecord::Base 2 | mount_uploader :avatar, AvatarUploader 3 | rolify 4 | # Include default devise modules. Others available are: 5 | # :confirmable, :lockable, :timeoutable and :omniauthable 6 | devise :database_authenticatable, :registerable, 7 | :recoverable, :rememberable, :trackable, :validatable, :timeoutable, 8 | :omniauthable, :omniauth_providers => [:github,:qq_connect, :weibo] 9 | 10 | validates_presence_of :avatar 11 | validates_integrity_of :avatar 12 | validates_processing_of :avatar 13 | 14 | def self.from_omniauth(auth) 15 | where(provider: auth.provider, uid: auth.uid).first_or_create do |user| 16 | user.provider = auth.provider 17 | user.uid = auth.uid 18 | email = auth.info.email 19 | user.email = email || user.uid.to_s + "@wilsonblog.com" 20 | 21 | user.password = Devise.friendly_token[0,20] 22 | end 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /app/uploaders/avatar_uploader.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | class AvatarUploader < CarrierWave::Uploader::Base 4 | 5 | # Include RMagick or MiniMagick support: 6 | # include CarrierWave::RMagick 7 | include CarrierWave::MiniMagick 8 | 9 | # Choose what kind of storage to use for this uploader: 10 | storage :file 11 | # storage :fog 12 | 13 | # Override the directory where uploaded files will be stored. 14 | # This is a sensible default for uploaders that are meant to be mounted: 15 | # def store_dir 16 | # "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" 17 | # end 18 | 19 | # Provide a default URL as a default if there hasn't been a file uploaded: 20 | # def default_url 21 | # # For Rails 3.1+ asset pipeline compatibility: 22 | # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) 23 | # 24 | # "/images/fallback/" + [version_name, "matt.jpg"].compact.join('_') 25 | # end 26 | 27 | # Process files as they are uploaded: 28 | #process :scale => [200, 300] 29 | 30 | # 31 | # def scale(width, height) 32 | # # do something 33 | # end 34 | 35 | # Create different versions of your uploaded files: 36 | version :thumb do 37 | process :resize_to_fit => [50, 50] 38 | end 39 | 40 | version :normal do 41 | process :resize_to_fill => [50, 50] 42 | end 43 | 44 | # Add a white list of extensions which are allowed to be uploaded. 45 | # For images you might use something like this: 46 | def extension_white_list 47 | %w(jpg jpeg gif png) 48 | end 49 | 50 | # Override the filename of the uploaded files: 51 | # Avoid using model.id or version_name here, see uploader/store.rb for details. 52 | # def filename 53 | # "something.jpg" if original_filename 54 | # end 55 | 56 | end 57 | -------------------------------------------------------------------------------- /app/views/application/_footer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/views/application/_header.html.erb: -------------------------------------------------------------------------------- 1 | 8 | 9 | -------------------------------------------------------------------------------- /app/views/articles/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= link_to articles_path do %> 2 | 返回文章列表 3 | <%end%> 4 | <%= form_for @article,class:"form-horizontal" do |f| %> 5 | <% if @article.errors.any? %> 6 |
7 |

8 | <%= pluralize(@article.errors.count, "error") %> prohibited 9 | this article from being saved: 10 |

11 | 16 |
17 | <% end %> 18 | 19 |
20 | 21 |
22 | <%= f.text_field :title, size:120 %> 23 |
24 |
25 | 26 |
27 | 28 |
29 | <%= f.text_field :tag_list,:size=>'120' %> 30 |
31 |
32 | 33 |
34 | 35 |
36 | <%= f.text_area :text,rows:"30", cols:"120" %> 37 |
38 |
39 | 40 |
41 |
42 | <%= f.submit "发布", class: "btn btn-success"%> 43 |
44 |
45 | 46 | <% end %> 47 | 48 | 49 | -------------------------------------------------------------------------------- /app/views/articles/edit.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

编辑 3 |

4 | <%= render 'form' %> 5 |
6 | 7 | 8 | -------------------------------------------------------------------------------- /app/views/articles/index.html.erb: -------------------------------------------------------------------------------- 1 | 26 | 27 | <% @articles.each do |article| %> 28 |
29 |
30 | 31 | 34 | 35 | 67 | 68 |
69 | 70 |
71 | 72 | <% end %> 73 | 74 | 75 |
76 | 79 |
80 | -------------------------------------------------------------------------------- /app/views/articles/index.rss.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | wilsonsblog 5 | 蔡稳的博客 6 | http://wilsonsblog.herokuapp.com/ 7 | zh-CN 8 | Copyright 2015, wilson.com 9 | http://blogs.law.harvard.edu/tech/rss 10 | 11 | <% @articles.each do |article| %> 12 | 13 | <%= article.title %> 14 | 15 | ]]> 16 | 17 | <%= article.created_at.rfc822 %> 18 | <%= article_url(article) %> 19 | <%= article_url(article) %> 20 | 21 | <% end %> 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/views/articles/new.html.erb: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /app/views/articles/show.html.erb: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 25 | 26 | 27 | 43 | 44 |
45 | 46 | 47 |

<%= markdown(@article.text.html_safe) %>

48 | 49 |
50 | 54 |
55 | 56 | 57 | 58 | 67 |
68 |
69 | 70 | <%= render(:partial=>'comments/comments') %> -------------------------------------------------------------------------------- /app/views/comments/_comments.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

<%= @article.comments.size %> 条评论

5 |
6 | 7 |
    8 | <% @article.comments.each do |comment| %> 9 | 10 |
  1. 11 | 32 |
  2. 33 | <% end %> 34 | 35 |
36 | 37 |

欢迎留言

38 |
39 | <%= form_for([@article, @article.comments.build], html: { class: "comment-form", id: "commentform" } ) do |f| %> 40 | <%= f.text_area :body, rows:"10", cols:"4",placeholder:"赶快发表你的见解吧!" %> 41 |

42 | <%= f.submit "发表评论", class: "ui green button", id:"submit"%> 43 |

44 | <% end %> 45 |
46 | 47 |
48 |
-------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Wilson's BLog 5 | 6 | 7 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> 8 | <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> 9 | <%= csrf_meta_tags %> 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |
19 | <%= yield %> 20 |
21 |
22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /app/views/layouts/blog.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Wilson's BLog 5 | 6 | 7 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> 8 | <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> 9 | <%= csrf_meta_tags %> 10 | 11 | 12 | <%= render(:partial=>'header') %> 13 | 14 | 15 |
16 |
17 | 18 |
19 |
20 |
21 | 22 | <%= image_tag(current_user.avatar.url(:normal)) if current_user.avatar %>欢迎来到Wilson的个人博客 23 | <%= link_to "发帖", new_article_path, class:"btn btn-success" %> 24 |
25 | 26 | <%= yield %> 27 |
28 | 29 | 107 |
108 | 109 |
110 |
111 | 112 | <%= render(:partial=>'footer') %> 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /app/views/users/confirmations/new.html.erb: -------------------------------------------------------------------------------- 1 |

Resend confirmation instructions

2 | 3 | <%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %> 4 | <%= devise_error_messages! %> 5 | 6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true %> 9 |
10 | 11 |
12 | <%= f.submit "Resend confirmation instructions" %> 13 |
14 | <% end %> 15 | 16 | <%= render "users/shared/links" %> 17 | -------------------------------------------------------------------------------- /app/views/users/mailer/confirmation_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Welcome <%= @email %>!

2 | 3 |

You can confirm your account email through the link below:

4 | 5 |

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

6 | -------------------------------------------------------------------------------- /app/views/users/mailer/reset_password_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.email %>!

2 | 3 |

Someone has requested a link to change your password. You can do this through the link below.

4 | 5 |

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

6 | 7 |

If you didn't request this, please ignore this email.

8 |

Your password won't change until you access the link above and create a new one.

9 | -------------------------------------------------------------------------------- /app/views/users/mailer/unlock_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.email %>!

2 | 3 |

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

4 | 5 |

Click the link below to unlock your account:

6 | 7 |

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

8 | -------------------------------------------------------------------------------- /app/views/users/passwords/edit.html.erb: -------------------------------------------------------------------------------- 1 | 20 | 21 | -------------------------------------------------------------------------------- /app/views/users/passwords/new.html.erb: -------------------------------------------------------------------------------- 1 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /app/views/users/registrations/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Edit <%= resource_name.to_s.humanize %>

2 | 3 | <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> 4 | <%= devise_error_messages! %> 5 | 6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true %> 9 |
10 | 11 | <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> 12 |
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
13 | <% end %> 14 | 15 |
16 | <%= f.label :password %> (leave blank if you don't want to change it)
17 | <%= f.password_field :password, autocomplete: "off" %> 18 |
19 | 20 |
21 | <%= f.label :password_confirmation %>
22 | <%= f.password_field :password_confirmation, autocomplete: "off" %> 23 |
24 | 25 |
26 | <%= f.label :current_password %> (we need your current password to confirm your changes)
27 | <%= f.password_field :current_password, autocomplete: "off" %> 28 |
29 | 30 |
31 | <%= f.submit "Update" %> 32 |
33 | <% end %> 34 | 35 |

Cancel my account

36 | 37 |

Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

38 | 39 | <%= link_to "Back", :back %> 40 | -------------------------------------------------------------------------------- /app/views/users/registrations/new.html.erb: -------------------------------------------------------------------------------- 1 | 35 | -------------------------------------------------------------------------------- /app/views/users/sessions/new.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /app/views/users/shared/_links.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
忘记密码?
3 | 34 |
-------------------------------------------------------------------------------- /app/views/users/unlocks/new.html.erb: -------------------------------------------------------------------------------- 1 |

Resend unlock instructions

2 | 3 | <%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> 4 | <%= devise_error_messages! %> 5 | 6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true %> 9 |
10 | 11 |
12 | <%= f.submit "Resend unlock instructions" %> 13 |
14 | <% end %> 15 | 16 | <%= render "users/shared/links" %> 17 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../../config/application', __FILE__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | 4 | # path to your application root. 5 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 6 | 7 | Dir.chdir APP_ROOT do 8 | # This script is a starting point to setup your application. 9 | # Add necessary setup steps to this file: 10 | 11 | puts "== Installing dependencies ==" 12 | system "gem install bundler --conservative" 13 | system "bundle check || bundle install" 14 | 15 | # puts "\n== Copying sample files ==" 16 | # unless File.exist?("config/database.yml") 17 | # system "cp config/database.yml.sample config/database.yml" 18 | # end 19 | 20 | puts "\n== Preparing database ==" 21 | system "bin/rake db:setup" 22 | 23 | puts "\n== Removing old logs and tempfiles ==" 24 | system "rm -f log/*" 25 | system "rm -rf tmp/cache" 26 | 27 | puts "\n== Restarting application server ==" 28 | system "touch tmp/restart.txt" 29 | end 30 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | require 'rails/all' 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(*Rails.groups) 8 | 9 | module OmniAuthDevise 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 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 16 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 17 | # config.time_zone = 'Central Time (US & Canada)' 18 | 19 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 20 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 21 | # config.i18n.default_locale = :de 22 | 23 | # Do not swallow errors in after_commit/after_rollback callbacks. 24 | config.active_record.raise_in_transactional_callbacks = true 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: 5 10 | timeout: 5000 11 | 12 | development: 13 | <<: *default 14 | database: db/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | database: db/test.sqlite3 22 | 23 | production: 24 | adapter: postgresql 25 | encoding: unicode 26 | database: postgres://inhgkzrprynkig:bQfprOWJiWwlPIZC5zS9OkKpte@ec2-107-20-244-39.compute-1.amazonaws.com:5432/dbkr96crvalmbq 27 | pool: 5 28 | timeout: 5000 -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } 5 | 6 | # In the development environment your application's code is reloaded on 7 | # every request. This slows down response time but is perfect for development 8 | # since you don't have to restart the web server when you make code changes. 9 | config.cache_classes = false 10 | 11 | # Do not eager load code on boot. 12 | config.eager_load = false 13 | 14 | # Show full error reports and disable caching. 15 | config.consider_all_requests_local = true 16 | config.action_controller.perform_caching = false 17 | 18 | # Don't care if the mailer can't send. 19 | config.action_mailer.raise_delivery_errors = false 20 | 21 | # Print deprecation notices to the Rails logger. 22 | config.active_support.deprecation = :log 23 | 24 | # Raise an error on page load if there are pending migrations. 25 | config.active_record.migration_error = :page_load 26 | 27 | # Debug mode disables concatenation and preprocessing of assets. 28 | # This option may cause significant delays in view rendering with a large 29 | # number of complex assets. 30 | config.assets.debug = true 31 | 32 | # Asset digests allow you to set far-future HTTP expiration dates on all assets, 33 | # yet still be able to expire them through the digest params. 34 | config.assets.digest = true 35 | 36 | # Adds additional error checking when serving assets at runtime. 37 | # Checks for improperly declared sprockets dependencies. 38 | # Raises helpful error messages. 39 | config.assets.raise_runtime_errors = true 40 | 41 | # Raises error for missing translations 42 | # config.action_view.raise_on_missing_translations = true 43 | 44 | config.action_mailer.delivery_method = :smtp 45 | config.action_mailer.raise_delivery_errors = true 46 | config.action_mailer.perform_deliveries = true 47 | config.action_mailer.default :charset => "utf-8" 48 | config.action_mailer.smtp_settings = { 49 | address: "smtp.163.com", 50 | port: 25, 51 | domain: "163.com", 52 | authentication: :login, 53 | user_name: "***", 54 | password: "***" 55 | } 56 | 57 | end 58 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # Code is not reloaded between requests. 5 | config.cache_classes = true 6 | 7 | # Eager load code on boot. This eager loads most of Rails and 8 | # your application in memory, allowing both threaded web servers 9 | # and those relying on copy on write to perform better. 10 | # Rake tasks automatically ignore this option for performance. 11 | config.eager_load = true 12 | 13 | # Full error reports are disabled and caching is turned on. 14 | config.consider_all_requests_local = false 15 | config.action_controller.perform_caching = true 16 | 17 | # Enable Rack::Cache to put a simple HTTP cache in front of your application 18 | # Add `rack-cache` to your Gemfile before enabling this. 19 | # For large-scale production use, consider using a caching reverse proxy like 20 | # NGINX, varnish or squid. 21 | # config.action_dispatch.rack_cache = true 22 | 23 | # Disable serving static files from the `/public` folder by default since 24 | # Apache or NGINX already handles this. 25 | config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? 26 | 27 | # Compress JavaScripts and CSS. 28 | config.assets.js_compressor = :uglifier 29 | # config.assets.css_compressor = :sass 30 | 31 | # Do not fallback to assets pipeline if a precompiled asset is missed. 32 | config.assets.compile = false 33 | 34 | # Asset digests allow you to set far-future HTTP expiration dates on all assets, 35 | # yet still be able to expire them through the digest params. 36 | config.assets.digest = true 37 | 38 | # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb 39 | 40 | # Specifies the header that your server uses for sending files. 41 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache 42 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX 43 | 44 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 45 | # config.force_ssl = true 46 | 47 | # Use the lowest log level to ensure availability of diagnostic information 48 | # when problems arise. 49 | config.log_level = :debug 50 | 51 | # Prepend all log lines with the following tags. 52 | # config.log_tags = [ :subdomain, :uuid ] 53 | 54 | # Use a different logger for distributed setups. 55 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) 56 | 57 | # Use a different cache store in production. 58 | # config.cache_store = :mem_cache_store 59 | 60 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 61 | # config.action_controller.asset_host = 'http://assets.example.com' 62 | 63 | # Ignore bad email addresses and do not raise email delivery errors. 64 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 65 | # config.action_mailer.raise_delivery_errors = false 66 | 67 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 68 | # the I18n.default_locale when a translation cannot be found). 69 | config.i18n.fallbacks = true 70 | 71 | # Send deprecation notices to registered listeners. 72 | config.active_support.deprecation = :notify 73 | 74 | # Use default logging formatter so that PID and timestamp are not suppressed. 75 | config.log_formatter = ::Logger::Formatter.new 76 | 77 | # Do not dump schema after migrations. 78 | config.active_record.dump_schema_after_migration = false 79 | 80 | config.action_mailer.delivery_method = :smtp 81 | config.action_mailer.raise_delivery_errors = true 82 | config.action_mailer.perform_deliveries = true 83 | config.action_mailer.default :charset => "utf-8" 84 | config.action_mailer.smtp_settings = { 85 | address: "smtp.163.com", 86 | port: 25, 87 | domain: "163.com", 88 | authentication: :login, 89 | user_name: "***", 90 | password: "***" 91 | } 92 | end 93 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.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 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure static file server for tests with Cache-Control for performance. 16 | config.serve_static_files = true 17 | config.static_cache_control = 'public, max-age=3600' 18 | 19 | # Show full error reports and disable caching. 20 | config.consider_all_requests_local = true 21 | config.action_controller.perform_caching = false 22 | 23 | # Raise exceptions instead of rendering exception templates. 24 | config.action_dispatch.show_exceptions = false 25 | 26 | # Disable request forgery protection in test environment. 27 | config.action_controller.allow_forgery_protection = false 28 | 29 | # Tell Action Mailer not to deliver emails to the real world. 30 | # The :test delivery method accumulates sent emails in the 31 | # ActionMailer::Base.deliveries array. 32 | config.action_mailer.delivery_method = :test 33 | 34 | # Randomize the order test cases are executed. 35 | config.active_support.test_order = :random 36 | 37 | # Print deprecation notices to the stderr. 38 | config.active_support.deprecation = :stderr 39 | 40 | # Raises error for missing translations 41 | # config.action_view.raise_on_missing_translations = true 42 | end 43 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 11 | # Rails.application.config.assets.precompile += %w( search.js ) 12 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.action_dispatch.cookies_serializer = :json 4 | -------------------------------------------------------------------------------- /config/initializers/default_settings.rb: -------------------------------------------------------------------------------- 1 | Settings.defaults[:page_size] = '5' 2 | Settings.defaults[:hot_comments_size] = '5' 3 | Settings.defaults[:hot_articles_size] = '5' -------------------------------------------------------------------------------- /config/initializers/devise.rb: -------------------------------------------------------------------------------- 1 | # Use this hook to configure devise mailer, warden hooks and so forth. 2 | # Many of these configuration options can be set straight in your model. 3 | Devise.setup do |config| 4 | # The secret key used by Devise. Devise uses this key to generate 5 | # random tokens. Changing this key will render invalid all existing 6 | # confirmation, reset password and unlock tokens in the database. 7 | # config.secret_key = '48dabe309d4f9d736ef024ca671919786b74f16af2e781065ebec71d88d4f3908f74ff7feb8ba5c6805093f0d449d3cfdefe171bad412f2f17ee808f6daae3c0' 8 | 9 | # ==> Mailer Configuration 10 | # Configure the e-mail address which will be shown in Devise::Mailer, 11 | # note that it will be overwritten if you use your own mailer class 12 | # with default "from" parameter. 13 | config.mailer_sender = 'caiwenhn2008@163.com' 14 | 15 | # Configure the class responsible to send e-mails. 16 | # config.mailer = 'Devise::Mailer' 17 | 18 | # ==> ORM configuration 19 | # Load and configure the ORM. Supports :active_record (default) and 20 | # :mongoid (bson_ext recommended) by default. Other ORMs may be 21 | # available as additional gems. 22 | require 'devise/orm/active_record' 23 | 24 | # ==> Configuration for any authentication mechanism 25 | # Configure which keys are used when authenticating a user. The default is 26 | # just :email. You can configure it to use [:username, :subdomain], so for 27 | # authenticating a user, both parameters are required. Remember that those 28 | # parameters are used only when authenticating and not when retrieving from 29 | # session. If you need permissions, you should implement that in a before filter. 30 | # You can also supply a hash where the value is a boolean determining whether 31 | # or not authentication should be aborted when the value is not present. 32 | # config.authentication_keys = [ :email ] 33 | 34 | # Configure parameters from the request object used for authentication. Each entry 35 | # given should be a request method and it will automatically be passed to the 36 | # find_for_authentication method and considered in your model lookup. For instance, 37 | # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. 38 | # The same considerations mentioned for authentication_keys also apply to request_keys. 39 | # config.request_keys = [] 40 | 41 | # Configure which authentication keys should be case-insensitive. 42 | # These keys will be downcased upon creating or modifying a user and when used 43 | # to authenticate or find a user. Default is :email. 44 | config.case_insensitive_keys = [ :email ] 45 | 46 | # Configure which authentication keys should have whitespace stripped. 47 | # These keys will have whitespace before and after removed upon creating or 48 | # modifying a user and when used to authenticate or find a user. Default is :email. 49 | config.strip_whitespace_keys = [ :email ] 50 | 51 | # Tell if authentication through request.params is enabled. True by default. 52 | # It can be set to an array that will enable params authentication only for the 53 | # given strategies, for example, `config.params_authenticatable = [:database]` will 54 | # enable it only for database (email + password) authentication. 55 | # config.params_authenticatable = true 56 | 57 | # Tell if authentication through HTTP Auth is enabled. False by default. 58 | # It can be set to an array that will enable http authentication only for the 59 | # given strategies, for example, `config.http_authenticatable = [:database]` will 60 | # enable it only for database authentication. The supported strategies are: 61 | # :database = Support basic authentication with authentication key + password 62 | # config.http_authenticatable = false 63 | 64 | # If 401 status code should be returned for AJAX requests. True by default. 65 | # config.http_authenticatable_on_xhr = true 66 | 67 | # The realm used in Http Basic Authentication. 'Application' by default. 68 | # config.http_authentication_realm = 'Application' 69 | 70 | # It will change confirmation, password recovery and other workflows 71 | # to behave the same regardless if the e-mail provided was right or wrong. 72 | # Does not affect registerable. 73 | # config.paranoid = true 74 | 75 | # By default Devise will store the user in session. You can skip storage for 76 | # particular strategies by setting this option. 77 | # Notice that if you are skipping storage for all authentication paths, you 78 | # may want to disable generating routes to Devise's sessions controller by 79 | # passing skip: :sessions to `devise_for` in your config/routes.rb 80 | config.skip_session_storage = [:http_auth] 81 | 82 | # By default, Devise cleans up the CSRF token on authentication to 83 | # avoid CSRF token fixation attacks. This means that, when using AJAX 84 | # requests for sign in and sign up, you need to get a new CSRF token 85 | # from the server. You can disable this option at your own risk. 86 | # config.clean_up_csrf_token_on_authentication = true 87 | 88 | # ==> Configuration for :database_authenticatable 89 | # For bcrypt, this is the cost for hashing the password and defaults to 10. If 90 | # using other encryptors, it sets how many times you want the password re-encrypted. 91 | # 92 | # Limiting the stretches to just one in testing will increase the performance of 93 | # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use 94 | # a value less than 10 in other environments. Note that, for bcrypt (the default 95 | # encryptor), the cost increases exponentially with the number of stretches (e.g. 96 | # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). 97 | config.stretches = Rails.env.test? ? 1 : 10 98 | 99 | # Setup a pepper to generate the encrypted password. 100 | # config.pepper = 'c8001c788cbc503f9d11453875ff1470f6fe3d817f0e536e9bdb0b76edf2589d67b8524fc9efc64dfd0a535fab8a096c400d35a8d71be7e6eff702221e6fe61a' 101 | 102 | # ==> Configuration for :confirmable 103 | # A period that the user is allowed to access the website even without 104 | # confirming their account. For instance, if set to 2.days, the user will be 105 | # able to access the website for two days without confirming their account, 106 | # access will be blocked just in the third day. Default is 0.days, meaning 107 | # the user cannot access the website without confirming their account. 108 | # config.allow_unconfirmed_access_for = 2.days 109 | 110 | # A period that the user is allowed to confirm their account before their 111 | # token becomes invalid. For example, if set to 3.days, the user can confirm 112 | # their account within 3 days after the mail was sent, but on the fourth day 113 | # their account can't be confirmed with the token any more. 114 | # Default is nil, meaning there is no restriction on how long a user can take 115 | # before confirming their account. 116 | # config.confirm_within = 3.days 117 | 118 | # If true, requires any email changes to be confirmed (exactly the same way as 119 | # initial account confirmation) to be applied. Requires additional unconfirmed_email 120 | # db field (see migrations). Until confirmed, new email is stored in 121 | # unconfirmed_email column, and copied to email column on successful confirmation. 122 | config.reconfirmable = true 123 | 124 | # Defines which key will be used when confirming an account 125 | # config.confirmation_keys = [ :email ] 126 | 127 | # ==> Configuration for :rememberable 128 | # The time the user will be remembered without asking for credentials again. 129 | # config.remember_for = 2.weeks 130 | 131 | # Invalidates all the remember me tokens when the user signs out. 132 | config.expire_all_remember_me_on_sign_out = true 133 | 134 | # If true, extends the user's remember period when remembered via cookie. 135 | # config.extend_remember_period = false 136 | 137 | # Options to be passed to the created cookie. For instance, you can set 138 | # secure: true in order to force SSL only cookies. 139 | # config.rememberable_options = {} 140 | 141 | # ==> Configuration for :validatable 142 | # Range for password length. 143 | config.password_length = 8..128 144 | 145 | # Email regex used to validate email formats. It simply asserts that 146 | # one (and only one) @ exists in the given string. This is mainly 147 | # to give user feedback and not to assert the e-mail validity. 148 | # config.email_regexp = /\A[^@]+@[^@]+\z/ 149 | 150 | # ==> Configuration for :timeoutable 151 | # The time you want to timeout the user session without activity. After this 152 | # time the user will be asked for credentials again. Default is 30 minutes. 153 | # config.timeout_in = 30.minutes 154 | 155 | # If true, expires auth token on session timeout. 156 | # config.expire_auth_token_on_timeout = false 157 | 158 | # ==> Configuration for :lockable 159 | # Defines which strategy will be used to lock an account. 160 | # :failed_attempts = Locks an account after a number of failed attempts to sign in. 161 | # :none = No lock strategy. You should handle locking by yourself. 162 | # config.lock_strategy = :failed_attempts 163 | 164 | # Defines which key will be used when locking and unlocking an account 165 | # config.unlock_keys = [ :email ] 166 | 167 | # Defines which strategy will be used to unlock an account. 168 | # :email = Sends an unlock link to the user email 169 | # :time = Re-enables login after a certain amount of time (see :unlock_in below) 170 | # :both = Enables both strategies 171 | # :none = No unlock strategy. You should handle unlocking by yourself. 172 | # config.unlock_strategy = :both 173 | 174 | # Number of authentication tries before locking an account if lock_strategy 175 | # is failed attempts. 176 | # config.maximum_attempts = 20 177 | 178 | # Time interval to unlock the account if :time is enabled as unlock_strategy. 179 | # config.unlock_in = 1.hour 180 | 181 | # Warn on the last attempt before the account is locked. 182 | # config.last_attempt_warning = true 183 | 184 | # ==> Configuration for :recoverable 185 | # 186 | # Defines which key will be used when recovering the password for an account 187 | # config.reset_password_keys = [ :email ] 188 | 189 | # Time interval you can reset your password with a reset password key. 190 | # Don't put a too small interval or your users won't have the time to 191 | # change their passwords. 192 | config.reset_password_within = 6.hours 193 | 194 | # ==> Configuration for :encryptable 195 | # Allow you to use another encryption algorithm besides bcrypt (default). You can use 196 | # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1, 197 | # :authlogic_sha512 (then you should set stretches above to 20 for default behavior) 198 | # and :restful_authentication_sha1 (then you should set stretches to 10, and copy 199 | # REST_AUTH_SITE_KEY to pepper). 200 | # 201 | # Require the `devise-encryptable` gem when using anything other than bcrypt 202 | # config.encryptor = :sha512 203 | 204 | # ==> Scopes configuration 205 | # Turn scoped views on. Before rendering "sessions/new", it will first check for 206 | # "users/sessions/new". It's turned off by default because it's slower if you 207 | # are using only default views. 208 | config.scoped_views = true 209 | 210 | # Configure the default scope given to Warden. By default it's the first 211 | # devise role declared in your routes (usually :user). 212 | # config.default_scope = :user 213 | 214 | # Set this configuration to false if you want /users/sign_out to sign out 215 | # only the current scope. By default, Devise signs out all scopes. 216 | # config.sign_out_all_scopes = true 217 | 218 | # ==> Navigation configuration 219 | # Lists the formats that should be treated as navigational. Formats like 220 | # :html, should redirect to the sign in page when the user does not have 221 | # access, but formats like :xml or :json, should return 401. 222 | # 223 | # If you have any extra navigational formats, like :iphone or :mobile, you 224 | # should add them to the navigational formats lists. 225 | # 226 | # The "*/*" below is required to match Internet Explorer requests. 227 | # config.navigational_formats = ['*/*', :html] 228 | 229 | # The default HTTP method used to sign out a resource. Default is :delete. 230 | config.sign_out_via = :delete 231 | 232 | # ==> OmniAuth 233 | # Add a new OmniAuth provider. Check the wiki for more information on setting 234 | # up on your models and hooks. 235 | #config.omniauth :github, '4cbcf714c51af5909f23', '760e664aa1cb3050f459d261987e6985aaf48f55', scope: 'user,public_repo' 236 | config.omniauth :github, '35afc7183620bc9675d9', '34839b4a56705fb17ec7905205e71296857c494e', scope: 'user,public_repo' 237 | config.omniauth :qq_connect, '101200256', '36967d36cf508d3b1fcc24bf9f9aec6d', scope: 'user,public_repo' 238 | config.omniauth :weibo, '1053744505', '63262590e669fd65e7b309d0e94d53b3', scope: 'user,public_repo' 239 | 240 | 241 | # ==> Warden configuration 242 | # If you want to use other strategies, that are not supported by Devise, or 243 | # change the failure app, you can configure them inside the config.warden block. 244 | # 245 | # config.warden do |manager| 246 | # manager.intercept_401 = false 247 | # manager.default_strategies(scope: :user).unshift :some_external_strategy 248 | # end 249 | 250 | # ==> Mountable engine configurations 251 | # When using Devise inside an engine, let's call it `MyEngine`, and this engine 252 | # is mountable, there are some extra configurations to be taken into account. 253 | # The following options are available, assuming the engine is mounted as: 254 | # 255 | # mount MyEngine, at: '/my_engine' 256 | # 257 | # The router that invoked `devise_for`, in the example above, would be: 258 | # config.router_name = :my_engine 259 | # 260 | # When using omniauth, Devise cannot automatically set Omniauth path, 261 | # so you need to do it manually. For the users scope, it would be: 262 | # config.omniauth_path_prefix = '/my_engine/users/auth' 263 | end 264 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /config/initializers/rails_admin.rb: -------------------------------------------------------------------------------- 1 | RailsAdmin.config do |config| 2 | 3 | ### Popular gems integration 4 | 5 | ## == Devise == 6 | config.authenticate_with do 7 | warden.authenticate! scope: :user 8 | end 9 | config.current_user_method(&:current_user) 10 | 11 | ## == Cancan == 12 | config.authorize_with :cancan 13 | 14 | ## == PaperTrail == 15 | # config.audit_with :paper_trail, 'User', 'PaperTrail::Version' # PaperTrail >= 3.0.0 16 | 17 | ### More at https://github.com/sferik/rails_admin/wiki/Base-configuration 18 | 19 | config.actions do 20 | dashboard # mandatory 21 | index # mandatory 22 | new 23 | export 24 | bulk_delete 25 | show 26 | edit 27 | delete 28 | show_in_app 29 | 30 | ## With an audit adapter, you can add: 31 | # history_index 32 | # history_show 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /config/initializers/rails_settings_ui.rb: -------------------------------------------------------------------------------- 1 | require 'rails-settings-ui' 2 | 3 | #= Application-specific 4 | # 5 | # # You can specify a controller for RailsSettingsUi::ApplicationController to inherit from: 6 | # RailsSettingsUi.parent_controller = 'Admin::ApplicationController' # default: '::ApplicationController' 7 | # 8 | # # Render RailsSettingsUi inside a custom layout (set to 'application' to use app layout, default is RailsSettingsUi's own layout) 9 | # RailsSettingsUi::ApplicationController.layout 'admin' 10 | 11 | Rails.application.config.to_prepare do 12 | # If you use a *custom layout*, make route helpers available to RailsSettingsUi: 13 | # RailsSettingsUi.inline_main_app_routes! 14 | end 15 | -------------------------------------------------------------------------------- /config/initializers/rolify.rb: -------------------------------------------------------------------------------- 1 | Rolify.configure do |config| 2 | # By default ORM adapter is ActiveRecord. uncomment to use mongoid 3 | # config.use_mongoid 4 | 5 | # Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false 6 | # config.use_dynamic_shortcuts 7 | end -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_OmniAuthDevise_session' 4 | -------------------------------------------------------------------------------- /config/initializers/simple_form.rb: -------------------------------------------------------------------------------- 1 | # Use this setup block to configure all options available in SimpleForm. 2 | SimpleForm.setup do |config| 3 | # Wrappers are used by the form builder to generate a 4 | # complete input. You can remove any component from the 5 | # wrapper, change the order or even add your own to the 6 | # stack. The options given below are used to wrap the 7 | # whole input. 8 | config.wrappers :default, class: :input, 9 | hint_class: :field_with_hint, error_class: :field_with_errors do |b| 10 | ## Extensions enabled by default 11 | # Any of these extensions can be disabled for a 12 | # given input by passing: `f.input EXTENSION_NAME => false`. 13 | # You can make any of these extensions optional by 14 | # renaming `b.use` to `b.optional`. 15 | 16 | # Determines whether to use HTML5 (:email, :url, ...) 17 | # and required attributes 18 | b.use :html5 19 | 20 | # Calculates placeholders automatically from I18n 21 | # You can also pass a string as f.input placeholder: "Placeholder" 22 | b.use :placeholder 23 | 24 | ## Optional extensions 25 | # They are disabled unless you pass `f.input EXTENSION_NAME => true` 26 | # to the input. If so, they will retrieve the values from the model 27 | # if any exists. If you want to enable any of those 28 | # extensions by default, you can change `b.optional` to `b.use`. 29 | 30 | # Calculates maxlength from length validations for string inputs 31 | b.optional :maxlength 32 | 33 | # Calculates pattern from format validations for string inputs 34 | b.optional :pattern 35 | 36 | # Calculates min and max from length validations for numeric inputs 37 | b.optional :min_max 38 | 39 | # Calculates readonly automatically from readonly attributes 40 | b.optional :readonly 41 | 42 | ## Inputs 43 | b.use :label_input 44 | b.use :hint, wrap_with: { tag: :span, class: :hint } 45 | b.use :error, wrap_with: { tag: :span, class: :error } 46 | 47 | ## full_messages_for 48 | # If you want to display the full error message for the attribute, you can 49 | # use the component :full_error, like: 50 | # 51 | # b.use :full_error, wrap_with: { tag: :span, class: :error } 52 | end 53 | 54 | # The default wrapper to be used by the FormBuilder. 55 | config.default_wrapper = :default 56 | 57 | # Define the way to render check boxes / radio buttons with labels. 58 | # Defaults to :nested for bootstrap config. 59 | # inline: input + label 60 | # nested: label > input 61 | config.boolean_style = :nested 62 | 63 | # Default class for buttons 64 | config.button_class = 'btn' 65 | 66 | # Method used to tidy up errors. Specify any Rails Array method. 67 | # :first lists the first message for each field. 68 | # Use :to_sentence to list all errors for each field. 69 | # config.error_method = :first 70 | 71 | # Default tag used for error notification helper. 72 | config.error_notification_tag = :div 73 | 74 | # CSS class to add for error notification helper. 75 | config.error_notification_class = 'error_notification' 76 | 77 | # ID to add for error notification helper. 78 | # config.error_notification_id = nil 79 | 80 | # Series of attempts to detect a default label method for collection. 81 | # config.collection_label_methods = [ :to_label, :name, :title, :to_s ] 82 | 83 | # Series of attempts to detect a default value method for collection. 84 | # config.collection_value_methods = [ :id, :to_s ] 85 | 86 | # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none. 87 | # config.collection_wrapper_tag = nil 88 | 89 | # You can define the class to use on all collection wrappers. Defaulting to none. 90 | # config.collection_wrapper_class = nil 91 | 92 | # You can wrap each item in a collection of radio/check boxes with a tag, 93 | # defaulting to :span. Please note that when using :boolean_style = :nested, 94 | # SimpleForm will force this option to be a label. 95 | # config.item_wrapper_tag = :span 96 | 97 | # You can define a class to use in all item wrappers. Defaulting to none. 98 | # config.item_wrapper_class = nil 99 | 100 | # How the label text should be generated altogether with the required text. 101 | # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" } 102 | 103 | # You can define the class to use on all labels. Default is nil. 104 | # config.label_class = nil 105 | 106 | # You can define the default class to be used on forms. Can be overriden 107 | # with `html: { :class }`. Defaulting to none. 108 | # config.default_form_class = nil 109 | 110 | # You can define which elements should obtain additional classes 111 | # config.generate_additional_classes_for = [:wrapper, :label, :input] 112 | 113 | # Whether attributes are required by default (or not). Default is true. 114 | # config.required_by_default = true 115 | 116 | # Tell browsers whether to use the native HTML5 validations (novalidate form option). 117 | # These validations are enabled in SimpleForm's internal config but disabled by default 118 | # in this configuration, which is recommended due to some quirks from different browsers. 119 | # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations, 120 | # change this configuration to true. 121 | config.browser_validations = false 122 | 123 | # Collection of methods to detect if a file type was given. 124 | # config.file_methods = [ :mounted_as, :file?, :public_filename ] 125 | 126 | # Custom mappings for input types. This should be a hash containing a regexp 127 | # to match as key, and the input type that will be used when the field name 128 | # matches the regexp as value. 129 | # config.input_mappings = { /count/ => :integer } 130 | 131 | # Custom wrappers for input types. This should be a hash containing an input 132 | # type as key and the wrapper that will be used for all inputs with specified type. 133 | # config.wrapper_mappings = { string: :prepend } 134 | 135 | # Namespaces where SimpleForm should look for custom input classes that 136 | # override default inputs. 137 | # config.custom_inputs_namespaces << "CustomInputs" 138 | 139 | # Default priority for time_zone inputs. 140 | # config.time_zone_priority = nil 141 | 142 | # Default priority for country inputs. 143 | # config.country_priority = nil 144 | 145 | # When false, do not use translations for labels. 146 | # config.translate_labels = true 147 | 148 | # Automatically discover new inputs in Rails' autoload path. 149 | # config.inputs_discovery = true 150 | 151 | # Cache SimpleForm inputs discovery 152 | # config.cache_discovery = !Rails.env.development? 153 | 154 | # Default class for inputs 155 | # config.input_class = nil 156 | 157 | # Define the default class of the input wrapper of the boolean input. 158 | config.boolean_label_class = 'checkbox' 159 | 160 | # Defines if the default input wrapper class should be included in radio 161 | # collection wrappers. 162 | # config.include_default_input_wrapper_class = true 163 | 164 | # Defines which i18n scope will be used in Simple Form. 165 | # config.i18n_scope = 'simple_form' 166 | end 167 | -------------------------------------------------------------------------------- /config/initializers/simple_form_bootstrap.rb: -------------------------------------------------------------------------------- 1 | # Use this setup block to configure all options available in SimpleForm. 2 | SimpleForm.setup do |config| 3 | config.error_notification_class = 'alert alert-danger' 4 | config.button_class = 'btn btn-default' 5 | config.boolean_label_class = nil 6 | 7 | config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| 8 | b.use :html5 9 | b.use :placeholder 10 | b.optional :maxlength 11 | b.optional :pattern 12 | b.optional :min_max 13 | b.optional :readonly 14 | b.use :label, class: 'control-label' 15 | 16 | b.use :input, class: 'form-control' 17 | b.use :error, wrap_with: { tag: 'span', class: 'help-block' } 18 | b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } 19 | end 20 | 21 | config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| 22 | b.use :html5 23 | b.use :placeholder 24 | b.optional :maxlength 25 | b.optional :readonly 26 | b.use :label, class: 'control-label' 27 | 28 | b.use :input 29 | b.use :error, wrap_with: { tag: 'span', class: 'help-block' } 30 | b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } 31 | end 32 | 33 | config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| 34 | b.use :html5 35 | b.optional :readonly 36 | 37 | b.wrapper tag: 'div', class: 'checkbox' do |ba| 38 | ba.use :label_input 39 | end 40 | 41 | b.use :error, wrap_with: { tag: 'span', class: 'help-block' } 42 | b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } 43 | end 44 | 45 | config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| 46 | b.use :html5 47 | b.optional :readonly 48 | b.use :label, class: 'control-label' 49 | b.use :input 50 | b.use :error, wrap_with: { tag: 'span', class: 'help-block' } 51 | b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } 52 | end 53 | 54 | config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| 55 | b.use :html5 56 | b.use :placeholder 57 | b.optional :maxlength 58 | b.optional :pattern 59 | b.optional :min_max 60 | b.optional :readonly 61 | b.use :label, class: 'col-sm-3 control-label' 62 | 63 | b.wrapper tag: 'div', class: 'col-sm-9' do |ba| 64 | ba.use :input, class: 'form-control' 65 | ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } 66 | ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } 67 | end 68 | end 69 | 70 | config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| 71 | b.use :html5 72 | b.use :placeholder 73 | b.optional :maxlength 74 | b.optional :readonly 75 | b.use :label, class: 'col-sm-3 control-label' 76 | 77 | b.wrapper tag: 'div', class: 'col-sm-9' do |ba| 78 | ba.use :input 79 | ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } 80 | ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } 81 | end 82 | end 83 | 84 | config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| 85 | b.use :html5 86 | b.optional :readonly 87 | 88 | b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr| 89 | wr.wrapper tag: 'div', class: 'checkbox' do |ba| 90 | ba.use :label_input, class: 'col-sm-9' 91 | end 92 | 93 | wr.use :error, wrap_with: { tag: 'span', class: 'help-block' } 94 | wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' } 95 | end 96 | end 97 | 98 | config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| 99 | b.use :html5 100 | b.optional :readonly 101 | 102 | b.use :label, class: 'col-sm-3 control-label' 103 | 104 | b.wrapper tag: 'div', class: 'col-sm-9' do |ba| 105 | ba.use :input 106 | ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } 107 | ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } 108 | end 109 | end 110 | 111 | config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| 112 | b.use :html5 113 | b.use :placeholder 114 | b.optional :maxlength 115 | b.optional :pattern 116 | b.optional :min_max 117 | b.optional :readonly 118 | b.use :label, class: 'sr-only' 119 | 120 | b.use :input, class: 'form-control' 121 | b.use :error, wrap_with: { tag: 'span', class: 'help-block' } 122 | b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } 123 | end 124 | 125 | # Wrappers for forms and inputs using the Bootstrap toolkit. 126 | # Check the Bootstrap docs (http://getbootstrap.com) 127 | # to learn about the different styles for forms and inputs, 128 | # buttons and other elements. 129 | config.default_wrapper = :vertical_form 130 | config.wrapper_mappings = { 131 | check_boxes: :vertical_radio_and_checkboxes, 132 | radio_buttons: :vertical_radio_and_checkboxes, 133 | file: :vertical_file_input, 134 | boolean: :vertical_boolean, 135 | } 136 | end 137 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /config/locales/devise.en.yml: -------------------------------------------------------------------------------- 1 | # Additional translations at https://github.com/plataformatec/devise/wiki/I18n 2 | 3 | en: 4 | devise: 5 | confirmations: 6 | confirmed: "Your email address has been successfully confirmed." 7 | send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes." 8 | send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes." 9 | failure: 10 | already_authenticated: "You are already signed in." 11 | inactive: "Your account is not activated yet." 12 | invalid: "Invalid %{authentication_keys} or password." 13 | locked: "Your account is locked." 14 | last_attempt: "You have one more attempt before your account is locked." 15 | not_found_in_database: "Invalid %{authentication_keys} or password." 16 | timeout: "Your session expired. Please sign in again to continue." 17 | unauthenticated: "You need to sign in or sign up before continuing." 18 | unconfirmed: "You have to confirm your email address before continuing." 19 | mailer: 20 | confirmation_instructions: 21 | subject: "Confirmation instructions" 22 | reset_password_instructions: 23 | subject: "Reset password instructions" 24 | unlock_instructions: 25 | subject: "Unlock instructions" 26 | omniauth_callbacks: 27 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"." 28 | success: "Successfully authenticated from %{kind} account." 29 | passwords: 30 | no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided." 31 | send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." 32 | send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." 33 | updated: "Your password has been changed successfully. You are now signed in." 34 | updated_not_active: "Your password has been changed successfully." 35 | registrations: 36 | destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon." 37 | signed_up: "Welcome! You have signed up successfully." 38 | signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated." 39 | signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked." 40 | signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." 41 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address." 42 | updated: "Your account has been updated successfully." 43 | sessions: 44 | signed_in: "Signed in successfully." 45 | signed_out: "Signed out successfully." 46 | already_signed_out: "Signed out successfully." 47 | unlocks: 48 | send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes." 49 | send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes." 50 | unlocked: "Your account has been unlocked successfully. Please sign in to continue." 51 | errors: 52 | messages: 53 | already_confirmed: "was already confirmed, please try signing in" 54 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" 55 | expired: "has expired, please request a new one" 56 | not_found: "not found" 57 | not_locked: "was not locked" 58 | not_saved: 59 | one: "1 error prohibited this %{resource} from being saved:" 60 | other: "%{count} errors prohibited this %{resource} from being saved:" 61 | -------------------------------------------------------------------------------- /config/locales/en.bootstrap.yml: -------------------------------------------------------------------------------- 1 | # Sample localization file for English. Add more files in this directory for other locales. 2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. 3 | 4 | en: 5 | breadcrumbs: 6 | application: 7 | root: "Index" 8 | pages: 9 | pages: "Pages" 10 | helpers: 11 | actions: "Actions" 12 | links: 13 | back: "Back" 14 | cancel: "Cancel" 15 | confirm: "Are you sure?" 16 | destroy: "Delete" 17 | new: "New" 18 | edit: "Edit" 19 | titles: 20 | edit: "Edit %{model}" 21 | save: "Save %{model}" 22 | new: "New %{model}" 23 | delete: "Delete %{model}" 24 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more, please read the Rails Internationalization guide 20 | # available at http://guides.rubyonrails.org/i18n.html. 21 | 22 | en: 23 | hello: "Hello world" 24 | settings: 25 | attributes: 26 | page_size: # setting name 27 | name: '分页【每页文章数】' 28 | hot_comments_size: 29 | name: '热门评论数量' 30 | hot_articles_size: 31 | name: '热门文章数量' -------------------------------------------------------------------------------- /config/locales/pagination.yml: -------------------------------------------------------------------------------- 1 | en: 2 | views: 3 | pagination: 4 | first: "首页" 5 | last: "末页" 6 | previous: "‹ 前一页" 7 | next: "后一页 ›" 8 | truncate: "…" 9 | helpers: 10 | page_entries_info: 11 | one_page: 12 | display_entries: 13 | zero: "No %{entry_name} found" 14 | one: "Displaying 1 %{entry_name}" 15 | other: "Displaying all %{count} %{entry_name}" 16 | more_pages: 17 | display_entries: "Displaying %{entry_name} %{first} - %{last} of %{total} in total" -------------------------------------------------------------------------------- /config/locales/simple_form.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | simple_form: 3 | "yes": 'Yes' 4 | "no": 'No' 5 | required: 6 | text: 'required' 7 | mark: '*' 8 | # You can uncomment the line below if you need to overwrite the whole required html. 9 | # When using html, text and mark won't be used. 10 | # html: '*' 11 | error_notification: 12 | default_message: "问题来啦,请重新输入!" 13 | labels: 14 | defaults: 15 | password: '密码' 16 | password_confirmation: '确认密码' 17 | 18 | user: 19 | new: 20 | email: '邮件地址' 21 | avatar: '头像' 22 | edit: 23 | email: 'E-mail.' 24 | hints: 25 | defaults: 26 | username: 'User name to sign in.' 27 | password: '*请不要输入特殊字符' 28 | include_blanks: 29 | defaults: 30 | age: 'Rather not say' 31 | prompts: 32 | defaults: 33 | age: 'Select your age' 34 | -------------------------------------------------------------------------------- /config/puma.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env puma 2 | 3 | environment 'development' 4 | threads 2, 32 # minimum 2 threads, maximum 64 threads 5 | workers 2 6 | 7 | app_name = 'rails4blog' 8 | 9 | application_path = "#{ENV["rails_app_home"]}/#{app_name}" 10 | 11 | directory "#{application_path}" 12 | 13 | pidfile "#{application_path}/shared/tmp/pids/puma.pid" 14 | state_path "#{application_path}/shared/tmp/sockets/puma.state" 15 | stdout_redirect "#{application_path}/shared/log/puma.stdout.log", "#{application_path}/shared/log/puma.stderr.log" 16 | 17 | 18 | # bind "unix://#{application_path}/shared/tmp/sockets/puma.sock" #绑定sock 19 | bind 'tcp://127.0.0.1:3000' #绑定端口801 20 | worker_timeout 60 21 | 22 | #daemonize true 23 | 24 | preload_app! -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | mount RailsSettingsUi::Engine, at: 'settings' 3 | mount RailsAdmin::Engine => '/admin', as: 'rails_admin' 4 | devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" } 5 | 6 | resources :articles 7 | resources :articles do 8 | resources :comments 9 | end 10 | 11 | root 'articles#index' 12 | 13 | 14 | # The priority is based upon order of creation: first created -> highest priority. 15 | # See how all your routes lay out with "rake routes". 16 | 17 | # You can have the root of your site routed with "root" 18 | # root 'welcome#index' 19 | 20 | # Example of regular route: 21 | # get 'products/:id' => 'catalog#view' 22 | 23 | # Example of named route that can be invoked with purchase_url(id: product.id) 24 | # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase 25 | 26 | # Example resource route (maps HTTP verbs to controller actions automatically): 27 | # resources :products 28 | 29 | # Example resource route with options: 30 | # resources :products do 31 | # member do 32 | # get 'short' 33 | # post 'toggle' 34 | # end 35 | # 36 | # collection do 37 | # get 'sold' 38 | # end 39 | # end 40 | 41 | # Example resource route with sub-resources: 42 | # resources :products do 43 | # resources :comments, :sales 44 | # resource :seller 45 | # end 46 | 47 | # Example resource route with more complex sub-resources: 48 | # resources :products do 49 | # resources :comments 50 | # resources :sales do 51 | # get 'recent', on: :collection 52 | # end 53 | # end 54 | 55 | # Example resource route with concerns: 56 | # concern :toggleable do 57 | # post 'toggle' 58 | # end 59 | # resources :posts, concerns: :toggleable 60 | # resources :photos, concerns: :toggleable 61 | 62 | # Example resource route within a namespace: 63 | # namespace :admin do 64 | # # Directs /admin/products/* to Admin::ProductsController 65 | # # (app/controllers/admin/products_controller.rb) 66 | # resources :products 67 | # end 68 | end 69 | -------------------------------------------------------------------------------- /config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rake secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: 4c0e6da17cdae2cac243ac22a982eae491cc34f22fea7b0e67288b467008257960e92c53a91b40a3439280d154b7cb5169cae79a76c0c7e0782dbe5397a704d6 15 | 16 | test: 17 | secret_key_base: 76227fbc24de7df49093a580fd2802ad4998daec1fac059bca725fbf7242686b693e36b16723f8da775fc6a704fd2582a370c852d849252c228da52b5ec93f29 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 23 | -------------------------------------------------------------------------------- /db/migrate/20150303150726_devise_create_users.rb: -------------------------------------------------------------------------------- 1 | class DeviseCreateUsers < ActiveRecord::Migration 2 | def change 3 | create_table(:users) do |t| 4 | ## Database authenticatable 5 | t.string :email, null: false, default: "" 6 | t.string :encrypted_password, null: false, default: "" 7 | 8 | ## Recoverable 9 | t.string :reset_password_token 10 | t.datetime :reset_password_sent_at 11 | 12 | ## Rememberable 13 | t.datetime :remember_created_at 14 | 15 | ## Trackable 16 | t.integer :sign_in_count, default: 0, null: false 17 | t.datetime :current_sign_in_at 18 | t.datetime :last_sign_in_at 19 | t.string :current_sign_in_ip 20 | t.string :last_sign_in_ip 21 | 22 | ## Confirmable 23 | # t.string :confirmation_token 24 | # t.datetime :confirmed_at 25 | # t.datetime :confirmation_sent_at 26 | # t.string :unconfirmed_email # Only if using reconfirmable 27 | 28 | ## Lockable 29 | # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts 30 | # t.string :unlock_token # Only if unlock strategy is :email or :both 31 | # t.datetime :locked_at 32 | 33 | 34 | t.timestamps 35 | end 36 | 37 | add_index :users, :email, unique: true 38 | add_index :users, :reset_password_token, unique: true 39 | # add_index :users, :confirmation_token, unique: true 40 | # add_index :users, :unlock_token, unique: true 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /db/migrate/20150303150952_add_columns_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddColumnsToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :provider, :string 4 | add_column :users, :uid, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20150307065926_create_articles.rb: -------------------------------------------------------------------------------- 1 | class CreateArticles < ActiveRecord::Migration 2 | def change 3 | create_table :articles do |t| 4 | t.string :title 5 | t.text :text 6 | 7 | t.timestamps null: false 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20150307074427_create_comments.rb: -------------------------------------------------------------------------------- 1 | class CreateComments < ActiveRecord::Migration 2 | def change 3 | create_table :comments do |t| 4 | t.string :commenter 5 | t.text :body 6 | t.references :article, index: true 7 | 8 | t.timestamps null: false 9 | end 10 | add_foreign_key :comments, :articles 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20150315103101_add_view_count_to_articles.rb: -------------------------------------------------------------------------------- 1 | class AddViewCountToArticles < ActiveRecord::Migration 2 | def change 3 | add_column :articles, :view_count, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150315112806_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from acts_as_taggable_on_engine (originally 1) 2 | class ActsAsTaggableOnMigration < ActiveRecord::Migration 3 | def self.up 4 | create_table :tags do |t| 5 | t.string :name 6 | end 7 | 8 | create_table :taggings do |t| 9 | t.references :tag 10 | 11 | # You should make sure that the column created is 12 | # long enough to store the required class names. 13 | t.references :taggable, polymorphic: true 14 | t.references :tagger, polymorphic: true 15 | 16 | # Limit is created to prevent MySQL error on index 17 | # length for MyISAM table type: http://bit.ly/vgW2Ql 18 | t.string :context, limit: 128 19 | 20 | t.datetime :created_at 21 | end 22 | 23 | add_index :taggings, :tag_id 24 | add_index :taggings, [:taggable_id, :taggable_type, :context] 25 | end 26 | 27 | def self.down 28 | drop_table :taggings 29 | drop_table :tags 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /db/migrate/20150315112807_add_missing_unique_indices.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from acts_as_taggable_on_engine (originally 2) 2 | class AddMissingUniqueIndices < ActiveRecord::Migration 3 | def self.up 4 | add_index :tags, :name, unique: true 5 | 6 | remove_index :taggings, :tag_id 7 | remove_index :taggings, [:taggable_id, :taggable_type, :context] 8 | add_index :taggings, 9 | [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type], 10 | unique: true, name: 'taggings_idx' 11 | end 12 | 13 | def self.down 14 | remove_index :tags, :name 15 | 16 | remove_index :taggings, name: 'taggings_idx' 17 | add_index :taggings, :tag_id 18 | add_index :taggings, [:taggable_id, :taggable_type, :context] 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /db/migrate/20150315112808_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from acts_as_taggable_on_engine (originally 3) 2 | class AddTaggingsCounterCacheToTags < ActiveRecord::Migration 3 | def self.up 4 | add_column :tags, :taggings_count, :integer, default: 0 5 | 6 | ActsAsTaggableOn::Tag.reset_column_information 7 | ActsAsTaggableOn::Tag.find_each do |tag| 8 | ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings) 9 | end 10 | end 11 | 12 | def self.down 13 | remove_column :tags, :taggings_count 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20150315112809_add_missing_taggable_index.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from acts_as_taggable_on_engine (originally 4) 2 | class AddMissingTaggableIndex < ActiveRecord::Migration 3 | def self.up 4 | add_index :taggings, [:taggable_id, :taggable_type, :context] 5 | end 6 | 7 | def self.down 8 | remove_index :taggings, [:taggable_id, :taggable_type, :context] 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20150315112810_change_collation_for_tag_names.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from acts_as_taggable_on_engine (originally 5) 2 | # This migration is added to circumvent issue #623 and have special characters 3 | # work properly 4 | class ChangeCollationForTagNames < ActiveRecord::Migration 5 | def up 6 | if ActsAsTaggableOn::Utils.using_mysql? 7 | execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;") 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20150315142442_rolify_create_roles.rb: -------------------------------------------------------------------------------- 1 | class RolifyCreateRoles < ActiveRecord::Migration 2 | def change 3 | create_table(:roles) do |t| 4 | t.string :name 5 | t.references :resource, :polymorphic => true 6 | 7 | t.timestamps 8 | end 9 | 10 | create_table(:users_roles, :id => false) do |t| 11 | t.references :user 12 | t.references :role 13 | end 14 | 15 | add_index(:roles, :name) 16 | add_index(:roles, [ :name, :resource_type, :resource_id ]) 17 | add_index(:users_roles, [ :user_id, :role_id ]) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /db/migrate/20150318150436_add_avatar_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddAvatarToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :avatar, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150321020003_create_settings.rb: -------------------------------------------------------------------------------- 1 | class CreateSettings < ActiveRecord::Migration 2 | def self.up 3 | create_table :settings do |t| 4 | t.string :var, :null => false 5 | t.text :value, :null => true 6 | t.integer :thing_id, :null => true 7 | t.string :thing_type, :limit => 30, :null => true 8 | t.timestamps 9 | end 10 | 11 | add_index :settings, [ :thing_type, :thing_id, :var ], :unique => true 12 | end 13 | 14 | def self.down 15 | drop_table :settings 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # This file is auto-generated from the current state of the database. Instead 3 | # of editing this file, please use the migrations feature of Active Record to 4 | # incrementally modify your database, and then regenerate this schema definition. 5 | # 6 | # Note that this schema.rb definition is the authoritative source for your 7 | # database schema. If you need to create the application database on another 8 | # system, you should be using db:schema:load, not running all the migrations 9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 10 | # you'll amass, the slower it'll run and the greater likelihood for issues). 11 | # 12 | # It's strongly recommended that you check this file into your version control system. 13 | 14 | ActiveRecord::Schema.define(version: 20150321020003) do 15 | 16 | create_table "articles", force: :cascade do |t| 17 | t.string "title" 18 | t.text "text" 19 | t.datetime "created_at", null: false 20 | t.datetime "updated_at", null: false 21 | t.integer "view_count" 22 | end 23 | 24 | create_table "comments", force: :cascade do |t| 25 | t.string "commenter" 26 | t.text "body" 27 | t.integer "article_id" 28 | t.datetime "created_at", null: false 29 | t.datetime "updated_at", null: false 30 | end 31 | 32 | add_index "comments", ["article_id"], name: "index_comments_on_article_id" 33 | 34 | create_table "roles", force: :cascade do |t| 35 | t.string "name" 36 | t.integer "resource_id" 37 | t.string "resource_type" 38 | t.datetime "created_at" 39 | t.datetime "updated_at" 40 | end 41 | 42 | add_index "roles", ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id" 43 | add_index "roles", ["name"], name: "index_roles_on_name" 44 | 45 | create_table "settings", force: :cascade do |t| 46 | t.string "var", null: false 47 | t.text "value" 48 | t.integer "thing_id" 49 | t.string "thing_type", limit: 30 50 | t.datetime "created_at" 51 | t.datetime "updated_at" 52 | end 53 | 54 | add_index "settings", ["thing_type", "thing_id", "var"], name: "index_settings_on_thing_type_and_thing_id_and_var", unique: true 55 | 56 | create_table "taggings", force: :cascade do |t| 57 | t.integer "tag_id" 58 | t.integer "taggable_id" 59 | t.string "taggable_type" 60 | t.integer "tagger_id" 61 | t.string "tagger_type" 62 | t.string "context", limit: 128 63 | t.datetime "created_at" 64 | end 65 | 66 | add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true 67 | add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context" 68 | 69 | create_table "tags", force: :cascade do |t| 70 | t.string "name" 71 | t.integer "taggings_count", default: 0 72 | end 73 | 74 | add_index "tags", ["name"], name: "index_tags_on_name", unique: true 75 | 76 | create_table "users", force: :cascade do |t| 77 | t.string "email", default: "", null: false 78 | t.string "encrypted_password", default: "", null: false 79 | t.string "reset_password_token" 80 | t.datetime "reset_password_sent_at" 81 | t.datetime "remember_created_at" 82 | t.integer "sign_in_count", default: 0, null: false 83 | t.datetime "current_sign_in_at" 84 | t.datetime "last_sign_in_at" 85 | t.string "current_sign_in_ip" 86 | t.string "last_sign_in_ip" 87 | t.datetime "created_at" 88 | t.datetime "updated_at" 89 | t.string "provider" 90 | t.string "uid" 91 | t.string "avatar" 92 | end 93 | 94 | add_index "users", ["email"], name: "index_users_on_email", unique: true 95 | add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true 96 | 97 | create_table "users_roles", id: false, force: :cascade do |t| 98 | t.integer "user_id" 99 | t.integer "role_id" 100 | end 101 | 102 | add_index "users_roles", ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id" 103 | 104 | end 105 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 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: 'Emanuel', city: cities.first) 8 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/lib/assets/.keep -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/lib/tasks/.keep -------------------------------------------------------------------------------- /lib/templates/haml/scaffold/_form.html.haml: -------------------------------------------------------------------------------- 1 | = simple_form_for(@<%= singular_table_name %>) do |f| 2 | = f.error_notification 3 | 4 | .form-inputs 5 | <%- attributes.each do |attribute| -%> 6 | = f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> 7 | <%- end -%> 8 | 9 | .form-actions 10 | = f.button :submit 11 | -------------------------------------------------------------------------------- /log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/log/.keep -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/test/controllers/.keep -------------------------------------------------------------------------------- /test/controllers/articles_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ArticlesControllerTest < ActionController::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/controllers/comments_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class CommentsControllerTest < ActionController::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/controllers/products_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ProductsControllerTest < ActionController::TestCase 4 | setup do 5 | @product = products(:one) 6 | end 7 | 8 | test "should get index" do 9 | get :index 10 | assert_response :success 11 | assert_not_nil assigns(:products) 12 | end 13 | 14 | test "should get new" do 15 | get :new 16 | assert_response :success 17 | end 18 | 19 | test "should create product" do 20 | assert_difference('Product.count') do 21 | post :create, product: { description: @product.description, name: @product.name, price: @product.price } 22 | end 23 | 24 | assert_redirected_to product_path(assigns(:product)) 25 | end 26 | 27 | test "should show product" do 28 | get :show, id: @product 29 | assert_response :success 30 | end 31 | 32 | test "should get edit" do 33 | get :edit, id: @product 34 | assert_response :success 35 | end 36 | 37 | test "should update product" do 38 | patch :update, id: @product, product: { description: @product.description, name: @product.name, price: @product.price } 39 | assert_redirected_to product_path(assigns(:product)) 40 | end 41 | 42 | test "should destroy product" do 43 | assert_difference('Product.count', -1) do 44 | delete :destroy, id: @product 45 | end 46 | 47 | assert_redirected_to products_path 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/fixtures/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/test/fixtures/.keep -------------------------------------------------------------------------------- /test/fixtures/articles.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | one: 4 | title: MyString 5 | text: MyText 6 | 7 | two: 8 | title: MyString 9 | text: MyText 10 | -------------------------------------------------------------------------------- /test/fixtures/comments.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | one: 4 | commenter: MyString 5 | body: MyText 6 | article_id: 7 | 8 | two: 9 | commenter: MyString 10 | body: MyText 11 | article_id: 12 | -------------------------------------------------------------------------------- /test/fixtures/products.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | one: 4 | name: MyString 5 | price: 1 6 | description: MyText 7 | 8 | two: 9 | name: MyString 10 | price: 1 11 | description: MyText 12 | -------------------------------------------------------------------------------- /test/fixtures/roles.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | # This model initially had no columns defined. If you add columns to the 4 | # model remove the '{}' from the fixture names and add the columns immediately 5 | # below each fixture, per the syntax in the comments below 6 | # 7 | one: {} 8 | # column: value 9 | # 10 | two: {} 11 | # column: value 12 | -------------------------------------------------------------------------------- /test/fixtures/users.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | # This model initially had no columns defined. If you add columns to the 4 | # model remove the '{}' from the fixture names and add the columns immediately 5 | # below each fixture, per the syntax in the comments below 6 | # 7 | one: {} 8 | # column: value 9 | # 10 | two: {} 11 | # column: value 12 | -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/test/helpers/.keep -------------------------------------------------------------------------------- /test/integration/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/test/integration/.keep -------------------------------------------------------------------------------- /test/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/test/mailers/.keep -------------------------------------------------------------------------------- /test/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/test/models/.keep -------------------------------------------------------------------------------- /test/models/article_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ArticleTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/comment_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class CommentTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/product_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ProductTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/role_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class RoleTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/user_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class UserTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV['RAILS_ENV'] ||= 'test' 2 | require File.expand_path('../../config/environment', __FILE__) 3 | require 'rails/test_help' 4 | 5 | class ActiveSupport::TestCase 6 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. 7 | fixtures :all 8 | 9 | # Add more helper methods to be used by all tests here... 10 | end 11 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/vendor/assets/javascripts/.keep -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiwenhn2008/rails4blog/8950ad421418895570653fc9c7b8712e4d815fea/vendor/assets/stylesheets/.keep --------------------------------------------------------------------------------