静的なページ作成からユーザー登録までの復習 | rails チュートリアル 14

Ruby on Rails チュートリアル:実例を使って Rails を学ぼう第3章 ほぼ静的なページの作成から第7章 ユーザー登録までの復習のメモです。

2章までの復習

3章よりも前の段階の復習は0から4までの復習を。

ほぼ静的なページの作成

ここからは、第3章ほぼ静的なページの作成です。

Gemfileの生成

適当な位置にcd コマンドで移動し、Gemfileを作成する。

$ bundle init

上記のコメントを行ったら、以下のようなファイルが作成される

# frozen_string_literal: true
source "https://rubygems.org"

# gem "rails"

末尾のコメントアウト「#」を外し、

# frozen_string_literal: true
source "https://rubygems.org"

gem "rails"

インストールを行う。

$ bundle install --path vendor/bundle

その後、RailsのDBを初めからMySQLに指定してアプリを作成する。

$ bundle exec rails new . -d mysql

Gemfileが更新されるので、それをまた書き直す。

source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

gem 'rails', '~> 5.1.2'
gem 'mysql2', '>= 0.3.18', '< 0.5'
gem 'bcrypt'
gem 'pry-rails'
gem 'puma', '~> 3.7'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'jquery-rails'
gem 'coffee-rails', '~> 4.2'
gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.5'


group :development, :test do
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'capybara', '~> 2.13'
  gem 'selenium-webdriver'
end

group :development do
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

group :test do
  gem 'rails-controller-testing'
  gem 'minitest-reporters'
  gem 'guard'
  gem 'guard-minitest'
end

group :production do
  gem 'pg'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

その後、またインストール

$ bundle install --without production

DBと連携

以下のファイルの、「username」と「password」を修正します。

username:'ユーザー名'
password:'パスワード'

その後、DBを作成します。

$ bundle exec rails db:create

サーバーの立ち上げ

ひとまず、ここまでを確認するために、サーバーを立ち上げてみる。

$ bundle exec rails s
# すでにほかが動いていたら、違うポートで立ち上げるのも可
# $ bundle exec rails s -p 3001

http://localhost:3000/が見れたら、OK

herokuにup

後でproduction環境にプッシュするときに悩まずに済むよう、アプリをなるべく早い段階でHerokuにデプロイします。

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def hello
    render html: "hello, world!"
  end
end
Rails.application.routes.draw do
  root 'application#hello'
end

上記、2つのファイルを修正し、

$ git add .
$ git c "Add hello"
# heroku環境を作成
$ heroku create 'アプリ名'

# herokuにpush
$ git push heroku master

# 今後 migrateしたいときは
$ heroku run rails db:migrate
# herokuのviewを見たいときは、
$ heroku open

ここで、「heroku open」をして、
hello, world!
が現れれば、OK!

静的なページの生成

generateコマンドで、home、helpのアクション名がついた static_pages_controller.rbを作成します。

$ bundle exec rails generate controller StaticPages home help
Running via Spring preloader in process 67790
      create  app/controllers/static_pages_controller.rb
       route  get 'static_pages/help'
       route  get 'static_pages/home'
      invoke  erb
      create    app/views/static_pages
      create    app/views/static_pages/home.html.erb
      create    app/views/static_pages/help.html.erb
      invoke  test_unit
      create    test/controllers/static_pages_controller_test.rb
      invoke  helper
      create    app/helpers/static_pages_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/static_pages.coffee
      invoke    scss
      create      app/assets/stylesheets/static_pages.scss

ちなみに、実行と取り消しの幾つかの方法は以下のようなコマンドでそれぞれ実行可能です。

# コントローラーの作成と取り消し
$ bundle exec rails generate controller StaticPages home help
$ rails destroy  controller StaticPages home help

# モデルの作成と取り消し
$ bundle exec rails generate model User name:string email:string
$ bundle exec rails destroy model User

# マイグレートの実行と取り消し
$ bundle exec rails db:migrate
$ bundle exec rails db:rollback

コントローラーを作成しおえたら、routes.rbを確認します。
改行はついでに削除しておきます。

Rails.application.routes.draw do
  get 'static_pages/home'
  get 'static_pages/help'
  root 'application#hello'
