diff --git a/.ruby-version b/.ruby-version index cc6612c..2bf1c1c 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.3.0 \ No newline at end of file +2.3.1 diff --git a/Gemfile.lock b/Gemfile.lock index 484b95a..a40ff37 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,43 +1,43 @@ GEM remote: https://rubygems.org/ specs: - actioncable (5.2.0) - actionpack (= 5.2.0) + actioncable (5.2.1) + actionpack (= 5.2.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.0) - actionpack (= 5.2.0) - actionview (= 5.2.0) - activejob (= 5.2.0) + actionmailer (5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.0) - actionview (= 5.2.0) - activesupport (= 5.2.0) + actionpack (5.2.1) + actionview (= 5.2.1) + activesupport (= 5.2.1) rack (~> 2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.0) - activesupport (= 5.2.0) + actionview (5.2.1) + activesupport (= 5.2.1) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.0) - activesupport (= 5.2.0) + activejob (5.2.1) + activesupport (= 5.2.1) globalid (>= 0.3.6) - activemodel (5.2.0) - activesupport (= 5.2.0) - activerecord (5.2.0) - activemodel (= 5.2.0) - activesupport (= 5.2.0) + activemodel (5.2.1) + activesupport (= 5.2.1) + activerecord (5.2.1) + activemodel (= 5.2.1) + activesupport (= 5.2.1) arel (>= 9.0) - activestorage (5.2.0) - actionpack (= 5.2.0) - activerecord (= 5.2.0) + activestorage (5.2.1) + actionpack (= 5.2.1) + activerecord (= 5.2.1) marcel (~> 0.3.1) - activesupport (5.2.0) + activesupport (5.2.1) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -47,11 +47,11 @@ GEM arel (9.0.0) bcrypt (3.1.12) bindex (0.5.0) - bootsnap (1.3.1) + bootsnap (1.3.2) msgpack (~> 1.0) builder (3.2.3) byebug (10.0.2) - capybara (3.5.1) + capybara (3.8.2) addressable mini_mime (>= 0.1.3) nokogiri (~> 1.8) @@ -75,7 +75,7 @@ GEM ffi (1.9.25) globalid (0.4.1) activesupport (>= 4.2.0) - i18n (1.0.1) + i18n (1.1.0) concurrent-ruby (~> 1.0) jbuilder (2.7.0) activesupport (>= 4.2.0) @@ -91,11 +91,11 @@ GEM nokogiri (>= 1.5.9) mail (2.7.0) mini_mime (>= 0.1.1) - marcel (0.3.2) + marcel (0.3.3) mimemagic (~> 0.3.2) method_source (0.9.0) mimemagic (0.3.2) - mini_mime (1.0.0) + mini_mime (1.0.1) mini_portile2 (2.3.0) minitest (5.11.3) msgpack (1.2.4) @@ -103,59 +103,59 @@ GEM nio4r (2.3.1) nokogiri (1.8.4) mini_portile2 (~> 2.3.0) - pg (1.0.0) - public_suffix (3.0.2) + pg (1.1.3) + public_suffix (3.0.3) puma (3.12.0) rack (2.0.5) - rack-test (1.0.0) + rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.0) - actioncable (= 5.2.0) - actionmailer (= 5.2.0) - actionpack (= 5.2.0) - actionview (= 5.2.0) - activejob (= 5.2.0) - activemodel (= 5.2.0) - activerecord (= 5.2.0) - activestorage (= 5.2.0) - activesupport (= 5.2.0) + rails (5.2.1) + actioncable (= 5.2.1) + actionmailer (= 5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) + activemodel (= 5.2.1) + activerecord (= 5.2.1) + activestorage (= 5.2.1) + activesupport (= 5.2.1) bundler (>= 1.3.0) - railties (= 5.2.0) + railties (= 5.2.1) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-html-sanitizer (1.0.4) loofah (~> 2.2, >= 2.2.2) - railties (5.2.0) - actionpack (= 5.2.0) - activesupport (= 5.2.0) + railties (5.2.1) + actionpack (= 5.2.1) + activesupport (= 5.2.1) method_source rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) + thor (>= 0.19.0, < 2.0) rake (12.3.1) rb-fsevent (0.10.3) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) - rspec-core (3.7.1) - rspec-support (~> 3.7.0) - rspec-expectations (3.7.0) + rspec-core (3.8.0) + rspec-support (~> 3.8.0) + rspec-expectations (3.8.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-mocks (3.7.0) + rspec-support (~> 3.8.0) + rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-rails (3.7.2) + rspec-support (~> 3.8.0) + rspec-rails (3.8.0) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-support (~> 3.7.0) - rspec-support (3.7.1) + rspec-core (~> 3.8.0) + rspec-expectations (~> 3.8.0) + rspec-mocks (~> 3.8.0) + rspec-support (~> 3.8.0) + rspec-support (3.8.0) ruby_dep (1.5.0) - sass (3.5.7) + sass (3.6.0) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) @@ -178,9 +178,9 @@ GEM tilt (2.0.8) tzinfo (1.2.5) thread_safe (~> 0.1) - uglifier (4.1.15) + uglifier (4.1.19) execjs (>= 0.3.0, < 3) - web-console (3.6.2) + web-console (3.7.0) actionview (>= 5.0) activemodel (>= 5.0) bindex (>= 0.4.0) @@ -217,4 +217,4 @@ RUBY VERSION ruby 2.3.1p112 BUNDLED WITH - 1.14.6 + 1.16.3 diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 6868d20..fe88aaf 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,7 +1,11 @@ class ApplicationController < ActionController::Base - helper_method :current_user + helper_method :current_user, :authorized_user def current_user @current_user ||= User.find(session[:user_id]) if session[:user_id] end + + def authorized_user(other_user) + current_user.id == other_user.id + end end diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb new file mode 100644 index 0000000..22100ab --- /dev/null +++ b/app/controllers/dashboard_controller.rb @@ -0,0 +1,8 @@ +class DashboardController < ApplicationController + def show + if !current_user + redirect_to root_path + flash[:warning] = 'You must be logged in first.' + end + end +end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb new file mode 100644 index 0000000..3ebd0e3 --- /dev/null +++ b/app/controllers/groups_controller.rb @@ -0,0 +1,53 @@ +class GroupsController < ApplicationController + before_action :set_group, only: [:show, :edit, :update, :destroy] + + def index + @groups = Group.all + end + + def new + @group = Group.new + end + + def create + @group = Group.new(group_params) + @group.user_ids= current_user.id + if @group.save + redirect_to dashboard_path + else + render 'new' + end + end + + def show + end + + def edit + end + + def update + if @group.update(group_params) + flash[:notice] = "Group '#{@group.name}' updated!" + redirect_to group_path(@group) + else + flash[:warning] = 'An error occurred, please try again.' + render 'edit' + end + end + + def destroy + @group.destroy + flash[:notice] = 'Group Deleted!' + redirect_to dashboard_path + end + + private + + def set_group + @group = Group.find(params[:id]) + end + + def group_params + params.require(:group).permit(:name, :description) + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 34eed65..a22a721 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,8 +1,9 @@ class UsersController < ApplicationController + before_action :set_user, only: [:edit, :update] def new @user = User.new if current_user - redirect_to root_path + redirect_to dashboard_path else render 'new' end @@ -11,6 +12,7 @@ def new def create @user = User.new(user_params) if @user.save + flash[:notice] = "Account successfully created." redirect_to login_path else render 'new' @@ -18,17 +20,44 @@ def create end def show - if current_user - @user = User.find(session[:user_id]) - render 'show' - else + @user = params[:id] ? User.find(params[:id]) : current_user + if !current_user redirect_to root_url flash[:warning] = 'You must be logged in first.' end end + def edit + end + + def update + segment_string = params[:commit].split(' ')[1] + if @user.update(validate_params(segment_string)) + flash[:notice] = "#{segment_string} successfully updated." + redirect_to profile_path + else + flash[:warning] = "An error occurred, please try again." + render 'edit' + end + end + private + def set_user + @user = current_user + end + + def validate_params(string) + case string + when 'Name' + return params.require(:user).permit(:first_name, :last_name) + when 'Email' + return params.require(:user).permit(:email) + when 'Password' + return params.require(:user).permit(:password, :password_confirmation) + end + end + def user_params params.require(:user).permit(:email, :first_name, :last_name, :password, :password_confirmation) end diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index f9b859b..4a76052 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -1,4 +1,7 @@ class WelcomeController < ApplicationController def index + if current_user + redirect_to dashboard_path + end end end diff --git a/app/models/group.rb b/app/models/group.rb new file mode 100644 index 0000000..afc116b --- /dev/null +++ b/app/models/group.rb @@ -0,0 +1,4 @@ +class Group < ApplicationRecord + has_many :user_groups + has_many :users, through: :user_groups +end diff --git a/app/models/user.rb b/app/models/user.rb index bbfc1b2..3cc1ae8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,6 @@ class User < ApplicationRecord + has_many :user_groups + has_many :groups, through: :user_groups has_secure_password validates_uniqueness_of :email validates :first_name, presence: true diff --git a/app/models/user_group.rb b/app/models/user_group.rb new file mode 100644 index 0000000..99451fc --- /dev/null +++ b/app/models/user_group.rb @@ -0,0 +1,4 @@ +class UserGroup < ApplicationRecord + belongs_to :user + belongs_to :group +end diff --git a/app/views/dashboard/show.html.erb b/app/views/dashboard/show.html.erb new file mode 100644 index 0000000..563501d --- /dev/null +++ b/app/views/dashboard/show.html.erb @@ -0,0 +1,14 @@ +<% if current_user %> +

