質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

530閲覧

NoMethodError in Users#showが解決できません

RThe

総合スコア25

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2020/08/08 02:57

編集2020/08/08 06:40

勤務情報管理アプリを作成しており、
user毎に、ボタンを押すと1ヶ月単位で月が切り替わるカレンダーの表を表示したいのですが
下記のエラーが出ました。
worked_onを入れたらエラーになったので、メソッド定義がされていないのかなと思いますが、
どのように修正すれば良いが、解決策が分からず、足踏みをしている」状態です。

該当するであろうファイルを下記に記載させて頂きます。

大変お手数おかけしますが、術を教えていただけますでしょうか。

*因みに、userとattendanceは1対多の関係です

イメージ説明

○表示したいViewです

rb

1<%= provide(:title,@user.name) %> 2<div> 3 <table class="table table-bordered table-condensed user-table"> 4 <tr> 5 <td> 6 <%= link_to "◀︎" ,user_path(date:@first_day.prev_month), class: "btn btn-primary" %> 7 &nbsp;&nbsp; 8 <%=l(@first_day, format: :middle) %>&nbsp;&nbsp;時間管理表 9 &nbsp;&nbsp; 10 <%= link_to "▶︎",user_path(date: @first_day.next_month), class: "btn btn-primary" %> 11 </td> 12 <td>指定勤務時間:<%= format_basic_info(@user.work_time) %></td> 13 <td colspan="3">基本時間:<%= format_basic_info(@user.basic_time) %></td> 14 <td>初日:<%= l(@first_day, format: :short) %></td> 15 </tr> 16 <tr> 17 <td>所属:<%= @user.department.present? ? @user.department : "未所属" %></td> 18 <td>名前:<%= @user.name %></td> 19 <td>コード</td> 20 <td></td> 21 <td>出勤日数</td> 22 <td>締め: <%= l(@last_day,format: :short)%></td> 23 </tr> 24 </table> 25</div> 26 <%= link_to "勤怠を編集", attendances_edit_one_month_user_path(date: @first_day), class: "btn btn-primary" %> 27<div> 28 <table class="table table-bordered table-condensd table-hover" id="table-attendances"> 29 <thead> 30 <tr> 31 <th rowspan="2">日付</th> 32 <th rowspan="2">曜日</th> 33 <th colspan="3">出社</th> 34 <th colspan="3">退社</th> 35 <th rowspan="2">在社時間</th> 36 <th rowspan="2">備考</th> 37 </tr> 38 <tr> 39 <th></th> 40 <th></th> 41 <th></th> 42 <th></th> 43 <th></th> 44 <th></th> 45 </tr> 46 </thead> 47 <tbody class="line"> 48 <% (@first_day..@last_day).each do |day| %> 49 <tr> 50 <td><%= l(day.worked_on, format: :short) %></td> 51 <td><%= $days_of_the_week[day.worked_on.wday] %></td> 52 <td></td> 53 <td></td> 54 <td></td> 55 <td></td> 56 <td></td> 57 <td></td> 58 <td></td> 59 <td></td> 60 </tr> 61 <% end %> 62 </tr> 63 </tbody> 64 </table> 65</div>

○コントローラです

rb

1class UsersController < ApplicationController 2 before_action :set_user,only:[:show, :edit,:update,:edit_basic_info,:update_basic_info] 3 before_action :logged_in_user,only: [:index,:index, :edit, :update] 4 before_action :correct_user,only:[:edit, :update] 5 before_action :admin_user, only: [:destroy, :edit_basic_info, :update_basic_info] 6 before_action :set_one_month,only: :show 7 8 def index 9 @users = User.paginate(page: params[:page]) 10 end 11 12 def new 13 @user = User.new 14 end 15 16 def show 17 end 18 19 def create 20 if @user.save 21 log_in @user # 保存成功後、ログインします。 22 flash[:success] = '新規作成に成功しました。' 23 redirect_to @user 24 else 25 render :new 26 end 27 end 28 29 30 def edit 31 end 32 33 def update 34 if @user.update_attributes(user_params) 35 flash[:success] = "ユーザー情報を更新しました。" 36 redirect_to @user 37 else 38 render :edit 39 end 40 end 41 42 def edit_basic_info 43 end 44 45 46 def update_basic_info 47 if @user.update_attributes(basic_info_params) 48 flash[:success] = "更新に成功しました" 49 else 50 flash[:danger] = "更新は失敗しました。" + @user.errors.full_messages.join("<br>") 51 end 52 redirect_to @user 53 end 54 55 56 57 58private 59 60 def user_params 61 params.require(:user).permit(:name, :email, :department, :password, :password_Confirmation) 62 end 63 64 def basic_info_params 65 params.require(:user).permit(:basic_time, :work_time) 66 end 67 68 69 70end