end

テストから始める

テストとは、http://railsdoc.com/testによると、

説明
あるURLにアクセスした際に、予期した画面が表示されるか
ある正しい操作をした際に、アプリケーションの状態が正しく変更されるか
ある正しくない操作をした際に、適切なエラーメッセージが表示されるか

単体テスト
モデルの検索系メソッドが正しい値を取得できるか
モデルの更新系メソッドが正しくデータベースを更新できるか
モデルの更新系メソッドが不正な入力に対して、適切なエラーを発生させるか

機能テスト
適切なテンプレートが選択されているか
インスタンス変数に適切な値が格納されているか
適切にレンダリングされているか
更新系のアクションが正しくデータベースを更新されるか

総合テスト
ログインして、新しいメンバーを追加して、ログアウトするといった一連の動きをテスト

といったことを指す。

今は、先程、自動で生成された、static_pages_controller_test.rbのファイルを確認して、テストを行う。

require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  test "should get home" do
    get static_pages_home_url
    assert_response :success
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
  end

end

テストを実行するには、以下のコマンドで可能。

$ bundle exec rails test
.
.
.
# Running:
..

Finished in 0.459343s, 4.3540 runs/s, 4.3540 assertions/s.
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips

失敗する例をみるために、static_pages_controller_test.rbに追記します。

require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
.
.
.
  test "should get about" do
    get static_pages_about_url
    assert_response :success
  end

end

すると、以下のようなlogが出る。

$ bundle exec rails test
.
.
.
Error:
StaticPagesControllerTest#test_should_get_about:
NameError: undefined local variable or method `static_pages_about_url' for #<StaticPagesControllerTest:0x007faa31fdcbf8>
    test/controllers/static_pages_controller_test.rb:15:in `block in <class:StaticPagesControllerTest>'

bin/rails test test/controllers/static_pages_controller_test.rb:14
.
Finished in 0.418257s, 7.1726 runs/s, 4.7817 assertions/s.
3 runs, 2 assertions, 0 failures, 1 errors, 0 skips

これを解決するために、routeや、controller、html.erbなどを修正、作成しておきます。

少しだけ動的なページ

titleを、すこしだけ動的にしていきます。

view/static_pages/○○.html.erbのそれぞれの先頭に

<% provide(:title, "○○") %>

を追記し、application.html.erbを修正する。

<title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>

home.html.erbをrootに設定する。

Rails.application.routes.draw do
  root 'static_pages#home'
  get 'static_pages/home'
  get 'static_pages/help'
  get  'static_pages/about'
  # root 'application#hello'
end

testも書き換えておく

require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

  test "should get root" do
    get root_url
    assert_response :success
  end

  test "should get home" do
    get static_pages_home_url
    assert_response :success
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
  end

  test "should get about" do
    get static_pages_about_url
    assert_response :success
  end

end

textを見やすくする

test_helper.rbを修正

require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/reporters"
Minitest::Reporters.use!

class ActiveSupport::TestCase
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all

  # Add more helper methods to be used by all tests here...
end

Guardによるテストの自動化するために、いろいろやる。

$ bundle exec guard init

Guardfileを修正。

# guard :minitest do
guard :minitest, spring: "bin/rails test", all_on_start: false do

.gitignoreを修正に追記。