<%= "Welcome, #{current_user.first_name || current_user.email}." %>

+ <%= link_to 'Profile', profile_path %> + <%= link_to 'Sign Out', logout_path, method: :delete %> + +

My Groups

+ <%= link_to "Create a Group", new_group_path %> +
+ <% if !current_user.groups.empty? %> + <%= render partial: 'users/groups', collection: current_user.groups %> + <% else %> + You are not part of any groups. + <% end %> +<% end %> diff --git a/app/views/groups/_form.html.erb b/app/views/groups/_form.html.erb new file mode 100644 index 0000000..b9f470d --- /dev/null +++ b/app/views/groups/_form.html.erb @@ -0,0 +1,13 @@ +<%= form_for @group do |f| %> +
+ <%= f.label :name %> + <%= f.text_field :name %> +
+
+ <%= f.label :description %> + <%= f.text_area :description %> +
+
+ <%= f.submit %> +
+<% end %> diff --git a/app/views/groups/edit.html.erb b/app/views/groups/edit.html.erb new file mode 100644 index 0000000..884fbc9 --- /dev/null +++ b/app/views/groups/edit.html.erb @@ -0,0 +1,3 @@ +

Edit a Group

+ +<%= render partial: 'groups/form' %> diff --git a/app/views/groups/index.html.erb b/app/views/groups/index.html.erb new file mode 100644 index 0000000..af1dbc7 --- /dev/null +++ b/app/views/groups/index.html.erb @@ -0,0 +1,10 @@ +<% if @groups %> +Groups: + +<% else %> + <%= link_to 'Create a group', new_group_path%> +<% end %> diff --git a/app/views/groups/new.html.erb b/app/views/groups/new.html.erb new file mode 100644 index 0000000..870a96c --- /dev/null +++ b/app/views/groups/new.html.erb @@ -0,0 +1,3 @@ +

