ruby
1NoMethodError in UsersController#import 2undefined method `import' for #<Class:0x00007f61f4ba6708> 3Extracted source (around line #18): 416 517 def import 618 User.import(params[:file]) 719 redirect_to user_import_path @user 820 end 921
csv
インポート機能実装中にて上記のエラーから抜け出せず困っている状況です。
【実現したいこと】
・ユーザ一覧に遷移させる際に上記のエラーを吐かれてしまうことの改善。
・undefined method path for nil:NilClass
より、file
メソッドが空であることは読み取れますが、解決方法がわからない状況を脱したい。
・csv機能実装完了。
【試したこと】
・参考記事との照らし合わせとundefined method
とはそもそも一体どういうことを伝えてくれているのかを下記記事より調べました。
・views
のfile_field_tag
のfile
からフォーム(import_users_path
)によりcontroller
のimport
アクションに飛びビューとモデルで処理を分別。←このあたりが怪しい?と思い、いくつかコントローラ(User.import(params[:file])
)とモデル(self.import(file)
)のfile
部分を改修してみましたが、状況は変わらず。
【参考記事】
csvインポート機能実装についての記事
・【Ruby on Rails】CSVインポート
https://qiita.com/seitarooodayo/items/c9d6955a12ca0b1fd1d4
・RailsでCSV/Excel/OpenOfficeのアップロード機能の実装方法
https://ruby-rails.hatenadiary.com/entry/20141120/1416483136
undefined methodについての記事
・Rubyのエラーメッセージundefined methodの解決方法【初心者向け】
https://techacademy.jp/magazine/19776
nil:NilClassについての記事
・nil:NilClassの「NoMethodError」への対処方法
https://www.ryotaku.com/entry/2019/02/18/231458
大変、初歩的な部分かと思われます。
ただただ、自分の力不足が露呈されていますが調べど解決に至れず、お力をお貸しいただきたくご質問させていただきました。
是非、勉強させていただけますと幸いです。
【routes.rb】
ruby
1resources :users do 2 collection { post :import } 3 get 'import', to: 'users#import' 4 get 'index_attendance', to: 'users#index_attendance' 5 member do 6 get 'edit_basic_info' 7 patch 'update_basic_info' 8 get 'attendances/edit_one_month' 9 patch 'attendances/update_one_month' 10 get 'attendances/edit_overtime_app' 11 patch 'attendances/update_over_app' 12 end 13 resources :attendances, only: :update 14 end
【users.rb】
ruby
1class User < ApplicationRecord 2 has_many :attendances, dependent: :destroy 3 attr_accessor :remember_token 4 before_save { self.email = email.downcase } 5 validates :name, presence: true, length: { maximum: 50 } 6 VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+.[a-z]+\z/i 7 validates :email, presence: true, length: { maximum: 100 }, format: { with: VALID_EMAIL_REGEX }, 8 uniqueness: true 9 has_secure_password 10 validates :password, presence: true, length: { minimum: 6 }, allow_nil: true 11 validates :affiliation, length: { in: 2..30 }, allow_blank: true 12 validates :basic_work_time, presence: true 13 validates :work_time, presence: true 14 15 def User.digest(string) 16 cost = 17 if ActiveModel::SecurePassword.min_cost 18 BCrypt::Engine::MIN_COST 19 else 20 BCrypt::Engine.cost 21 end 22 BCrypt::Password.create(string, cost: cost) 23 end 24 25 def User.new_token 26 SecureRandom.urlsafe_base64 27 end 28 29 def remember 30 self.remember_token = User.new_token 31 update_attribute(:remember_digest, User.digest(remember_token)) 32 end 33 34 def authenticated?(remember_token) 35 return false if remember_digest.nil? 36 BCrypt::Password.new(remember_digest).is_password?(remember_token) 37 end 38 39 def forget 40 update_attribute(:remember_digest, nil) 41 end 42 43 def self.import(file) 44 CSV.foreach(file.path, headers: true) do |row| 45 # IDが見つかれば、レコードを呼び出し、見つかれなければ、新しく作成 46 user = find_by(id: row["id"]) || new 47 # CSVからデータを取得し、設定する 48 user.attributes = row.to_hash.slice(*updatable_attributes) 49 # 保存する 50 user.save 51 end 52 end 53end
【users_controller.rb 】
ruby
1class UsersController < ApplicationController 2 before_action :set_user, only: [:show, :edit, :update, :destroy, :edit_basic_info, :update_basic_info] 3 before_action :logged_in_user, only: [:index, :show, :edit, :update, :destroy, :edit_basic_info, :update_basic_info] 4 before_action :correct_user, only: [:edit, :update, :edit_basic_info] 5 before_action :admin_user, only: [:index, :destroy, :edit_basic_info, :update_basic_info] 6 before_action :set_one_month, only: :show 7 before_action :admin_or_correct_user, only: :show 8 9 def index 10 if params[:search] 11 @users = User.where('LOWER(name) LIKE ?', "%#{params[:search][:name].downcase}%").paginate(page: params[:page]) 12 else 13 @users = User.paginate(page: params[:page]) 14 end 15 end 16 17 def import 18 User.import(params[:file]) 19 redirect_to user_import_path @user 20 end 21 22 def index_attendance 23 end 24 25 def new 26 @user = User.new 27 end 28 29 def create 30 @user = User.new(user_params) 31 if @user.save 32 log_in @user 33 flash[:success] = '新規作成に成功しました。' 34 redirect_to @user 35 else 36 render :new 37 end 38 end 39 40 def edit 41 end 42 43 def update 44 if @user.update_attributes(user_params) 45 flash[:success] = "ユーザー情報を更新しました。" 46 redirect_to @user 47 else 48 render :edit 49 end 50 end 51 52 def destroy 53 @user.destroy 54 flash[:success] = "#{@user.name}を削除しました。" 55 redirect_to users_url 56 end 57 58 def show 59 @worked_sum = @attendances.where.not(started_at: nil).count 60 end 61 62 def edit_basic_info 63 end 64 65 def update_basic_info 66 if @user.update_attributes(basic_params) 67 flash[:success] = "#{@user.name}の基本情報を更新しました。" 68 else 69 flash[:danger] = "#{@user.name}の更新は失敗しました。<br>" + @user.errors.full_messages.join("<br>") 70 end 71 redirect_to users_url 72 end 73 74 def admin_or_correct_user 75 unless current_user?(@user) || current_user.admin? 76 flash[:danger] = "残念でした!" 77 redirect_to(root_url) 78 end 79 end 80 81 private 82 83 def user_params 84 params.require(:user).permit(:name, :email, :affiliation, :employee_number, :password) 85 end 86 87 def basic_params 88 params.require(:user).permit(:basic_time, :work_time) 89 end 90end
【import.html.erb】
ruby
1<% provide(:title, "ユーザ一覧") %> 2<h1>ユーザ一覧</h1> 3 4<% if flash[:notice] %> 5 <div class="alert alert-info" role="alert"><%= flash[:notice] %></div> 6<% end %> 7 8<div class="csv_holder"> 9 <%= form_tag import_users_path, multipart: true do %> 10 <%= file_field_tag :file %> 11 <%= submit_tag "インポート" %> 12 <% end %> 13</div> 14<div> 15 <p>Example</p> 16</div> 17<% if current_user.admin? %> 18 19 <div class="example"> 20 <div></div> 21 <div> 22 <span>|</span><%= link_to "削除", "#", method: :delete, class: "btn btn-lg, btn-primary btn-delete" %> 23 </div> 24 <div class="edit-csv"> 25 <div><%= link_to "編集", "#", class: "btn btn-lg btn-primary w-10" %></div> 26 </div> 27 </div> 28 29<% end %> 30 31<script type="text/javascript"> 32 function file_selected(file_field){ 33 var filename = $(file_field)[0].files[0].name; 34 $("#filename").val(filename); 35 } 36</script> 37
回答2件
あなたの回答
tips
プレビュー