# Ignore Spring files.
/spring/*.pid

ここまで、行うと、

# 新しいターミナルを開き、cdで移動した後、
$ bundle exec guard
# その後、Returnキー
# Guardを終了するにはCtrl-Dキーでできる。

Rails風味のRuby

ここからは、第4章Rails風味のRubyです。

helperを修正していきます。

module ApplicationHelper
  # ページごとの完全なタイトルを返します。
  def full_title(page_title = '')
    base_title = "Ruby on Rails Tutorial Sample App"
    if page_title.empty?
      base_title
    else
      page_title + " | " + base_title
    end
  end
end

application.html.erbを修正する。

<title><%= full_title(yield(:title)) %></title>

home.html.erbとstatic_pages_controller_test.rbを修正しておく。

<% provide(:title, "Home") %>
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Ruby on Rails Tutorial Sample App"
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
    assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
  end

  test "should get about" do
    get static_pages_about_url
    assert_response :success
    assert_select "title", "About | Ruby on Rails Tutorial Sample App"
  end
end

レイアウトを作成する

ここからは、第5章レイアウトを作成するです。

ルートや、コントローラーなどを修正します。

Rails.application.routes.draw do
  root 'static_pages#home'
  get '/help', to: 'static_pages#help'
  get '/about', to: 'static_pages#about'
  get '/contact', to: 'static_pages#contact'
end
class StaticPagesController < ApplicationController
  def home
  end

  def help
  end

  def about
  end

  def contact
  end
end
<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= csrf_meta_tags %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= render '_parts/global/header' %>

    <%= render '/_parts/global/flash' %>

    <%= yield %>

    <%= render '_parts/global/footer' %>

    <%= debug(params) if Rails.env.development? %>
  </body>
</html>

renderで、headerパーシャルなどを読み込むようにする。

scssを使う

別途作成した、master.scssを今後触っていくようにしたいため、修正する。

/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= # require_tree .
 *= require_self
 *= require ./scss/master.scss
 */

ユーザー登録

あたらしくcontrollerなどを作成する。

$ bundle exec rails generate controller Users new
Running via Spring preloader in process 69546
      create  app/controllers/users_controller.rb
       route  get 'users/new'
      invoke  erb
      create    app/views/users
      create    app/views/users/new.html.erb
      invoke  test_unit
      create    test/controllers/users_controller_test.rb
      invoke  helper
      create    app/helpers/users_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users.coffee
      invoke    scss
      create      app/assets/stylesheets/users.scss

その後、routes.rbを修正

Rails.application.routes.draw do
  root 'static_pages#home'
  get '/help', to: 'static_pages#help'
  get '/about', to: 'static_pages#about'
  get '/contact', to: 'static_pages#contact'
  get  '/signup',  to: 'users#new'
  post '/signup',  to: 'users#create'
end

home.html.erbを適当に修正

<div class="ta_center">
<br>
<br>
<br>
  <h1>StaticPages#home</h1>
  <p>Find me in app/views/static_pages/home.html.erb</p>
  <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
<br>
<br>
<br>
</div>

users/new.html.erbもすこしだけ修正

<% provide(:title, 'Sign up') %>
<div class="ta_center">
<br>
<br>
<br>
  <h1>Sign up</h1>
  <p>This will be a signup page for new users.</p>
<br>
<br>
<br>
</div>

ひとまず、ここでherokuにpushする。

$ git push heroku master

第6章ユーザーのモデルを作成する

ここからは、第6章ユーザーのモデルを作成するです。

modelを作成する。

以下のコマンドで、modelを作成する。

$ bundle exec rails generate model User name:string email:string
Running via Spring preloader in process 69854
      invoke  active_record
      create    db/migrate/20170717230314_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml

# controller作成はこっち
# bundle exec rails generate controller Users new

その後、user.rbを修正

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end

その後、migrateする

$ bundle exec rails db:migrate

models/user.rbを追記して、文字数制限や、メルアドの制限をする。

class User < ApplicationRecord
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
end

その後、マイグレーションファイルを作成し、マイグレートを行う。

$ bundle exec rails generate migration add_index_to_users_email
$ bundle exec rails db:migrate

メールアドレスの一意性を保証するために、もうすこしmodels/user.rbを修正
また、セキュアなパスワードの実装をするためにhas_secure_passwordというRailsのメソッドを使用する。これを使用するには、'bcrypt'というというが必要です。

class User < ApplicationRecord
  before_save { self.email = email.downcase }
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }
end

その後、マイグレーションファイルを作成し、マイグレートを行う。

$ bundle exec rails generate migration add_password_digest_to_users password_digest:string
$ bundle exec rails db:migrate

ここまで行えば、rails consoleで、以下のようなことが可能。

