这两天正在做一个在线调查问卷的 ROR 习题。这是其中遇到的一个让我困惑不解的问题,先简单说明一下问题所对应的数据结构,文字说明不如直接上代码。
create_table "join_options", force: :cascade do |t| t.integer "multi_response_id" t.integer "response_option_id" end
create_table "multi_responses", force: :cascade do |t| t.integer "respondent_id" t.integer "question_id" t.text "answer" end
create_table "questions", force: :cascade do |t| t.text "text" t.integer "survey_id" t.integer "options" t.boolean "multi_select" t.boolean "required" end
create_table "respondents", force: :cascade do |t| t.string "name" t.integer "survey_id" end
create_table "response_options", force: :cascade do |t| t.integer "question_id", null: false t.text "text", null: false end
create_table "surveys", force: :cascade do |t| t.string "title", null: false t.text "description", null: false end
> 我的目的是希望一次提交创建Respondent,MultiResponse(以及之后的Range表单)。为了达到这个目的,我想到了两个方案,一个方案是只创建一个单独的`answer`列而舍弃`JoinOption`这个关系连(或者数据保存之后再创建关系),但这要求我保存一个`Array`到数据结构中,这是我不愿看到的.(可能的数据提交如下)
```ruby
"respondent"=>
{"survey_id"=>"1",
"name"=>"",
"multi_responses_attributes"=>
{"0"=>{"question_id"=>"2", "answer"=>["", "3", "4"]},
"1"=>{"question_id"=>"4", "answer"=>"13"},
"2"=>{"question_id"=>"6", "answer"=>"20"},
"3"=>{"question_id"=>"9", "answer"=>["", "30", "31", "32"]}}},
"commit"=>"Submit your Survey"}
问题的关键是我根本就无法顺利保存这个
array
。顺便说一下,我用的是postgresql
做的开发环境,serialize
和在migration
里添加array: true, default: []
等办法都试过了,都没有用。于是我决定采取另一种即现在这种 直接建立MultiResponse
和ResponseOption
关系的办法。于是表单的形式就如下所见<%= form_for @respondent do |f| %> <%= f.hidden_field :survey_id, value: @survey.id %> <%= f.text_field :name %> <ol> <!-- Multiple selection questions --> <% if multi_question.multi_select? %> <%= f.fields_for :multi_responses do |multi_response| %> <%= multi_response.hidden_field :question_id, value: multi_question.id %> <%= multi_response.collection_check_boxes :response_option_ids, multi_question.response_options, :id, :text, {}, class: "checkbox" %> <% end %> <!-- Single selection questions --> <% else %> <%= f.fields_for :multi_responses do |multi_response| %> <%= multi_response.hidden_field :question_id, value: multi_question.id %> <%= multi_response.collection_radio_buttons :answer, multi_question.response_options, :id, :text, {}, class: "radio radio-inline" %> <% end %> <% end %> </ol> <%= f.submit "Submit your Survey" %> <% end %>
上个图也许能对这个表格看的更清楚点(以上表单简略了许多)
关于这个办法的
radio button
数据如何保存,也还没头绪就遇到了标题所说的问题。Could not find the source association(s) "response_option" or :response_options in model JoinOption. Try 'has_many :response_options, :through => :join_options, :source => <name>'. Is it one of ?
我的
model
关系class JoinOption < ApplicationRecord belongs_to :multi_response belongs_to :response_option end
class MultiResponse < ApplicationRecord belongs_to :respondent, optional: true belongs_to :question
has_many :join_options has_many :response_options, through: :join_options end
class ResponseOption < ApplicationRecord belongs_to :question
has_many :join_options has_many :multi_responses, through: :join_options end
>如果有不清楚的可以留言或者直接去我的[Github链接地址](https://github.com/BranLiang/project_surveyor/tree/withjointable)去看。
总结一下我遇到主要问题。
- 为什么这个简单`many to many`关系建立不成功
- 如何才能向`posgresql`里面保存`array`
- 是否有更好的办法完成该任务即同时保存`checkbox`和`radio`的数据