1

저는 웹 애플 리케이션 기존 모델 중 하나에 속한 새 모델을 구현하려고했습니다. 결국에는 중첩 된 양식을 만들고 싶습니다. 나는 폼과 강력한 params가 자신 만의 문제를 가질 수 있다는 것을 이해하지만 현재는 레일 콘솔에서 기대하는 것처럼 모델이 작동하도록 고심하고 있습니다. 레일 4.2.7레일 중첩 된 속성은 parent_id를 인덱스로 올바르게 지정하지만 추가 속성은 지정하지 않습니다.

, 포스트 그레스 DB

UPDATE

- 10/3/16이 - 아직도 적합한 솔루션을 찾기 위해 노력하고 있지만,

우리의 연구는 학교와 지구와 함께 일부 변경

을 만들었습니다,이 설문 조사와 설문 조사가 학교 및 교육구에 할당 된 구체적인 경우를 다룹니다. 지금까지 SurveyAssignment 모델을 사용하는 지구에 설문 조사가 할당되었으며, 지구의 모든 학교가 설문 조사에 "할당"되었다고 가정 한 논리가 있습니다. 이제 우리는 SurveyAssignment에보다 세분화 된 기능을 추가하고 학교 수준에서 특정 기능을 사용할 수 있기를 원합니다.

그래서 SchoolSurveyAssignment 모델을 만들고 그 자리에서 비트를 얻기 시작했습니다. 여기

는 관련 모델 정보입니다 :

class District < ActiveRecord::Base 
    ... 
    has_many :schools, dependent: :destroy 
    has_many :survey_assignments, dependent: :destroy 
    ... 
end 

class School 
    ... 
    belongs_to :district 
    has_many :school_survey_assignments 
    has_many :survey_assignments, :through => :school_survey_assignments 

    ... 
end 

class SurveyAssignment 
    belongs_to :district 
    belongs_to :survey 
    has_one :survey_version, through: :survey 
    has_many :school_survey_assignments, inverse_of: survey_assignment 
    has_many :schools, :through => :school_survey_assignments 

    accepts_nested_attributes_for :school_survey_assignments 

    attr_accessor :survey_group, :survey_version_type, :survey_version_id, :school_survey_assignments_attributes 
    validates :survey_id, presence: true 
end 

class SchoolSurveyAssignment 
    belongs_to :survey_assignment, inverse_of: :school_survey_assignments 
    belongs_to :school 

    attr_accessor :school_id, :survey_assignment_id, :grades_affected, :ulc_affected 
    validates_presence_of :survey_assignment 
    validates :school_id, presence: true, uniqueness: {scope: :survey_assignment_id} 
end 

관련 컨트롤러 코드 : 여기

class SurveyAssignmentsController < ApplicationController 
    before_action :set_district 
    before_action :set_survey_assignment, only: [:show, :edit, :update, :destroy] 

    respond_to :html, :json, :js 

    def new 
    @new_survey_assignment = SurveyAssignment.new() 
    @district.schools.each do |school| 
     @new_survey_assignment.school_survey_assignments.build(school_id: school.id) 
    end 
    end 

    def create 
    @survey_assignment = SurveyAssignment.new(survey_assignment_params) 
    if @survey_assignment.save 
     flash[:notice] = "Survey successfully assigned to #{@district.name}" 
    else 
     flash[:alert] = "There was a problem assigning this survey to #{@district.name}" 
    end 
    redirect_to district_survey_assignments_path(@district) 
    end 

    def survey_assignment_params 
    params.require(:survey_assignment).permit(:survey_id, :status, :survey_version_id, school_survey_assignments_attributes: [:id, :survey_assignment_id, :school_id, grades_affected: [], ulc_affected: []]).tap do |p| 
     p[:district_id] = @district.id 
     p[:school_year] = session[:selected_year] 
    end 
    end 

    def set_district 
    @district = District.find(params[:district_id]) 
    end 

가 관련 스키마 정보입니다 : 장소에 있던이 일단

create_table "school_survey_assignments", force: :cascade do |t| 
    t.integer "survey_assignment_id" 
    t.integer "school_id" 
    t.integer "grades_affected",  default: [], array: true 
    t.string "ulc_affected",   default: [], array: true 
end 

add_index "school_survey_assignments", ["school_id"], name: "index_school_survey_assignments_on_school_id", using: :btree 
add_index "school_survey_assignments", ["survey_assignment_id"], name: "index_school_survey_assignments_on_survey_assignment_id", using: :btree 

create_table "survey_assignments", force: :cascade do |t| 
    t.integer "district_id" 
    t.integer "survey_id" 
    t.integer "status" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    t.integer "school_year" 
    t.integer "last_response_status_id" 
end 

add_index "survey_assignments", ["district_id"], name: "index_survey_assignments_on_district_id", using: :btree 

, I 내 레일 콘솔을 밟았으며 다음을 시도했습니다.

2.3.1 :002 > sa1 = SurveyAssignment.create(district_id: 3, survey_id: 508, school_year: 2017) 
    (0.2ms) BEGIN 