$ bundle exec rails c
.
.
.
[1] pry(main)> User.create(name: "Michael Hartl", email: "mhartl@example.com",password: "foobar", password_confirmation: "foobar")
   (1.8ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
   (0.5ms)  BEGIN
  User Exists (0.3ms)  SELECT  1 AS one FROM `users` WHERE `users`.`email` = 'mhartl@example.com' LIMIT 1
  SQL (1.0ms)  INSERT INTO `users` (`name`, `email`, `created_at`, `updated_at`, `password_digest`) VALUES ('Michael Hartl', 'mhartl@example.com', '2017-07-17 23:28:01', '2017-07-17 23:28:01', '$2a$10$jPzB5m.BUaw5HJLolc7aWulGSIQ3BrXoKfrNxgzcDhaWT2WT4v79e')
   (0.6ms)  COMMIT
=> #<User:0x007ff27d5796b8
 id: 1,
 name: "Michael Hartl",
 email: "mhartl@example.com",
 created_at: Mon, 17 Jul 2017 23:28:01 UTC +00:00,
 updated_at: Mon, 17 Jul 2017 23:28:01 UTC +00:00,
 password_digest: "$2a$10$jPzB5m.BUaw5HJLolc7aWulGSIQ3BrXoKfrNxgzcDhaWT2WT4v79e">

ちなみに同じものを再びやろうとすると、

[2] pry(main)> User.create(name: "Michael Hartl", email: "mhartl@example.com",password: "foobar", password_confirmation: "foobar")
   (1.3ms)  BEGIN
  User Exists (0.3ms)  SELECT  1 AS one FROM `users` WHERE `users`.`email` = 'mhartl@example.com' LIMIT 1
   (0.2ms)  ROLLBACK
=> #<User:0x007ff27befb210

…ROLLBACKされます。

ユーザー登録

ここからは、第7章ユーザー登録です。

ユーザーページを見れるようにするために、routes.rbに追記

Rails.application.routes.draw do
  root 'static_pages#home'
  get '/help', to: 'static_pages#help'
  get '/about', to: 'static_pages#about'
  get '/contact', to: 'static_pages#contact'
  get '/signup',  to: 'users#new'
  post '/signup',  to: 'users#create'

  resources :users
end

次に、controllerを修正

class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])
  end

  def new
  end
end

html.erbファイルを作成し

$ touch app/views/users/show.html.erb
<div class="ta_center">
<br>
<br>
<br>
  <h1><%= @user.name %></h1>
  <table class="mr_auto ml_auto">

    <tbody>
      <tr>
        <th>メールアドレス</th>
        <td><%= @user.email %></td>
      </tr>
    </tbody>
  </table>
<br>
<br>
<br>
</div>

Gravatar画像

便利なサービスがあるので、使えるようにする。

まず、html.erbを修正

<h1><%= gravatar_for @user %><%= @user.name %></h1>

次にhelper

module UsersHelper

  # 引数で与えられたユーザーのGravatar画像を返す
  def gravatar_for(user, size: 60)
    gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
    gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
    image_tag(gravatar_url, alt: "", class: "")
  end
end

Digest::MD5::hexdigestメソッドは、ランダムなハッシュにしてくれる。

$ bundle exec rails c
[1] pry(main)> email = "MHARTL@example.COM"
=> "MHARTL@example.COM"
[2] pry(main)> Digest::MD5::hexdigest(email.downcase)
=> "1fda4469bcbec3badf5418269ffc5968"
[3] pry(main)> Digest::MD5::hexdigest(em

ユーザー登録フォームの作成

ユーザーが実際にブラウザで登録できるようにしていく

ルーティングでは、

  get  '/signup',  to: 'users#new'
  post '/signup',  to: 'users#create'

というようにしているので、controllerも同じ箇所を修正していく

 

Userの登録なので、フォームタグや、input、User情報を操作するので、@user = User.new でUserオブジェクトを生成などをする。

class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])
    # debugger
  end

  def new
    @user = User.new
  end

end

また、フォームはパーシャル化しておく。

<% provide(:title, 'Sign up') %>
<div class="container">
  <div class="ta_center">
  <br>
  <br>
  <br>
    <h1 class="title_signup">Sign up</h1>
    <p>This will be a signup page for new users.</p>

    <%= render 'form', user: @user %>
  <br>
  <br>
  <br>
  </div>
</div>

renderするファイルを作成。

