错误:undefined method 'before_save' for YearsController:Class Did you mean? before_action
https://guides.rubyonrails.org/active_record_callbacks.html 谈到"对象可能会被创建、更新和销毁",如果通过 ActiveStorage 添加的图像已经存在以避免重复,我想中断该过程。before_save
是可用的回调之一。
导轨 (6.0.0(。我对活动记录回调没有经验,但 https://api.rubyonrails.org 活动记录回调列出了before_save
,但没有before_action
。但是before_action.
没有错误,我什至不确定何时需要激活回调,但正在通过有效的方法进行研究。允许哪些回调?不知道before_action
会是什么。
years_controller.rb
class YearsController < ApplicationController
helper_method :sort_column, :sort_direction
before_action :set_year, only: [:show, :edit, :update, :destroy] # 2019.06.20 Can't see that this is being used anywhere
before_action :set_s3_direct_post, only: [:new, :edit, :create, :update]
# before_action :dup_check, only: [:new, :edit, :update] # runs, but not what I think I want
before_save :dup_check, only: [:new, :edit, :update] # undefined method `before_save' for YearsController:Class Did you mean? before_action
PAGE_SIZE = 10
def index
@years = Year.order(sort_column + " " + sort_direction)
respond_to do |format|
format.html {}
format.json { render json: @years }
end
end
def documents
@years = Year.all
end
def map_one # mapping one connection/year
# need to use the year passed in and then make it for a year
years = Year.where( year_date: '1865-01-01' .. '1995-12-31' )
end
def search
# Copeland except within the else
@page = (params[:page] || 0).to_i
if params[:keywords].present?
@keywords = params[:keywords]
year_search_term = YearSearchTerm.new(@keywords)
@years = Year.where(
year_search_term.where_clause,
year_search_term.where_args).
order(year_search_term.order).
offset(PAGE_SIZE * @page).limit(PAGE_SIZE)
else
@years = Year.order(sort_column + " " + sort_direction)
end
respond_to do |format|
format.html {}
format.json { render json: @years }
end
end
def summary
@years = Year.order(:year_date)
respond_to do |format|
format.html {}
format.json { render json: @years }
end
end
def show
end
# GET /years/new
def new
# All from Tutorial Points Tutorial
@year = Year.new({:year_date => "1900-09-01"}) # This is default. Helps to change when going through a group.
@locations = Location.all
@people = Person.all
end
# GET /years/1/edit
def edit
@positions = Position.all # Needed for Positions/ Titles list to work, However not added to database
end
# POST /years
# POST /years.json
def create
@year = Year.new(year_params)
respond_to do |format|
if @year.save
format.html { redirect_to @year, notice: 'Connection was successfully created.' }
format.json { render :show, status: :created, location: @year }
else
format.html { render :new }
format.json { render json: @year.errors, status: :unprocessable_entity }
end
end
repopulateResidResto()
end
# PATCH/PUT /years/1
# PATCH/PUT /years/1.json
def update
respond_to do |format|
if @year.update(year_params)
format.html { redirect_to @year, notice: 'Connection was successfully updated.' }
format.json { render :show, status: :ok, location: @year }
else
format.html { render :edit }
format.json { render json: @year.errors, status: :unprocessable_entity }
end
end
repopulateResidResto() # nice to have some error handling here
end
# DELETE /years/1
# DELETE /years/1.json
def destroy
@year.destroy
respond_to do |format|
format.html { redirect_to years_url, notice: 'Connection was successfully destroyed.' }
format.json { head :no_content }
end
repopulateResidResto()
end
private
# Use callbacks to share common setup or constraints between actions.
def set_year
@year = Year.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def year_params
params.require(:year).permit(:year_date, :person_id, :location_id, :resto, :resto_name, :resid, :title, :source, :source_url, :ref_image, :doc_image , :ref_url, :notes, :ref_url, :caption, documents: []) # document replaces _images, brackets for has many
end
def set_s3_direct_post
@s3_direct_post = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: '201', acl: 'public-read')
end
def dup_check
# if active_storage_blobs(:checksum ) == an existing blob
# let's first run a test seeing if a know checksum exists. That works. Now get the existing checksums
test_checksum = '0M4nc4nuUaVuqo3+sJw+Lg==' # will get for selected image at some point
test_checksum == '0M4nc4nuUaVuqo3+sJw+Lg==' ? (puts "years_controller:158. test_checksum #{test_checksum} does exist") : (puts "years_controller:158. test_checksum #{test_checksum} does not exist") # Need the ()
puts "years_controller:160. dup_check entered via before_action. before_save results in an errro"
end
# NOT CLEAR ANY OF THIS IS NEEDED. BUT PUT IT IN AGAIN WHEN CREATE DIDN'T WORK
def person_params
params.require(:person).permit(:last_name, :given_name, :full_name, :full_name_id)
end
def sort_column
Year.column_names.include?(params[:sort]) ? params[:sort] : "year_date" # it does matter what this last field is.
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
end
year.rb
class Year < ApplicationRecord
belongs_to :location
belongs_to :person
has_many :resto_resid_lines
has_many_attached :documents # ActiveStorage
has_rich_text :caption # ActionText 2019.12.05 not implemented because form needs major changes to work
scope :with_eager_loaded_documents, -> { eager_load(documents_attachments: :blob) }
default_scope -> { order(:year_date) }
validates :person_id, presence: true
validates :location_id, presence: true
validates_presence_of :resto, {:if => :resto_name?, message: 'Click on Restaurant (above) since a restaurant name has been selected' }
validates :resto, :presence => { :if => :resto_name?, message: 'Select Restaurant since a restaurant name has been specified' } # is this the same as above, but not working?
def self.search(search)
where("year_date ILIKE ? OR resto ILIKE ? OR resto_name ILIKE ? OR resid ILIKE ? OR title ILIKE ? OR source ILIKE ? OR source_url ILIKE ? OR ref_url ILIKE ? OR notes ?", "%#{search}%", "%#{search}%", "%#{search}%", "%#{search}%", "%#{search}%", "%#{search}%", "%#{search}%", "%#{search}%", "%#{search}%")
end
def map_popup
"#{person.given_name} #{person.last_name} was a #{title} at #{location.address} in #{year_date.to_formatted_s(:month_year)}"
end
def next
Year.where("id > ? AND year_date = ?", id, year_date).first
end
def previous
Year.where("id < ? AND year_date = ?", id, year_date).last
end
private
def resid_xor_resid
if [resto, resid].compact.count != 1
errors.add(:base, "Select Residence or Restaurant, but not both")
end
end
end
很多麻烦,因为这是我的第一个应用程序,我已经工作了多年。
还好你说你会在回来之前尝试研究自己。
您缺少的是某些回调特定于您调用它们的类类型。我希望您现在很清楚,保存是模型特有的东西,控制器与它无关(@record.save
,还记得吗?另一方面,before_action
和after_action
是控制器中使用的,因为控制器具有操作。参考:边栏边拼音指南
溶液:
- 由于重复性与模型有关,因此您应该向模型添加before_save或before_create(我猜已弃用(而不是第二个解决方案:
class Year < ApplicationRecord
before_save :is_duplicate?
private
def is_duplicate
return Year.where([the_attributes_that_make_it_duplicate]).present? # or something like that :P
# throw :abort or return false (I guess you can't through in this case)
end
end
- 您可以在操作前检查重复性,如果控制器中重复,则重定向回来,例如:
class YearsController < ApplicationController
before_action :dup_check
private
def dup_check
set_year
redirect_to your_desired_path if Year.where([the_attributes_that_make_it_duplicate]).present?
end
end