Decidim の Meeting コンポーネントには、ミーティング中にリアルタイムで投票(Poll)を実施する機能が組み込まれています。この機能により、参加者は質問に対してライブで回答することができ、管理者はその結果をリアルタイムで確認できます。
ファイル: app/models/decidim/meetings/poll.rb
class Poll < Meetings::ApplicationRecord
has_one :questionnaire, as: :questionnaire_for
belongs_to :meeting
QUESTION_TYPES = %w(single_option multiple_option).freeze
end
- 各ミーティングに1つの投票(Poll)を設定可能
- アンケート形式で質問を管理
- 単一選択・複数選択の質問タイプをサポート
ファイル: app/models/decidim/meetings/questionnaire.rb
class Questionnaire < Meetings::ApplicationRecord
belongs_to :questionnaire_for, polymorphic: true
has_many :questions, -> { order(:position) }
has_many :answers
end
- 投票の質問群を管理
- 位置順で質問を並び替え
- 全ての質問・回答を追跡
ファイル: app/models/decidim/meetings/question.rb
class Question < Meetings::ApplicationRecord
include Decidim::TranslatableResource
QUESTION_TYPES = %w(single_option multiple_option).freeze
enum status: { unpublished: 0, published: 1, closed: 2 }
belongs_to :questionnaire
has_many :answers
has_many :answer_options
end
質問の状態:
unpublished
: 未公開(管理者のみ表示)published
: 公開中(参加者が回答可能)closed
: 終了(結果表示のみ)
質問タイプ:
single_option
: 単一選択(ラジオボタン)multiple_option
: 複数選択(チェックボックス)
ファイル: app/models/decidim/meetings/answer.rb
class Answer < Meetings::ApplicationRecord
belongs_to :user, optional: true
belongs_to :questionnaire
belongs_to :question
has_many :choices
end
- ユーザーの回答を記録
- 複数の選択肢(choices)を持てる
ファイル: app/models/decidim/meetings/answer_option.rb
class AnswerOption < Meetings::ApplicationRecord
include Decidim::TranslatableResource
belongs_to :question
has_many :choices
end
- 質問の選択肢を定義
- 多言語対応
-- 投票テーブル
CREATE TABLE decidim_meetings_polls (
id bigint PRIMARY KEY,
decidim_meeting_id bigint, -- ミーティングとの関連
created_at timestamp,
updated_at timestamp
);
-- その他のテーブルは decidim-forms モジュールの構造を使用
-- - decidim_meetings_questionnaires
-- - decidim_meetings_questions
-- - decidim_meetings_answer_options
-- - decidim_meetings_answers
-- - decidim_meetings_answer_choices
ファイル: app/controllers/decidim/meetings/admin/meetings_poll_controller.rb
主要メソッド:
edit
: 投票の質問を編集update
: 投票の質問を更新answer_options
: JSON形式で選択肢を返す
def edit
enforce_permission_to(:update, :poll, meeting:, poll:)
@form = form(Admin::QuestionnaireForm).from_model(questionnaire)
end
def update
Admin::UpdateQuestionnaire.call(@form, questionnaire) do
on(:ok) { redirect_to after_update_url }
on(:invalid) { render template: "decidim/meetings/admin/poll/edit" }
end
end
ファイル: app/controllers/decidim/meetings/polls/questions_controller.rb
主要メソッド:
index
: 質問一覧表示(AJAX)update
: 質問の状態更新(公開/終了)
def update
enforce_permission_to(:update, :question, question:)
Decidim::Meetings::Admin::UpdateQuestionStatus.call(question, current_user) do
respond_to do |format|
format.js { render template: admin_index_template }
end
end
end
ファイル: app/controllers/decidim/meetings/polls/answers_controller.rb
主要メソッド:
admin
: 管理者向け結果表示index
: 参加者向け投票画面create
: 回答の作成
def create
enforce_permission_to(:create, :answer, question:)
@form = form(AnswerForm).from_params(params.merge(question:, current_user:))
CreateAnswer.call(@form, questionnaire) do
respond_to do |format|
format.js # AJAX レスポンス
end
end
end
ファイル: app/permissions/decidim/meetings/permissions.rb
reply_poll
: 投票への回答- 条件: ミーティングが存在 && 投票が存在 && 認証済み
def can_reply_poll?
meeting.present? &&
meeting.poll.present? &&
authorized?(:reply_poll, resource: meeting)
end
update
(poll): 投票の更新- 条件: ユーザーが管理者 && ミーティング・投票が存在
def can_update_poll?
user.present? &&
user.admin? &&
meeting.present? &&
meeting.poll.present?
end
create
(answer): 回答の作成- 条件: 質問が存在 && ユーザー存在 && 未回答
def can_answer_question?
question.present? && user.present? && !question.answered_by?(user)
end
update
(question): 質問の状態更新- 条件: ユーザーが管理者 && 質問が存在
-
投票作成
- ミーティング詳細画面で「Manage poll」をクリック
/admin/meetings/{meeting_id}/poll/edit
にアクセス
-
質問設定
- 質問タイプ選択(単一選択/複数選択)
- 質問文の入力(多言語対応)
- 選択肢の設定
-
質問公開
- 質問を
published
状態に変更 - 参加者が回答可能になる
- 質問を
-
結果確認
- リアルタイムで回答状況を確認
- 質問を
closed
状態に変更して結果公開
-
投票参加
- ミーティングページで「Reply poll」をクリック
- 権限チェック(認証・参加権限)
-
質問回答
- 公開中の質問に回答
- AJAX で即座に送信
- 1つの質問につき1回のみ回答可能
-
結果確認
- 管理者が結果を公開した質問の結果を表示
ファイル: config/locales/en.yml
decidim:
components:
meetings:
actions:
reply_poll: Reply poll
settings:
global:
# 投票関連の設定は現在特別な設定項目なし
# ミーティング全体の設定を継承
現在サポートされている質問タイプ:
QUESTION_TYPES = %w(single_option multiple_option).freeze
single_option
: ラジオボタン(1つのみ選択)multiple_option
: チェックボックス(複数選択可能)
- JavaScript/AJAX による動的更新
- ページリロード不要で質問の状態変更
- 即座の回答反映
- 質問文・選択肢の多言語対応
TranslatableResource
を使用
- きめ細かい権限制御
- 認証・認可の分離
- ロールベースアクセス制御
- 外部キー制約
- バリデーション
- トランザクション処理
- 1つのミーティングにつき1つの投票のみ
- 複数の投票を並行実施することは不可
- 1つの質問につき1ユーザー1回のみ回答可能
- 回答の修正・削除は不可
- 現在は選択式のみサポート
- 自由記述式の質問は未対応
- 回答はユーザーと紐づけて保存
- 完全匿名での投票は不可
# Question モデルを拡張
QUESTION_TYPES = %w(single_option multiple_option text_input rating_scale).freeze
- グラフ・チャート表示機能
- エクスポート機能
- 統計分析機能
- 参加者グループ別の投票権限
- 段階的な結果公開
- 投票期間の設定
Decidim の Meeting Poll 機能は、リアルタイムでの参加型投票を実現する強力な機能です。シンプルでありながら拡張性を持ち、様々な会議や意思決定プロセスで活用できます。多言語対応や権限管理など、Decidim の基本的な思想を踏襲しており、民主的なプロセスを支援するツールとして設計されています。