$ touch app/views/users/_form.html.erb
<%= form_with(model: user, url: signup_path, html: {class: ''}, local: true) do |f| %>
  <table class="mr_auto ml_auto">
    <tr>
      <th><%= f.label :name %></th>
      <td><%= f.text_field :name %></td>
    </tr>
    <tr>
      <th><%= f.label :email %></th>
      <td><%= f.email_field :email %></td>
    </tr>
    <tr>
      <th><%= f.label :password %></th>
      <td><%= f.password_field :password %></td>
    </tr>
    <tr>
      <th><%= f.label :password_confirmation, "Confirmation" %></th>
      <td><%= f.password_field :password_confirmation %></td>
    </tr>
  </table>
  <div>
    <%= f.submit "Create my account", class: "btn btn-primary" %>
  </div>
<% end %>

form_withは、form_forとform_tagが統合されたもの。

<!-- 以下の記述で -->
<%= form_with(model: user, url: signup_path, html: {class: ''}, local: true) do |f| %>

<!-- 以下のようなformタグが生成される。 -->
<form class="" action="/signup" accept-charset="UTF-8" method="post">

エラー時の対応のために、エラー分を表示するパーシャルを作成し、

$ touch app/views/users/_error_messages.html.erb

html.erbに記述する。(ほかにも幾つか記述。)

<%= form_with(model: user, url: signup_path, html: {class: ''}, local: true) do |f| %>

  <%= render 'error_messages' %>

  <table class="mr_auto ml_auto">
    <tr>
      <th><%= f.label :name %></th>
      <td><%= f.text_field :name, class: 'form-control' %></td>
    </tr>
    <tr>
      <th><%= f.label :email %></th>
      <td><%= f.email_field :email, class: 'form-control' %></td>
    </tr>
    <tr>
      <th><%= f.label :password %></th>
      <td><%= f.password_field :password, class: 'form-control' %></td>
    </tr>
    <tr>
      <th><%= f.label :password_confirmation, "Confirmation" %></th>
      <td><%= f.password_field :password_confirmation, class: 'form-control' %></td>
    </tr>
  </table>
  <div>
    <%= f.submit "Create my account", class: "btn btn-primary" %>
  </div>
<% end %>
<% if user.errors.any? %>
  <div id="error_explanation">
    <h2>
        The form contains <%= pluralize(user.errors.count, "error") %>
    </h2>
    <ul>
    <% user.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>

formタグのaction先が、/users。

ルーティングの/usersは、users#createとなっているので、controllerを修正する。

class UsersController < ApplicationController
.
.
.
  def create
    @user = User.new(user_params)
    if @user.save

    else
      render 'new'
    end
  end

  private

    def user_params
      params.require(:user).permit(:name, :email, :password, :password_confirmation)
    end
end

flash

<%- if flash -%>
  <div id="flash" class="container">
    <%- flash.each do |message_type, message |-%>
      <div class="box_flash box_flash_<%= message_type %>"><%= message %></div>
    <%- end #each -%>
  </div>
<%- end #if -%>
class UsersController < ApplicationController
.
.
.
  def create
    @user = User.new(user_params)
    if @user.save
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @user
    else
      render 'new'
    end
  end
end

herokuをsslに

色々手を加えます。

  config.force_ssl = true
  # コメントアウトを外す。
$ touch ./Procfile
web: bundle exec puma -C config/puma.rb

その後、herokuにup

$ git push heroku master

第8章基本的なログイン機構、第9章発展的なログイン機構の復習はまた、次回

メモ form_withの使い方

<%= form_with(local: true) do |f| %> にしないと、うまくいかない。。。うーん

調べよう。

ActionView::Helpers::FormHelperをみると、

:url
:method
:format
:scope
:model
:authenticity_token
:skip_enforcing_utf8
:builder
:data
:local
└By default form submits are remote and unobstrusive XHRs. Disable remote submits with local: true. :id
└Optional HTML id attribute.
:class
└Optional HTML class attribute.
:html
└Other optional HTML attributes for the form tag.

いろいろあるようで、。ここに解説ものっていた。

JavaScript によるフォームの送信 - ウェブ開発を学ぶ | MDNこういうのが絡んでそう。。

コメント

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

内容に問題なければ、下記の「コメントを送信する」ボタンを押してください。


  1. KATOON.NET
  2. TRASH
  3. 静的なページ作成からユーザー登録までの復習 | rails チュートリアル 14