SQL (0.7ms) INSERT INTO "survey_assignments" ("district_id", "survey_id", "school_year", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["district_id", 3], ["survey_id", 508], ["school_year", 2017], ["created_at", "2016-09-30 21:30:20.205144"], ["updated_at", "2016-09-30 21:30:20.205144"]] 
    (7.2ms) COMMIT 
=> #<SurveyAssignment id: 369, district_id: 3, survey_id: 508, status: nil, created_at: "2016-09-30 21:30:20", updated_at: "2016-09-30 21:30:20", school_year: 2017, last_response_status_id: nil> 
2.3.1 :003 > sa2 = SurveyAssignment.create(district_id: 3, survey_id: 508, school_year: 2017) 
    (0.3ms) BEGIN 
SQL (0.4ms) INSERT INTO "survey_assignments" ("district_id", "survey_id", "school_year", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["district_id", 3], ["survey_id", 508], ["school_year", 2017], ["created_at", "2016-09-30 21:30:30.701197"], ["updated_at", "2016-09-30 21:30:30.701197"]] 
    (0.5ms) COMMIT 
=> #<SurveyAssignment id: 370, district_id: 3, survey_id: 508, status: nil, created_at: "2016-09-30 21:30:30", updated_at: "2016-09-30 21:30:30", school_year: 2017, last_response_status_id: nil> 

이제는 두 가지 조사 할당을 성공적으로 만들었습니다. 지금 SA1 떨어져 두 학교 설문 조사 할당을 만들려고 :

2.3.1 :004 > [{school_id: 5}, {school_id: 6}].each do |ssa| 
2.3.1 :005 >  sa1.school_survey_assignments.create(ssa) 
2.3.1 :006?> end 
    (0.2ms) BEGIN 
SchoolSurveyAssignment Exists (2.4ms) SELECT 1 AS one FROM "school_survey_assignments" WHERE ("school_survey_assignments"."school_id" = 5 AND "school_survey_assignments"."survey_assignment_id" = 369) LIMIT 1 
SQL (0.4ms) INSERT INTO "school_survey_assignments" ("survey_assignment_id") VALUES ($1) RETURNING "id" [["survey_assignment_id", 369]] 
    (6.4ms) COMMIT 
    (0.6ms) BEGIN 
SchoolSurveyAssignment Exists (0.4ms) SELECT 1 AS one FROM "school_survey_assignments" WHERE ("school_survey_assignments"."school_id" = 6 AND "school_survey_assignments"."survey_assignment_id" = 369) LIMIT 1 
    SQL (0.3ms) INSERT INTO "school_survey_assignments" ("survey_assignment_id") VALUES ($1) RETURNING "id" [["survey_assignment_id", 369]] 
    (0.4ms) COMMIT 
=> [{:school_id=>5}, {:school_id=>6}] 
2.3.1 :007 > sa1.save 
    (0.3ms) BEGIN 
    (0.4ms) COMMIT 
=> true 

을 지금, 나는이 성공적으로 survey_assignment_id = 369 두 SchoolSurveyAssignments를 생성 한 것 같습니다 school_ids = 5, 6

2.3.1 :008 > sa1.school_survey_assignments 
    SchoolSurveyAssignment Load (0.3ms) SELECT "school_survey_assignments".* FROM "school_survey_assignments" WHERE "school_survey_assignments"."survey_assignment_id" = $1 [["survey_assignment_id", 369]] 
=> #<ActiveRecord::Associations::CollectionProxy [#<SchoolSurveyAssignment id: 5, survey_assignment_id: 369, school_id: nil, grades_affected: [], ulc_affected: []>, #<SchoolSurveyAssignment id: 6, survey_assignment_id: 369, school_id: nil, grades_affected: [], ulc_affected: []>]> 

ActivRecord :: Associations :: CollectionProxy에서 볼 수 있듯이, survey_assignment_id : 369와 함께 SchoolSurveyAssignments가 생성되었지만 nall school_id가되었습니다. 가 생성 함수에 전달되는 매개 변수를 무시

내가 이해하지 못하는 또 다른 항목은 다음이다 school_id의 검증을 무시하는 것 같다 이것은 골치 아프다 :

2.3.1 :009 > SchoolSurveyAssignment.find(5).survey_assignment_id 
    SchoolSurveyAssignment Load (0.6ms) SELECT "school_survey_assignments".* FROM "school_survey_assignments" WHERE "school_survey_assignments"."id" = $1 LIMIT 1 [["id", 5]] 
=> nil 
2.3.1 :011 > SchoolSurveyAssignment.find(5).survey_assignment.id 
    SchoolSurveyAssignment Load (0.3ms) SELECT "school_survey_assignments".* FROM "school_survey_assignments" WHERE "school_survey_assignments"."id" = $1 LIMIT 1 [["id", 5]] 
    SurveyAssignment Load (0.4ms) SELECT "survey_assignments".* FROM "survey_assignments" WHERE "survey_assignments"."id" = $1 LIMIT 1 [["id", 369]] 
=> 369 

SchoolSurveyAssignment에 속성을 반환하고 단순히 잡고있다 369. .survey_assignment.id를 제공해야 .survey_assignment_id를 호출 부모 객체의 ID를 가져온다. 두 값 모두 동일한 값을 반환 할 것으로 예상되지만, 아무 값도 반환하지 않습니다.

