YearsController:Class的未定义方法'before_save'是什么意思? before_action

问题描述 投票:0回答:1

错误:undefined method 'before_save' for YearsController:Class Did you mean? before_action

https://guides.rubyonrails.org/active_record_callbacks.html讨论“可能会创建,更新和销毁对象”,如果通过ActiveStorage添加的映像已经存在,请避免该过程,以避免重复。 before_save是可用的回调之一。

rails(6.0.0)。我没有ActiveRecord回调的经验,但是https://api.rubyonrails.org Active Record回调列出了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

很多东西,因为这是我的第一个应用程序,我已经从事了很多年。

ruby-on-rails activerecord callback ruby-on-rails-6 before-save
1个回答
0
投票

好话,你会说回来之前会尝试研究自己。

您缺少的是,某些回调特定于您要对其调用的类的类型。我希望现在对您来说显而易见的是,保存是模型所特有的,并且控制器与它无关(@record.save,还记得吗?)。另一方面,由于控制器具有动作,因此before_actionafter_action是在控制器中使用的。参考:Ruby-on-Rails guides

解决方案:

  1. 由于重复性与模型有关,您应该添加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
  1. 您可以在操作之前检查是否重复,如果在控制器中重复,则可以重定向回去,例如:
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
© www.soinside.com 2019 - 2024. All rights reserved.