构建 Comment 评论功能
git checkout -b xw-020304
`
Switched to a new branch 'xw-020304'
rails generate model Comment content:text message:references user:references
Running via Spring preloader in process 2222 invoke active_record create db/migrate/20180203100358_create_comments.rb create app/models/comment.rb invoke test_unit create test/models/comment_test.rb create test/fixtures/comments.yml
rake db:migrate
`
== 20180203100358 CreateComments: migrating ======== -- create_table(:comments) -> 0.0055s == 20180203100358 CreateComments: migrated (0.0056s) ========
rails c
Running via Spring preloader in process 2312 Loading development environment (Rails 5.1.4)
2.3.1 :001 > Comment.connection
=> #<ActiveRecord::ConnectionAdapters::SQLite3Adapter:0x007fdec5c09490 @transaction_manager=#<ActiveRecord::ConnectionAdapters::TransactionManager:0x007fdec5be16c0 @stack=[], @connection=#<ActiveRecord::ConnectionAdapters::SQLite3Adapter:0x007fdec5c09490 ...>>, @query_cache={}, @query_cache_enabled=false, @connection=#<SQLite3::Database:0x007fdec5c09828 @tracefunc=nil, @authorizer=nil, @encoding=#<Encoding:UTF-8>, @busy_handler=nil, @collations={}, @functions={}, @results_as_hash=true, @type_translation=nil, @readonly=false>, @owner=#<Thread:0x007fdec2883418 run>, @instrumenter=#<ActiveSupport::Notifications::Instrumenter:0x007fdec5b08e88 @id="401f7b11a16681fdf126", @notifier=#<ActiveSupport::Notifications::Fanout:0x007fdec32328b0 @subscribers=[#<ActiveSupport::Notifications::Fanout::Subscribers::Evented:0x007fdec59e8d50 @pattern="sql.active_record", @delegate=#<ActiveRecord::LogSubscriber:0x007fdec59e9070 @queue_key="ActiveRecord::LogSubscriber-70297387485240", @patterns=["sql.active_record"]>, @can_publish=false>, #<ActiveSupport::Notifications::Fanout::Subscribers::Evented:0x007fdec5993a30 @pattern="logger.action_view", @delegate=#<ActionView::LogSubscriber:0x007fdec5993e18 @root=nil, @queue_key="ActionView::LogSubscriber-70297387310860", @patterns=["logger.action_view", "render_partial.action_view", "render_template.action_view", "render_collection.action_view"]>, @can_publish=false>, #<ActiveSupport::Notifications::Fanout::Subscribers::Evented:0x007fdec5993828 @pattern="render_partial.action_view", @delegate=#<ActionView::LogSubscriber:0x007fdec5993e18 @root=nil, @queue_key="ActionView::LogSubscriber-70297387310860", @patterns=["logger.action_view", "render_partial.action_view", "render_template.action_view", "render_collection.action_view"]>, @can_publish=false>, #<ActiveSupport::Notifications::Fanout::Subscribers::Evented:0x007fdec5993648 @pattern="render_template.action_view", @delegate=#<ActionView::LogSubscriber:0x007fdec5993e18 @root=nil, @queue_key="ActionView::LogSubscriber-70297387310860", @patterns=["logger.action_view", "render_partial.action_view", "render_template.action_view", "render_collection.action_view"]>, @can_publish=false>, #<ActiveSupport::Notifications::Fanout::Subscribers::Evented:0x007fdec5993440 @pattern="render_collection.action_view", @delegate=#<ActionView::LogSubscriber:0x007fdec5993e18 @root=nil, @queue_key="ActionView::LogSubscriber-70297387310860", @patterns=["logger.action_view", "render_partial.action_view", "render_template.action_view", "render_collection.action_view"]>, @can_publish=false>, #<ActiveSupport::Notifications::Fanout::Subscribers::Evented:0x007fdec2d7cf00 @pattern="sql.active_record", @delegate=#<ActiveRecord::ExplainSubscriber:0x007fdec2d7cfa0>, @can_publish=false>], @listeners_for=#<Concurrent::Map:0x007fdec3232860 entries=2 default_proc=nil>, @_mutex=#<Thread::Mutex:0x007fdec3232748>>>, @logger=#<ActiveSupport::Logger:0x007fdec3630098 @progname=nil, @level=0, @default_formatter=#<Logger::Formatter:0x007fdec3630020 @datetime_format=nil>, @formatter=#<ActiveSupport::Logger::SimpleFormatter:0x007fdec36d2118 @datetime_format=nil>, @logdev=#<Logger::LogDevice:0x007fdec3630a70 @shift_size=nil, @shift_age=nil, @filename=nil, @dev=#<File:/Users/xiaowei/messageapp/log/development.log>, @mon_owner=nil, @mon_count=0, @mon_mutex=#<Thread::Mutex:0x007fdec3630ea8>>, @local_levels=#<Concurrent::Map:0x007fdec3631ee8 entries=0 default_proc=nil>>, @config={:adapter=>"sqlite3", :pool=>5, :timeout=>5000, :database=>"/Users/xiaowei/messageapp/db/development.sqlite3"}, @pool=#<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007fdec5dc8a38 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Thread::Mutex:0x007fdec5dc8948>, @query_cache_enabled=#<Concurrent::Map:0x007fdec5dc8920 entries=0 default_proc=#<Proc:0x007fdec5dc8880@/Users/xiaowei/.rvm/gems/ruby-2.3.1/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/query_cache.rb:27>>, @spec=#<ActiveRecord::ConnectionAdapters::ConnectionSpecification:0x007fdec5dc8bf0 @name="primary", @config={:adapter=>"sqlite3", :pool=>5, :timeout=>5000, :database=>"/Users/xiaowei/messageapp/db/development.sqlite3"}, @adapter_method="sqlite3_connection">, @checkout_timeout=5, @reaper=#<ActiveRecord::ConnectionAdapters::ConnectionPool::Reaper:0x007fdec5dc8808 @pool=#<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007fdec5dc8a38 ...>, @frequency=nil>, @size=5, @thread_cached_conns=#<Concurrent::Map:0x007fdec5dc87b8 entries=1 default_proc=nil>, @connections=[#<ActiveRecord::ConnectionAdapters::SQLite3Adapter:0x007fdec5c09490 ...>], @automatic_reconnect=true, @now_connecting=0, @threads_blocking_new_connections=0, @available=#<ActiveRecord::ConnectionAdapters::ConnectionPool::ConnectionLeasingQueue:0x007fdec5dc86a0 @lock=#<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007fdec5dc8a38 ...>, @cond=#<MonitorMixin::ConditionVariable:0x007fdec5dc8600 @monitor=#<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007fdec5dc8a38 ...>, @cond=#<Thread::ConditionVariable:0x007fdec5dc85b0>>, @num_waiting=0, @queue=[]>, @lock_thread=false>, @schema_cache=#<ActiveRecord::ConnectionAdapters::SchemaCache:0x007fdec5be1440 @connection=#<ActiveRecord::ConnectionAdapters::SQLite3Adapter:0x007fdec5c09490 ...>, @columns={}, @columns_hash={}, @primary_keys={}, @data_sources={}>, @quoted_table_names={}, @quoted_column_names={}, @visitor=#<Arel::Visitors::SQLite:0x007fdec5be11e8 @dispatch={}, @connection=#<ActiveRecord::ConnectionAdapters::SQLite3Adapter:0x007fdec5c09490 ...>>, @lock=#<Monitor:0x007fdec5be1120 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Thread::Mutex:0x007fdec5be10a8>>, @prepared_statements=true, @active=nil, @statements=#<ActiveRecord::ConnectionAdapters::SQLite3Adapter::StatementPool:0x007fdec5be0fb8 @cache={}, @statement_limit=1000>>
2.3.1 :002 > Comment
`
=> Comment(id: integer, content: text, message_id: integer, user_id: integer, created_at: datetime, updated_at: datetime)
2.3.1 :003 > exit
rails g controller Comments
Running via Spring preloader in process 2353
create app/controllers/comments_controller.rb
invoke erb
create app/views/comments
invoke test_unit
create test/controllers/comments_controller_test.rb
invoke helper
create app/helpers/comments_helper.rb
invoke test_unit
invoke assets
invoke coffee
create app/assets/javascripts/comments.coffee
invoke scss
create app/assets/stylesheets/comments.scss
R: 修改root
C:修改controller
V:修改views
M:修改model
代码展示:
message show
<h2><%= @message.title %></h2>
<p>posted by <%= @message.user.email %><%= time_ago_in_words(@message.created_at) %>ago</p>
<p><%= @message.description %></p>
<!-- add a poster at timestamp -->
<h3>Comments:</h3>
<%= render @message.comments %>
<h3>reply to message:</h3>
<%= render 'comments/form' %>
<%= link_to "back", messages_path(@message) %>
<% if user_signed_in? %>
<% if @message.user_id == current_user.id %>
<%= link_to "edit", edit_message_path(@message) %>
<%= link_to "Delete", message_path(@message), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-default" %>
<% end %>
<% end %>
comment
_comment.html.erb
<%= comment.content="" %="">
posted by <%= comment.user.email="" %=""><%= time_ago_in_words(comment.created_at)="" %="">ago
<% if user_signed_in? %> <% if comment.user_id == current_user.id %> <%= link_to "edit", edit_message_comment_path(comment.message,comment) %> <%= link_to "Delete", message_comment_path(comment.message, comment), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-default" %> <% end %> <% end %> _form.html.erb
<%= simple_form_for ([@message,@message.comments.build]) do |f| %>
<%= f.input :content, label: "comment" %>
<%= f.button :submit %>
<% end %>
edit
<h1>edit comment</h1>
<%= simple_form_for([@message,@comment]) do |f| %>
<%= f.input :content, label: "comment" %>
<%= f.button :submit %>
<% end %>
rake routes
```
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
user_password PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
POST /users/password(.:format) devise/passwords#create
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
user_registration PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
POST /users(.:format) devise/registrations#create
message_comments GET /messages/:message_id/comments(.:format) comments#index
POST /messages/:message_id/comments(.:format) comments#create
new_message_comment GET /messages/:message_id/comments/new(.:format) comments#new
edit_message_comment GET /messages/:message_id/comments/:id/edit(.:format) comments#edit
message_comment GET /messages/:message_id/comments/:id(.:format) comments#show
PATCH /messages/:message_id/comments/:id(.:format) comments#update
PUT /messages/:message_id/comments/:id(.:format) comments#update
DELETE /messages/:message_id/comments/:id(.:format) comments#destroy
messages GET /messages(.:format) messages#index
POST /messages(.:format) messages#create
new_message GET /messages/new(.:format) messages#new
edit_message GET /messages/:id/edit(.:format) messages#edit
message GET /messages/:id(.:format) messages#show
PATCH /messages/:id(.:format) messages#update
PUT /messages/:id(.:format) messages#update
DELETE /messages/:id(.:format) messages#destroy
root GET / messages#index
rails s
=> Booting Puma
=> Rails 5.1.4 application starting in development
=> Run rails server -h
for more startup options
Puma starting in single mode...
- Version 3.11.2 (ruby 2.3.1-p112), codename: Love Song
- Min threads: 5, max threads: 5
- Environment: development
- Listening on tcp://0.0.0.0:3000 Use Ctrl-C to stop