최종 사용 사례는 사용자가 새로운 SurveyAssignment에 대한 속성을 설정하고 SchoolSurveyAssignments의 X 번호에 대한 속성을 설정할 수있게하는 SurveyAssignment 양식을 만듭니다 (한 지구에있는 학교 수에 따라 2에서 15까지 다양 함) . 일단이 모델들이 어떻게 상호 작용하는지에 대한 더 나은 이해를 얻었을 때, 나는이 목표를 실행하는 것에 확신을 가지지 만, 내가 보는 행동은 나에게 의미가 없으며 이러한 관련 모델을 구현하는데 약간의 명확성을 찾기를 희망했다. 나는 그 대답을 돌아 다니고있는 것처럼 느껴지지만 중요한 세부 사항을 놓치고있다.

감사합니다, 첫 번째 질문에 대한

알렉스

+0

당신이 컨트롤러 코드를 게시 할 수 있습니다 제대로 저장되지 원인, 액티브 이미 기본적으로 제공하는 방법을 엉망이야? 강력한 매개 변수를 사용하고 있다고 가정합니까? – Ren

+0

강력한 매개 변수를 사용하고 있습니다. 컨트롤러 코드로 업데이트하겠습니다. 이것은 나의 무지를 드러 낼지 모르지만 컨트롤러 메소드가 실제 HTTP 요청/라우팅에만 영향을주고 콘솔에서 명령을 실행하면 해당 메소드에 영향을 미치지 않는다는 인상하에있었습니다. –

답변

1

시도를 attr_accessor 코드 줄을 제거하십시오. attr_accessor 데이터베이스에 유지되는 속성에 사용되어서는 안 그것은 아마 그 속성이

class SurveyAssignment 
    belongs_to :district 
    belongs_to :survey 
    has_one :survey_version, through: :survey 
    has_many :school_survey_assignments, inverse_of: survey_assignment 
    has_many :schools, :through => :school_survey_assignments 

    accepts_nested_attributes_for :school_survey_assignments 

    validates :survey_id, presence: true 
end 

class SchoolSurveyAssignment 
    belongs_to :survey_assignment, inverse_of: :school_survey_assignments 
    belongs_to :school 

    validates_presence_of :survey_assignment 
    validates :school_id, presence: true, uniqueness: {scope: :survey_assignment_id} 
end 
+0

안녕하세요, 도움 주셔서 감사합니다! 나는 귀하의 제안에 따라 생성을 시도했지만 SurveyAssignment를 만들었지 만 school_survey_assignments는 만들지 않았습니다. 또한 api.rubyonrails.org 문서에서 일대 다 예제 인 에 대한 답변을 시도했습니다. http://api.rubyonrails.org/v4.2/classes/ActiveRecord/NestedAttributes/ClassMethods.html#label - + + + + 부모 + 모델의 + 존재 + 확인 또한 설문 조사 할당을 만들었지 만 SchoolSurveyAssignments를 만들지 않았습니다. –

+0

동료의 조언에 따라 맞춤형 Form 객체 클래스를 사용하여 측량 과제 및 SchoolSurveyAssignments를 처리하는 방향으로 옮겼습니다. 적절하게 매개 변수를 처리하고 있으며 필요한 모든 매개 변수를 SurveyAssignmentController를 통해이 개체로 가져옵니다. 그러나 여전히 하위 모델 (school_survey_assignment)에 특성을 저장하지 않습니다. 중첩 된 양식/양식 객체가있는 문제가 아닌 다른 문제가있는 것으로 보입니다 –

+0

원래 게시물을 편집했습니다.'attr_accessor' 라인을 주석 처리/삭제하려고 시도하십시오. – Ren

1

는 학교와 SurveyAssignment는 서로 school_id이 전무하게 알지 못한다. 귀하의 앱에서 이러한 모델은 간접적으로 m 대 n 연관이 있으므로 모델 간의 연관을 통해 has_many를 사용하는 것이 어떻습니까?

학교 모델에서

, 아래에 추가 :

has_many :survey_assignments, :through => :school_survey_assignments 

을 SurveyAssignments 모델에서, 아래에 추가

마지막 질문에 대한
has_many :schools, :through => :school_survey_assignments 

이 두 코드는 같은 것 같다 ..

+0

필요한 연관성을 지적 해 주셔서 감사합니다. 나는 그것을 추가했고, 나는 여전히 몇 가지 문제에 직면 해있다. 변경 사항을 반영하도록 코드를 업데이트했습니다. 마지막 질문과 관련하여 차이점은 .id vs _id –

+0

죄송합니다. 간과했으나 .id와 _id 둘 다 내 PC에서 작동합니다. 문제가 여전히 .id vs _id입니까? BTW, SurveyAssignment 클래스에서 inverse_of : survey_assignment가 'survey_assignment'이전에 ':'누락되었습니다. – YTorii

+0

후속 조치를 보내 주셔서 감사합니다. 그 누락 : 내 편집장에서 Stackoverflow가는 오타되었지만 좋은 잡기. –