Create a Group

+ +<%= render partial: 'groups/form' %> diff --git a/app/views/groups/show.html.erb b/app/views/groups/show.html.erb new file mode 100644 index 0000000..b6f2d49 --- /dev/null +++ b/app/views/groups/show.html.erb @@ -0,0 +1,19 @@ +

<%= @group.name %>

+<%= @group.description %> +
+ +Users in this group: + + + + +
+<%= link_to 'Edit Group', edit_group_path %> +<%= link_to 'Delete Group', group_path, method: :delete, data: { confirm: 'Are you sure? This cannot be undone.' } %> + +
+<%= link_to 'Back', dashboard_path %> diff --git a/app/views/users/_groups.html.erb b/app/views/users/_groups.html.erb new file mode 100644 index 0000000..5193a95 --- /dev/null +++ b/app/views/users/_groups.html.erb @@ -0,0 +1,4 @@ +
+ Group Name: <%= link_to groups.name, group_path(groups.id) %> +

<%= groups.description %>

+
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb new file mode 100644 index 0000000..6f48d80 --- /dev/null +++ b/app/views/users/edit.html.erb @@ -0,0 +1,39 @@ +

Edit Profile

+ +<%= form_for @user do |f| %> +
+ <%= f.label :first_name %> + <%= f.text_field :first_name %> +
+
+ <%= f.label :last_name %> + <%= f.text_field :last_name %> +
+
+ <%= f.submit 'Update Name' %> +
+<% end %> + +<%= form_for @user do |f| %> +
+ <%= f.label :email %> + <%= f.text_field :email %> +
+
+ <%= f.submit 'Update Email' %> +
+<% end %> + +<%= form_for @user do |f| %> +
+ <%= f.label :password %> + <%= f.password_field :password %> +
+
+ <%= f.label :password_confirmation %> + <%= f.password_field :password_confirmation %> +
+
+ <%= f.submit 'Update Password' %> +
+<% end %> diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb index 6b92895..2e5c476 100644 --- a/app/views/users/new.html.erb +++ b/app/views/users/new.html.erb @@ -1,27 +1,27 @@

Sign Up

