diff --git a/app/assets/stylesheets/static_pages.css.scss b/app/assets/stylesheets/static_pages.css.scss index 284c9ef..0408814 100644 --- a/app/assets/stylesheets/static_pages.css.scss +++ b/app/assets/stylesheets/static_pages.css.scss @@ -191,4 +191,32 @@ input { border-bottom: 1px solid $grayLighter; } } - } \ No newline at end of file + } + +/* microposts */ + +.microposts { + list-style: none; + margin: 10px 0 0 0; + + li { + padding: 10px 0; + border-top: 1px solid #e8e8e8; + } +} +.content { + display: block; +} +.timestamp { + color: $grayLight; +} +.gravatar { + float: left; + margin-right: 10px; +} +aside { + textarea { + height: 100px; + margin-bottom: 5px; + } +} \ No newline at end of file diff --git a/app/controllers/microposts_controller.rb b/app/controllers/microposts_controller.rb new file mode 100644 index 0000000..2e65fb0 --- /dev/null +++ b/app/controllers/microposts_controller.rb @@ -0,0 +1,30 @@ +class MicropostsController < ApplicationController + before_action :signed_in_user + + def create + @micropost = current_user.microposts.build(micropost_params) + if @micropost.save + flash[:success] = "Micropost created!" + redirect_to root_url + else + @feed_items = [] + render 'static_pages/home' + end + end + + def destroy + @micropost.destroy + redirect_to root_url + end + + private + + def micropost_params + params.require(:micropost).permit(:content) + end + def correct_user + @micropost = current_user.microposts.find_by(id: params[:id]) + redirect_to root_url if @micropost.nil? + end + +end \ No newline at end of file diff --git a/app/controllers/static_pages_controller.rb b/app/controllers/static_pages_controller.rb index d0c9ebb..ff86a0f 100644 --- a/app/controllers/static_pages_controller.rb +++ b/app/controllers/static_pages_controller.rb @@ -1,5 +1,10 @@ class StaticPagesController < ApplicationController + def home + if signed_in? + @micropost = current_user.microposts.build + @feed_items = current_user.feed.paginate(page: params[:page]) + end end def help diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index d86c0ce..6b7b828 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -9,6 +9,7 @@ class UsersController < ApplicationController def show @user = User.find(params[:id]) + @microposts = @user.microposts.paginate(page: params[:page]) end def new @@ -51,13 +52,6 @@ class UsersController < ApplicationController def admin_user redirect_to(root_url) unless current_user.admin? end - - def signed_in_user - unless signed_in? - store_location - redirect_to signin_url, notice: "Please sign in." - end - end def correct_user @user = User.find(params[:id]) diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index 3da6641..9559f35 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -25,7 +25,12 @@ module SessionsHelper def current_user?(user) user == current_user end - + def signed_in_user + unless signed_in? + store_location + redirect_to signin_url, notice: "Please sign in." + end + end def sign_out self.current_user = nil diff --git a/app/models/micropost.rb b/app/models/micropost.rb new file mode 100644 index 0000000..70493fe --- /dev/null +++ b/app/models/micropost.rb @@ -0,0 +1,6 @@ +class Micropost < ActiveRecord::Base + belongs_to :user + default_scope -> { order('created_at DESC') } + validates :content, presence: true, length: { maximum: 140 } + validates :user_id, presence: true +end \ No newline at end of file diff --git a/app/models/user.rb b/app/models/user.rb index d68c333..c4128b1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,5 @@ class User < ActiveRecord::Base + has_many :microposts, dependent: :destroy before_save { self.email = email.downcase } before_create :create_remember_token validates :name, presence: true, length: { maximum: 50 } @@ -17,6 +18,11 @@ class User < ActiveRecord::Base Digest::SHA1.hexdigest(token.to_s) end + def feed + # This is preliminary. See "Following users" for the full implementation. + Micropost.where("user_id = ?", id) + end + private def create_remember_token diff --git a/app/views/microposts/_micropost.html.erb b/app/views/microposts/_micropost.html.erb new file mode 100644 index 0000000..fe116ba --- /dev/null +++ b/app/views/microposts/_micropost.html.erb @@ -0,0 +1,11 @@ +
  • + <%= micropost.content %> + + Posted <%= time_ago_in_words(micropost.created_at) %> ago. + + <% if current_user?(micropost.user) %> + <%= link_to "delete", micropost, method: :delete, + data: { confirm: "You sure?" }, + title: micropost.content %> + <% end %> +
  • \ No newline at end of file diff --git a/app/views/shared/_error_messages.html.erb b/app/views/shared/_error_messages.html.erb index d441f4c..a455f6c 100644 --- a/app/views/shared/_error_messages.html.erb +++ b/app/views/shared/_error_messages.html.erb @@ -1,10 +1,10 @@ -<% if @user.errors.any? %> +<% if object.errors.any? %>
    - The form contains <%= pluralize(@user.errors.count, "error") %>. + The form contains <%= pluralize(object.errors.count, "error") %>.
    diff --git a/app/views/shared/_feed.html.erb b/app/views/shared/_feed.html.erb new file mode 100644 index 0000000..edc8f5a --- /dev/null +++ b/app/views/shared/_feed.html.erb @@ -0,0 +1,6 @@ +<% if @feed_items.any? %> +
      + <%= render partial: 'shared/feed_item', collection: @feed_items %> +
    + <%= will_paginate @feed_items %> +<% end %> \ No newline at end of file diff --git a/app/views/shared/_feed_item.html.erb b/app/views/shared/_feed_item.html.erb new file mode 100644 index 0000000..019e1e1 --- /dev/null +++ b/app/views/shared/_feed_item.html.erb @@ -0,0 +1,15 @@ +
  • + <%= link_to gravatar_for(feed_item.user), feed_item.user %> + + <%= link_to feed_item.user.name, feed_item.user %> + + <%= feed_item.content %> + + Posted <%= time_ago_in_words(feed_item.created_at) %> ago. + + <% if current_user?(feed_item.user) %> + <%= link_to "delete", feed_item, method: :delete, + data: { confirm: "You sure?" }, + title: feed_item.content %> + <% end %> +
  • \ No newline at end of file diff --git a/app/views/shared/_micropost_form.html.erb b/app/views/shared/_micropost_form.html.erb new file mode 100644 index 0000000..dbc8ee1 --- /dev/null +++ b/app/views/shared/_micropost_form.html.erb @@ -0,0 +1,7 @@ +<%= form_for(@micropost) do |f| %> + <%= render 'shared/error_messages', object: f.object %> +
    + <%= f.text_area :content, placeholder: "Compose new micropost..." %> +
    + <%= f.submit "Post", class: "btn btn-large btn-primary" %> +<% end %> \ No newline at end of file diff --git a/app/views/shared/_user_info.html.erb b/app/views/shared/_user_info.html.erb new file mode 100644 index 0000000..04f2c79 --- /dev/null +++ b/app/views/shared/_user_info.html.erb @@ -0,0 +1,10 @@ +<%= link_to gravatar_for(current_user, size: 52), current_user %> +

    + <%= current_user.name %> +

    + + <%= link_to "view my profile", current_user %> + + + <%= pluralize(current_user.microposts.count, "micropost") %> + \ No newline at end of file diff --git a/app/views/static_pages/home.html.erb b/app/views/static_pages/home.html.erb index ad47b04..a0f5d2f 100644 --- a/app/views/static_pages/home.html.erb +++ b/app/views/static_pages/home.html.erb @@ -1,13 +1,31 @@ -
    -

    Welcome to the Sample App

    +<% if signed_in? %> +
    + +
    +

    Micropost Feed

    + <%= render 'shared/feed' %> +
    +
    +<% else %> +
    +

    Welcome to the Sample App

    -

    - This is the home page for the - Ruby on Rails Tutorial - sample application. -

    +

    + This is the home page for the + Ruby on Rails Tutorial + sample application. +

    - <%= link_to "Sign up now!", signup_path, class: "btn btn-large btn-primary" %> -
    + <%= link_to "Sign up now!", signup_path, + class: "btn btn-large btn-primary" %> +
    -<%= link_to image_tag("rails.png", alt: "Rails"), 'http://rubyonrails.org/' %> \ No newline at end of file + <%= link_to image_tag("rails.png", alt: "Rails"), 'http://rubyonrails.org/' %> +<% end %> \ No newline at end of file diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 48c8fc7..e06640d 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -4,7 +4,7 @@
    <%= form_for(@user) do |f| %> - <%= render 'shared/error_messages' %> + <%= render 'shared/error_messages', object: f.object %> <%= f.label :name %> <%= f.text_field :name %> diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb index 0e42845..0558efe 100644 --- a/app/views/users/new.html.erb +++ b/app/views/users/new.html.erb @@ -5,7 +5,7 @@
    <%= form_for(@user) do |f| %> - <%= render 'shared/error_messages' %> + <%= render 'shared/error_messages', object: f.object %> <%= f.label :name %> <%= f.text_field :name %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index a6db57a..0ebe5a2 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -8,4 +8,13 @@ +
    + <% if @user.microposts.any? %> +

    Microposts (<%= @user.microposts.count %>)

    +
      + <%= render @microposts %> +
    + <%= will_paginate @microposts %> + <% end %> +
    \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index cfde7b3..763b8e3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,9 +2,10 @@ SampleApp::Application.routes.draw do resources :products resources :users resources :sessions, only: [:new, :create, :destroy] + resources :microposts, only: [:create, :destroy] root 'static_pages#home' match '/signup', to: 'users#new', via: 'get' - match '/signin', to: 'sessions#new', via: 'get' + match '/signin', to: 'sessions#new', via: 'get' match '/signout', to: 'sessions#destroy', via: 'delete' match '/help', to: 'static_pages#help', via: 'get' match '/about', to: 'static_pages#about', via: 'get' diff --git a/db/migrate/20131107052554_create_microposts.rb b/db/migrate/20131107052554_create_microposts.rb new file mode 100644 index 0000000..988c9df --- /dev/null +++ b/db/migrate/20131107052554_create_microposts.rb @@ -0,0 +1,11 @@ +class CreateMicroposts < ActiveRecord::Migration + def change + create_table :microposts do |t| + t.string :content + t.integer :user_id + + t.timestamps + end + add_index :microposts, [:user_id, :created_at] + end +end diff --git a/db/schema.rb b/db/schema.rb index 47b80bc..1c0e962 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,16 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20131105022512) do +ActiveRecord::Schema.define(version: 20131107052554) do + + create_table "microposts", force: true do |t| + t.string "content" + t.integer "user_id" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "microposts", ["user_id", "created_at"], name: "index_microposts_on_user_id_and_created_at" create_table "products", force: true do |t| t.string "name" diff --git a/lib/tasks/sample_data.rake b/lib/tasks/sample_data.rake index 7c0fc50..52b02c4 100644 --- a/lib/tasks/sample_data.rake +++ b/lib/tasks/sample_data.rake @@ -1,7 +1,9 @@ namespace :db do + desc "Fill database with sample data" task populate: :environment do - User.create!(name: "Example User", + + User.create!(name: "Example User", email: "example@railstutorial.org", password: "foobar", password_confirmation: "foobar") @@ -14,5 +16,11 @@ namespace :db do password: password, password_confirmation: password) end - end -end \ No newline at end of file + users = User.all(limit: 6) + 50.times do + content = Faker::Lorem.sentence(5) + users.each { |user| user.microposts.create!(content: content) } + end +end +end + \ No newline at end of file diff --git a/spec/factories.rb b/spec/factories.rb index 5c0cbc2..5bbc0ab 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -4,5 +4,14 @@ FactoryGirl.define do sequence(:email) { |n| "person_#{n}@example.com"} password "foobar" password_confirmation "foobar" + + factory :admin do + admin true + end + end + + factory :micropost do + content "Lorem ipsum" + user end end \ No newline at end of file diff --git a/spec/models/micropost_spec.rb b/spec/models/micropost_spec.rb new file mode 100644 index 0000000..b255ed5 --- /dev/null +++ b/spec/models/micropost_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe Micropost do + + let(:user) { FactoryGirl.create(:user) } + before { @micropost = user.microposts.build(content: "Lorem ipsum") } + + subject { @micropost } + + it { should respond_to(:content) } + it { should respond_to(:user_id) } + it { should respond_to(:user) } + its(:user) { should eq user } + + it { should be_valid } + + describe "when user_id is not present" do + before { @micropost.user_id = nil } + it { should_not be_valid } + end +end \ No newline at end of file diff --git a/spec/requests/micropost_pages_spec.rb b/spec/requests/micropost_pages_spec.rb new file mode 100644 index 0000000..0d3091d --- /dev/null +++ b/spec/requests/micropost_pages_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe "Micropost pages" do + + subject { page } + + let(:user) { FactoryGirl.create(:user) } + before { sign_in user } + + describe "micropost creation" do + before { visit root_path } + + describe "with invalid information" do + + it "should not create a micropost" do + expect { click_button "Post" }.not_to change(Micropost, :count) + end + + describe "error messages" do + before { click_button "Post" } + it { should have_content('error') } + end + end + + describe "with valid information" do + + before { fill_in 'micropost_content', with: "Lorem ipsum" } + it "should create a micropost" do + expect { click_button "Post" }.to change(Micropost, :count).by(1) + end + end + end +end \ No newline at end of file