○before_actionを記載した共通のコントローラです

rb

1class ApplicationController < ActionController::Base 2 protect_from_forgery with: :exception 3 include SessionsHelper 4 5 $days_of_the_week = %w{日 月 火 水 木 金 土} 6 7 def set_user 8 @user = User.find(params[:id]) 9 end 10 11 12 def logged_in_user 13 unless logged_in? 14 store_location 15 flash[:danger] = "ログインしてください。" 16 redirect_to login_url 17 end 18 end 19 20 def correct_user 21 redirect_to(root_url) unless current_user?(@user) 22 end 23 24 def admin_user 25 redirect_to root_url unless current_user.admin? 26 end 27 28 29 30 31 def set_one_month 32 @first_day = params[:date].nil?? 33 Date.current.beginning_of_month : params[:date].to_date 34 @last_day = @first_day.end_of_month 35 one_month = [*@first_day..@last_day] 36 37 @attendances = @user.attendances.where(worked_on: @first_day..@last_day).order(:worked_on) 38 39 unless one_month.count == @attendances.count 40 ActiveRecord::Base.transaction do 41 42 one_month.each { |day| @user.attendances.create!(worked_on: day) } 43 end 44 @attendannces = @user.attendances.where(worked_on: @first_day..@last_day).order(:worked_on) 45 end 46 47 rescue ActiveRecord::RecordInvalid 48 49 flash[:danger] = "ページ情報の取得に失敗しました、再アクセスしてください。" 50 redirect_to root_url 51 end 52end 53

○ルーティングです

rb

1Rails.application.routes.draw do 2 get 'attendances/def' 3 4 get 'attendances/edit_one_month' 5 6 root 'static_pages#top' 7# 新規登録 8 get '/signup', to: 'users#new' 9# ログインページ 10 get '/login' , to: 'sessions#new' 11 # ログイン 12 post '/login' , to: 'sessions#create' 13 # ログアウト 14 delete '/logout', to: 'sessions#destroy' 15 16 resources :users do 17 member do 18 19 get 'edit_basic_info' 20 patch 'update_basic_info' 21 # 勤怠編集 22 get 'attendances/edit_one_month' 23 patch 'attendances/update_one_month' 24 end 25 resources :attendances, only: :update 26 end 27end 28

○userのモデルです

rb