-<%= form_for @user do |form| %> +<%= form_for @user do |f| %>
- <%= form.label :first_name %> - <%= form.text_field :first_name %> + <%= f.label :first_name %> + <%= f.text_field :first_name %>
- <%= form.label :last_name %> - <%= form.text_field :last_name %> -
+ <%= f.label :last_name %> + <%= f.text_field :last_name %> +
- <%= form.label :email %> - <%= form.text_field :email %> + <%= f.label :email %> + <%= f.text_field :email %>
- <%= form.label :password %> - <%= form.password_field :password %> + <%= f.label :password %> + <%= f.password_field :password %>
- <%= form.label :password_confirmation %> - <%= form.password_field :password_confirmation %> + <%= f.label :password_confirmation %> + <%= f.password_field :password_confirmation %>
- <%= form.submit %> + <%= f.submit %>
<% end %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index f8c1bb1..8d024d5 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -1,3 +1,9 @@ Name: <%= "#{@user.first_name} #{@user.last_name}" %>
-Email: <%= @user.email %> \ No newline at end of file +Email: <%= @user.email %> +
+ +<% if authorized_user(@user) %> + <%= link_to 'Update Your Information', edit_user_path(@user.id) %> +<% end %> +<%= link_to 'Back', dashboard_path %> diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb index 7f0ca59..b511eb2 100644 --- a/app/views/welcome/index.html.erb +++ b/app/views/welcome/index.html.erb @@ -1,11 +1,3 @@

Welcome to Secret Santa

- -<% if current_user%> - <%= "Welcome, #{current_user.first_name || current_user.email}." %> - <%= link_to 'Sign Out', logout_path, method: :delete %> -
- <%= link_to 'Profile', profile_path %> -<% else %> - <%= link_to 'Log In', login_path %> or - <%= link_to 'Sign Up', signup_path %> -<% end %> +<%= link_to 'Log In', login_path %> or +<%= link_to 'Sign Up', signup_path %> diff --git a/config/routes.rb b/config/routes.rb index 92725e8..969dbd1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,11 +7,15 @@ # note Rails has a helper for the above "root" path: root to: 'welcome#index' # to see all routes and connections to controllers, run `rails routes` Rake task + get '/dashboard' => 'dashboard#show', as: 'dashboard' + get '/signup' => 'users#new', as: 'signup' - get '/profile' => 'users#show', as: 'profile' + get '/profile(/:id)' => 'users#show', as: 'profile' get '/login' => 'sessions#new', as: 'login' delete '/logout' => 'sessions#destroy', as: 'logout' - resources :users, only: [:create] + resources :users, only: [:create, :edit, :update] + resources :groups + resources :sessions, except: [:edit, :update] end diff --git a/db/migrate/20180828043741_create_groups.rb b/db/migrate/20180828043741_create_groups.rb new file mode 100644 index 0000000..7c59732 --- /dev/null +++ b/db/migrate/20180828043741_create_groups.rb @@ -0,0 +1,7 @@ +class CreateGroups < ActiveRecord::Migration[5.2] + def change + create_table :groups do |t| + t.text :name + end + end +end diff --git a/db/migrate/20180828043756_create_user_groups.rb b/db/migrate/20180828043756_create_user_groups.rb new file mode 100644 index 0000000..b9a21ac --- /dev/null +++ b/db/migrate/20180828043756_create_user_groups.rb @@ -0,0 +1,8 @@ +class CreateUserGroups < ActiveRecord::Migration[5.2] + def change + create_table :user_groups do |t| + t.integer :user_id, foreign_key: true, index: true + t.integer :group_id, foreign_key: true, index: true + end + end +end diff --git a/db/migrate/20180928203618_add_description_to_groups.rb b/db/migrate/20180928203618_add_description_to_groups.rb new file mode 100644 index 0000000..6ffbdc9 --- /dev/null +++ b/db/migrate/20180928203618_add_description_to_groups.rb @@ -0,0 +1,5 @@ +class AddDescriptionToGroups < ActiveRecord::Migration[5.2] + def change + add_column :groups, :description, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 5f9ff07..bc39f68 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,23 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2018_07_21_200244) do +ActiveRecord::Schema.define(version: 2018_09_28_203618) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "groups", force: :cascade do |t| + t.text "name" + t.string "description" + end + + create_table "user_groups", force: :cascade do |t| + t.integer "user_id" + t.integer "group_id" + t.index ["group_id"], name: "index_user_groups_on_group_id" + t.index ["user_id"], name: "index_user_groups_on_user_id" + end + create_table "users", force: :cascade do |t| t.string "first_name" t.string "last_name" diff --git a/spec/features/users/user_can_signup_spec.rb b/spec/features/users/user_can_signup_spec.rb index 29a6883..ab2a02e 100644 --- a/spec/features/users/user_can_signup_spec.rb +++ b/spec/features/users/user_can_signup_spec.rb @@ -18,7 +18,7 @@ fill_in('password', with: 'passpass') click_on 'Log In' - expect(current_path).to eq root_path + expect(current_path).to eq dashboard_path expect(page).to have_content 'Welcome, Ra.' expect(page).to have_link 'Sign Out' expect(page).to have_link 'Profile' @@ -32,7 +32,7 @@ u = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(u) visit signup_path - expect(current_path).to eq root_path + expect(current_path).to eq dashboard_path end end end