Rails 5 Неверный атрибут объекта при сохранении - PullRequest
0 голосов
/ 18 октября 2018

У меня есть модель поиска с HABTM-связью с моделью Area.

Когда я пытаюсь выполнить поиск, я получаю эту ошибку на localhost: 3000:

    1 error prohibited this search from being saved:
 - Areas is invalid

Соответствующий код из контроллера поиска:

class SearchesController < ApplicationController

  before_action :set_search, only: [:show, :edit, :update, :destroy]
  before_action :require_admin, only: [:index]

def create
    @search = Search.new(search_params)
    @search.max_price = search_params["max_price"].gsub('$', '').gsub(',', '')
    @contact = Contact.new #in case it gets rerouted back to search#new

    respond_to do |format|
      if @search.save 
        if @search.school_slug.present?
          #           # format.html { redirect_to @school(:search_id => @search.id), notice: "#{@school.name} search updated"}
          @school = School.find_by(slug: @search.school_slug)
          p @school.name
          p @school.id
          # format.html { redirect_to @school(:search_id => @search.id), notice: "#{@school.name} search updated"}
          format.html { redirect_to school_path(slug: @school.slug, city: @school.city.parameterize.truncate(80, omission: ''), :search_id => @search.id), notice: "#{@school.name} search updated"}
        else
          format.html { redirect_to @search, notice: 'Search was successfully created.' }
          format.json { render :show, status: :created, location: @search }
        end 
      else
        format.html { render :new }
        format.json { render json: @search.errors.full_messages, status: :unprocessable_entity }
      end
    end
  end

private
    # Use callbacks to share common setup or constraints between actions.
    def set_search
      @search = Search.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def search_params
      params.require(:search).permit(:school_id, :beds, :max_price, :user_id, :name, :district_id, :city_id, :email_me, :rental, :grade, :school_slug, area_ids: [], :prop_type => [])
    end
end

Я попытался создать поиск в консоли с похожим результатом:

irb(main):004:0> a = Search.new(beds: "3", max_price: "450000", area_ids:["1","2"])
  Area Load (0.3ms)  SELECT "areas".* FROM "areas" WHERE "areas"."id" IN (?, ?)  [["id", 1], ["id", 2]]
=> #<Search id: nil, beds: 3, max_price: 450000, prop_type: nil, user_id: nil, name: nil, area_id: nil, school_id: nil, district_id: nil, city_id: nil, email_me: nil, rental: nil, created_at: nil, updated_at: nil, grade: nil, school_slug: nil>
irb(main):005:0> a.areas
=> #<ActiveRecord::Associations::CollectionProxy [#<Area id: 1, name: "N", created_at: "2018-05-24 12:24:16", updated_at: "2018-10-10 16:22:16", msa_id: 1, state_id: nil>, #<Area id: 2, name: "NW", created_at: "2018-05-24 12:24:16", updated_at: "2018-10-10 16:22:16", msa_id: 1, state_id: nil>]>
irb(main):006:0> a.save
   (0.2ms)  begin transaction
  Msa Load (0.5ms)  SELECT  "msas".* FROM "msas" WHERE "msas"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  Msa Load (0.1ms)  SELECT  "msas".* FROM "msas" WHERE "msas"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.2ms)  rollback transaction
=> false
irb(main):007:0> a.errors
=> #<ActiveModel::Errors:0x00007fb245504958 @base=#<Search id: nil, beds: 3, max_price: 450000, prop_type: nil, user_id: nil, name: nil, area_id: nil, school_id: nil, district_id: nil, city_id: nil, email_me: nil, rental: nil, created_at: nil, updated_at: nil, grade: nil, school_slug: nil>, @messages={:areas=>["is invalid"]}, @details={:areas=>[{:error=>:invalid}, {:error=>:invalid}]}>

Я попытался удалить ассоциацию Msa без изменений в ошибке,Я также попытался создать контроллер области и внес в белый список каждый атрибут объекта без изменений в ошибке.

Любая помощь будет принята!

Вот контроллер области и модель для комментария ниже:

class AreasController < ApplicationController

  def index(:msa_id)
    @areas = Area.where(msa_id: params[:msa_id])
  end

  def show
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_area
      @area = Area.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def area_params
      params.require(:area).permit(:name, :msa_id, :state_id, district_ids:[], search_ids:[], county_ids:[])
    end
end

class Area < ApplicationRecord

  has_many :districts
  has_many :counties
  has_and_belongs_to_many :searches
  belongs_to :msa
  belongs_to :state

end

И ниже столбцы базы данных из schema.rb:

create_table "searches", force: :cascade do |t|
    t.integer "beds"
    t.integer "max_price"
    t.string "prop_type"
    t.integer "user_id"
    t.string "name"
    t.integer "area_id"
    t.integer "school_id"
    t.integer "district_id"
    t.integer "city_id"
    t.boolean "email_me"
    t.boolean "rental"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "grade"
    t.string "school_slug"
  end

Модель поиска, добавленная к комментарию ниже:

class Search < ApplicationRecord

  belongs_to :user, optional: true
  has_and_belongs_to_many :areas

end

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Будьте осторожны с отношениями и данными моделей.

Если у модели whatever много things, то модели должны выглядеть следующим образом:

class Whatever < ApplicationRecord
has_many :things
end


class Thing < ApplicationRecord
belongs_to :whatever
end

Это имеет один эффект для вашеготаблицы: когда вы создаете таблицу Thing, вы должны добавить эту строку в миграцию вещи: t.references :whatever, index: true, foreign_key: true, которая создаст поле с именем whatever_id в таблице things.

Это своего родасоглашение о присвоении имен родителям полей, таких как parent_id.

Теперь, что касается вашего случая, я думаю, что Search должен быть потомком User (это пользователь, который создает запросы), но не так многодругие модели, кроме этой ...

Если вы хотите сохранить детали поиска, создайте определенное поле с явным именем, например search_content, в котором вы можете сохранить хэш деталей поиска:{'beds': 3, 'max_price': 45000, 'areas' : [1,2]}.

Конечно, вы также можете создать связь между поиском и областью с помощью отношения HABTM.

В этом случае, как только ваша поисковая запись будет создана и сохранена:

s = Search.new(user_id: 1, search_details: {'beds': 3, 'max_price': 45000, 'areas': [1,2]})
s.save

Затем вы можете добавить отношение областей:

s.search_details['areas'].each do |area_id|
  s << Area.find(area_id)
end
0 голосов
/ 18 октября 2018

После вашего Search.new консоль Rails возвращает это:

=> #<Search id: nil, beds: 3, max_price: 450000, prop_type: nil, user_id: nil, name: nil, area_id: nil, school_id: nil, district_id: nil, city_id: nil, email_me: nil, rental: nil, created_at: nil, updated_at: nil, grade: nil, school_slug: nil>

Обратите внимание на атрибут area_id: nil возвращаемого объекта.Вы указываете area_ids во множественном числе, но модель имеет столбец area_id в единственном числе, который не устанавливается при вызове new, вызывая ошибку недопустимого отношения.Я не знаю, как выглядит ваша модель Searches, но что-то не так, и я думаю, именно поэтому вы получаете эту ошибку ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...