1class User < ApplicationRecord 2 # userが消えると子因子として紐づいているattendancesも準じて(dependent)消える 3 has_many :attendances, dependent: :destroy 4 # コールバックメソッドであるbefore_save=保存前、を呼び出す。 5 # これに{ self.email = email.downcase }を渡している。 6 # (ブロックはメアドを小文字にする内かつ、モデルインスタンスの関連データ) 7 attr_accessor :remember_token 8 before_save { self.email = email.downcase } 9 # 文字数制限かつ、空白で保存できない様に検証をかける 10 validates :name, presence: true, length: { maximum: 50 } 11 # formatオプションの引数である正規表記を指定 12 VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+.[a-z]+\z/i 13 # 文字数制限かつ、空白で保存できない様に検証をかける 14 validates :email, presence: true, length: { maximum: 100 }, 15 # メアドがsample@email.comの様な形かを検証(引数にVALID_EMAIL_REGEXを指定) 16 format: { with: VALID_EMAIL_REGEX }, 17 # 同じ値がないかの検証 18 uniqueness: true 19 # 2〜30文字の文字数制限。allow_blankで空の入力はバリデーションをスルー 20 validates :department, length: { in: 2..30 }, allow_blank: true 21 validates :basic_time, presence: true 22 validates :work_time, presence: true 23# password_digestカラムに追加したhas_secure_passwordの機能を利用 24 has_secure_password 25 validates :password, presence: true, length: { minimum: 6 },allow_nil: true 26 27 28# 渡された文字列のハッシュ値を返します。 29 def User.digest(string) 30 cost = 31 if ActiveModel::SecurePassword.min_cost 32 BCrypt::Engine::MIN_COST 33 else 34 BCrypt::Engine.cost 35 end 36 BCrypt::Password.create(string, cost: cost) 37 end 38 39 # ランダムなトークンを返します。 40 def User.new_token 41 SecureRandom.urlsafe_base64 42 end 43 44 45 # 永続セッションのためハッシュ化したトークンをデータベースに記憶します。 46 def remember 47 self.remember_token = User.new_token 48 update_attribute(:remember_digest, User.digest(remember_token)) 49 end 50 51 52 # トークンがダイジェストと一致すればtrueを返します。 53def authenticated?(remember_token) 54 # ダイジェストが存在しない場合はfalseを返して終了します。 55 return false if remember_digest.nil? 56 BCrypt::Password.new(remember_digest).is_password?(remember_token) 57end 58 59 60 # ユーザーのログイン情報を破棄します。 61 def forget 62 update_attribute(:remember_digest, nil) 63 end 64 65 66end

○attendanceのモデルです

rb

1class Attendance < ApplicationRecord 2 # userモデルと1対1の関係を示す 3 belongs_to :user 4 5 validates :worked_on, presence: true 6 validates :note, length: { maximum: 50 } 7 8 # 出勤時間が存在しない場合、退勤時間は無効 9 validate :finished_at_is_invalid_without_a_started_at 10 11 def finished_at_is_invalid_without_a_started_at 12 # 出勤時間がからで退勤時間が存在する場合にエラーを出す 13 errors.add(:started_at, "が必要です") if started_at.blank? && finished_at.present? 14 end 15end 16

○スキーマです

rb

1 2ActiveRecord::Schema.define(version: 20200803060313) do 3 4 create_table "attendances", force: :cascade do |t| 5 t.date "worked_on" 6 t.datetime "started_at" 7 t.datetime "finished_at" 8 t.string "note" 9 t.integer "user_id" 10 t.datetime "created_at", null: false 11 t.datetime "updated_at", null: false 12 t.index ["user_id"], name: "index_attendances_on_user_id" 13 end 14 15 create_table "users", force: :cascade do |t| 16 t.string "name" 17 t.string "email" 18 t.string "department" 19 t.datetime "created_at", null: false 20 t.datetime "updated_at", null: false 21 t.string "password_digest" 22 t.string "remember_digest" 23 t.datetime "basic_time", default: "2020-08-05 23:00:00" 24 t.datetime "work_time", default: "2020-08-05 22:30:00" 25 t.boolean "admin", default: false 26 t.index ["email"], name: "index_users_on_email", unique: true 27 end 28 29end 30

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/08/08 03:01

「day.worked_on」は、何を取得しようとして書いたコードでしょうか?
RThe

2020/08/08 05:46

day.worked_onはuserが個々に持つ月日となります。 1人のuserが持つ勤務日を取得したい状況です。 Viewに記載した<%= l(day.worked_on, format: :short) %>と $days_of_the_week[day.worked_on.wday] %>はworked_on,を取れば表示はできます。
guest

回答1

0

ベストアンサー

day.worked_onはuserが個々に持つ月日となります。

エラーメッセージにも出ているとおり、dayは単なるDate@first_day..@last_dayの間にある1つの日付)ですので、そのようなことはできません。

投稿2020/08/08 05:49

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/08/08 05:50

Userのメソッドは、Userのインスタンスからしか呼べません。 (実現したいこと自体がいまいち見えてこないので、代替案が提案できない感じです)
RThe

2020/08/08 06:30

ご回答ありがとうございます。 そうなのですね。では、worked_on:を使用せず、Userのインスタンスのみで作るしかないのですかね・・・・無知で申し訳ないです。テキストを進めているので、念のため、テキストの画像を載せさせて頂きます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問