$ cd myapp2
$ rails s -b 0.0.0.0 -p 3000
* In Firefox, I typed: http://localhost:3000/
* I started Brackets and I changed the project folder to myapp2.
* I went to Michael Hartl's Ruby on Rails tutorial. https://www.railstutorial.org/book
* I went to Chapter 10 Updating, showing, and deleting users
* I created a branch called updating-users
$ git checkout -b updating-users
* I changed the heading of the <h2> tag to "Welcome to the myapp2".
myapp2/app/views/static_pages/home.html.erb
<h2 class="tm-gold-text tm-title">Welcome to the myapp2</h2>
* I changed the header of the website to myapp2.
myapp2/app/views/layouts/_header.html.erb
<%= link_to("myapp2", root_path, :class => "navbar-brand tm-site-name") %>
* I copied and pasted the codes in User Controllers and then I made some minor changes to split the name field into first_name and last_name.
myapp2/app/controllers/users_controller.rb
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password,
:password_confirmation)
end
* I created an Edit view file for editing user profile. I copied and pasted the codes and split the name field into first_name and last_name.
myapp2/app/views/users/edit.html.erb
<%= f.label :first_name %>
<%= f.text_field :first_name, class: 'form-control' %>
<%= f.label :last_name %>
<%= f.text_field :last_name, class: 'form-control' %>
* I added the edit_user_path() for the Settings menu in the header.
myapp2/app/views/layouts/_header.html.erb
<li><%= link_to "Settings", edit_user_path(current_user) %></li>
* I generated the Integration Test Suite to test User Edit function.
$ rails generate integration_test users_edit
Running via Spring preloader in process 5208
invoke test_unit
create test/integration/users_edit_test.rb
* I copied and pasted the codes in User Edit Integration Test Suite and I separated the name field into first_name and last_name.
test/integration/users_edit_test.rb
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
def setup
@user = users(:jimmy)
end
test "unsuccessful edit" do
log_in_as(@user)
get edit_user_path(@user)
assert_template 'users/edit'
patch user_path(@user), params: { user: { first_name: "",
last_name: "",
email: "foo@invalid",
password: "foo",
password_confirmation: "bar" } }
assert_template 'users/edit'
end
test "successful edit" do
log_in_as(@user)
get edit_user_path(@user)
assert_template 'users/edit'
firstName = "Foo"
lastName = "Bar"
email = "foo@bar.com"
patch user_path(@user), params: { user: { first_name: firstName,
last_name: lastName,
email: email,
password: "",
password_confirmation: "" } }
assert_not flash.empty?
assert_redirected_to @user
@user.reload
assert_equal firtName, @user.first_name
assert_equal lastName, @user.last_name
assert_equal email, @user.email
end
test "successful edit with friendly forwarding" do
get edit_user_path(@user)
log_in_as(@user)
assert_redirected_to edit_user_url(@user)
firstName = "Foo"
lastName = "Bar"
email = "foo@bar.com"
patch user_path(@user), params: { user: { first_name: firstName,
last_name: lastName,
email: email,
password: "",
password_confirmation: "" } }
assert_not flash.empty?
assert_redirected_to @user
@user.reload
assert_equal firstName, @user.first_name
assert_equal lastName, @user.last_name
assert_equal email, @user.email
end
end
* I edited User Model to allow the allow_nil: true option to validates.
myapp2/app/models/user.rb
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
* I copied and pasted the codes in User Controller Test Suite and separated the name field into first_name and last_name.
myapp2/test/controllers/users_controller_test.rb
test "should redirect update when not logged in" do
patch user_path(@user), params: { user: { first_name: @user.first_name,
last_name: @user.last_name,
email: @user.email } }
assert_not flash.empty?
assert_redirected_to login_url
end
* I copied and pasted the Test Fixture file and I separated the name field into first_name and last_name
myapp2/test/fixtures/users.yml
jimmy:
first_name: Jimmy
last_name: Chong
email: jimmyc5@example.com
password_digest: <%= User.digest('password') %>
michael:
first_name: Michael
last_name: Example
email: michael@example.com
password_digest: <%= User.digest('password') %>
admin: true
archer:
first_name: Sterling
last_name: Archer
email: duchess@example.com
password_digest: <%= User.digest('password') %>
lana:
first_name: Lana
last_name: Kane
email: hands@example.com
password_digest: <%= User.digest('password') %>
malory:
first_name: Malory
last_name: Archer
email: boss@example.com
password_digest: <%= User.digest('password') %>
<% 30.times do |n| %>
user_<%= n %>:
first_name: <%= "User.first_name #{n}" %>
last_name: <%= "User.last_name #{n}" %>
email: <%= "user-#{n}@example.com" %>
password_digest: <%= User.digest('password') %>
<% end %>
* In the Session Helper class, I copied the def current_user?(user) and def redirect_back_or(default) actions.
myapp2/app/helpers/sessions_helper.rb
# Returns true if the given user is the current user.
def current_user?(user)
user == current_user
end
# Redirects to stored location (or to the default).
def redirect_back_or(default)
redirect_to(session[:forwarding_url] || default)
session.delete(:forwarding_url)
end
* One more action called def store_location was copied to Session Helper
myapp2/app/helpers/sessions_helper.rb
# Stores the URL trying to be accessed.
def store_location
session[:forwarding_url] = request.original_url if request.get?
end
* In Session Controller, I updated the action to redirect_back_or user for friendly forwarding.
myapp2/app/controllers/sessions_controller.rb
redirect_back_or user
* I created and copied the codes in User Index file index.html.erb for listing out all users.
myapp2/app/views/users/index.html.erb
<% provide(:title, 'All users') %>
<h1>All users</h1>
<%= will_paginate %>
<ul class="users">
<%= render @users %>
</ul>
<%= will_paginate %>
* I copied and pasted the codes in users_helper.rb for Gravatars.
app/helpers/users_helper.rb
module UsersHelper
# Returns the Gravatar for the given user.
def gravatar_for(user, options = { size: 80 })
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
size = options[:size]
gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
image_tag(gravatar_url, alt: user.first_name, class: "gravatar")
end
end
* Also, I defined the formatting and style for the .user class when listing out all users.
myapp2/app/assets/stylesheets/templatemo-style.css
/* Users index */
.users {
list-style: none;
margin: 0;
li {
overflow: auto;
padding: 10px 0;
border-bottom: 1px solid $gray-lighter;
}
}
* I assigned the user_path for the Users menu in the Header.
myapp2/app/views/layouts/_header.html.erb
<li class="nav-item"><%= link_to "Users", users_path, class: "nav-link" %></li>
* I added 'faker', 'will_paginate', and 'bootstrap-will_paginate' in the Gemfile.
myapp2/Gemfile
# faker for creating sample users for testing
gem 'faker', '1.7.3'
# For pagination
gem 'will_paginate', '3.1.5'
gem 'bootstrap-will_paginate', '1.0.0'
* Then, I ran bundle install.
$ bundle install
* I copied and pasted a program for seeding the database with sample users. I also separated and first_name and last_name field.
myapp2/db/seeds.rb
User.create!(first_name: "Example",
last_name: "User",
email: "example@railstutorial.org",
password: "foobar",
password_confirmation: "foobar")
99.times do |n|
firstName = Faker::Name.first_name
lastName = Faker::Name.last_name
email = "example-#{n+1}@railstutorial.org"
password = "password"
User.create!(first_name: firstName,
last_name: lastName,
email: email,
password: password,
password_confirmation: password)
end
* After I had saved the seeds.rb file, I reset the database and then invoked the Rake task using db:seed
$ rails db:migrate:reset
$ rails db:seed
* I created a partial file to render a user.
myapp2/app/views/users/_user.html.erb
<li>
<%= gravatar_for user, size: 50 %>
<%= link_to user.name, user %>
</li>
* After I had run bundle install, I found Gem Faker was working, but Gem paginate wasn't. So, I re-started the Rails server.
Keyboard: Ctrl + C
$ rails s -b 0.0.0.0 -p 3000
* In the User View Partial file, I forgot to separate the first_name and last_name fields. I re-wrote it to match my data model.
myapp2/app/views/users/_user.html.erb
<li>
<%= gravatar_for user, size: 50 %>
<%= link_to user.first_name, user %>
</li>
* I generated an Integration Test for user_index to test users are listed out properly.
$ rails generate integration_test users_index
Running via Spring preloader in process 7001
invoke test_unit
create test/integration/users_index_test.rb
* I copied and pasted the code in User Index Integration Test Suite. As of the time being, I only verified the first_name field.
myapp2/test/integration/users_index_test.rb
require 'test_helper'
class UsersIndexTest < ActionDispatch::IntegrationTest
def setup
@admin = users(:michael)
@non_admin = users(:archer)
end
test "index including pagination" do
log_in_as(@non_admin)
get users_path
assert_template 'users/index'
assert_select 'div.pagination', count: 2
User.paginate(page: 1).each do |user|
assert_select 'a[href=?]', user_path(user), text: user.first_name
end
end
test "index as admin including pagination and delete links" do
log_in_as(@admin)
get users_path
assert_template 'users/index'
assert_select 'div.pagination'
first_page_of_users = User.paginate(page: 1)
first_page_of_users.each do |user|
assert_select 'a[href=?]', user_path(user), text: user.first_name
unless user == @admin
assert_select 'a[href=?]', user_path(user), text: 'delete'
end
end
assert_difference 'User.count', -1 do
delete user_path(@non_admin)
end
end
test "index as non-admin" do
log_in_as(@non_admin)
get users_path
assert_select 'a', text: 'delete', count: 0
end
end
* I added the admin column for the User model to specify a user with admin privilege.
$ rails generate migration add_admin_to_users admin:boolean
Running via Spring preloader in process 7098
invoke active_record
create db/migrate/20170717004219_add_admin_to_users.rb
* I added default: false for the admin column.
myapp2/db/migrate
class AddAdminToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :admin, :boolean, default: false
end
end
* Then, I ran DB migrate.
$ rails db:migrate
== 20170717004219 AddAdminToUsers: migrating ==================================
-- add_column(:users, :admin, :boolean, {:default=>false})
-> 0.0056s
== 20170717004219 AddAdminToUsers: migrated (0.0064s) =========================
* I added admin: true for the Example User.
myapp2/db/seeds.rb
User.create!(first_name: "Example",
last_name: "User",
email: "example@railstutorial.org",
password: "foobar",
password_confirmation: "foobar",
admin: true)
* Then, I reset the database and re-did the database seeding.
$ rails db:migrate:reset
$ rails db:seed
* Then, I added the delete links in the user views that is only accessible by admin.
myapp2/app/views/users/_user.html.erb
<li>
<%= gravatar_for user, size: 50 %>
<%= link_to user.first_name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
</li>
* When I ran a test, there were error of
Error:
UsersIndexTest#test_index_including_pagination:
ActionView::Template::Error: Undefined variable: "$gray-lighter".
app/views/layouts/application.html.erb:6:in `_app_views_layouts_application_html_erb__254424222595337930_47226138909680'
test/integration/users_index_test.rb:12:in `block in <class:UsersIndexTest>'
* Later, I found it Undefined variable: "$gray-lighter" is in the CSS style.
app/assets/stytlesheets/templatemo-style.css
.users {
list-style: none;
margin: 0;
li {
overflow: auto;
padding: 10px 0;
/* border-bottom: 1px solid $gray-lighter; */
border-bottom: 1px solid;
}
* There were 2 failures that 'div.pagination' could not be found.
$ rails test
Running via Spring preloader in process 7821
Run options: --seed 37045
# Running:
........F
Failure:
UsersIndexTest#test_index_as_admin_including_pagination_and_delete_links [/home/jimmyc/myapp2/test/integration/users_index_test.rb:24]:
Expected at least 1 element matching "div.pagination", found 0..
Expected 0 to be >= 1.
bin/rails test test/integration/users_index_test.rb:20
F
Failure:
UsersIndexTest#test_index_including_pagination [/home/jimmyc/myapp2/test/integration/users_index_test.rb:14]:
Expected exactly 2 elements matching "div.pagination", found 0..
Expected: 2
Actual: 0
bin/rails test test/integration/users_index_test.rb:10
..................................
Finished in 2.308248s, 19.0621 runs/s, 45.9223 assertions/s.
44 runs, 106 assertions, 2 failures, 0 errors, 0 skips
* As I check the HTML file (in Firefox -> Ctrl + U), I saw that there were some odd with the pagination. One is
<div class="pagination"><ul class="pagination">
* Then, I started the server instance of Michael Hartl's original sample_app. I found that the patterns were just the same...
<div class="pagination"><ul class="pagination">
* I made some editing and this was the final version of the fixture file for Users.yml
myapp2/test/fixtures/users.yml
malory:
first_name: Malory
last_name: Archer
email: boss@example.com
password_digest: <%= User.digest('password') %>
<% 30.times do |n| %>
user_<%= n %>:
first_name: <%= "User #{n}" %>
last_name: <%= "User #{n}" %>
email: <%= "user-#{n}@example.com" %>
password_digest: <%= User.digest('password') %>
<% end %>
* In _user.html.erb partial file, I concatenated the first_name and last_name of the user.
myapp2/app/views/users/_user.html.erb
<%= link_to user.first_name + " " + user.last_name, user %>
* In User Index Integration Test Suite, I changed the test case to verify a full name that includes first_name and last_name.
myapp2/test/integration/users_index_test.rb
assert_select 'a[href=?]', user_path(user), text: user.first_name + " " + user.last_name
* After all, I ran the test to make sure no failures.
$ rails test
Running via Spring preloader in process 9902
Run options: --seed 41776
# Running:
.................................../home/jimmyc/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/will_paginate-3.1.5/lib/will_paginate/view_helpers/link_renderer.rb:27: warning: constant ::Fixnum is deprecated
/home/jimmyc/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/will_paginate-3.1.5/lib/will_paginate/view_helpers/link_renderer.rb:91: warning: constant ::Fixnum is deprecated
.........
Finished in 2.264808s, 19.4277 runs/s, 85.6585 assertions/s.
44 runs, 194 assertions, 0 failures, 0 errors, 0 skips
* I added all untracked files.
$ git add -A
* I committed the changes and marked it an bootstrap had not been installed.
$ git commit -m "No Boostrap Finish user edit, update, index, and destroy actions"
* I merged it back into Master branch.
$ git checkout master
$ git merge updating-users
* Lastly, I pushed it onto Github (https://github.com/jimmy2046/myapp2).
$ git push
it is very excellent blog and useful article thank you for sharing with us , keep posting Ruby on Rails Online Training India
ReplyDelete