railsは'4.2.5'を使用しています。
各種テーブルが以下のようなグループ単位になっている場合に、
ログインしたユーザーの所属するグループ情報のみ閲覧編集可能にしたいです。
groupテーブル
・userテーブル(ログインに使用)
・Customerテーブル
・その他各種テーブル
各テーブルにgroup_idを持たせて、ログインしたユーザーのgroup_idで絞り込むしかないのでしょうか?
何か定石のようなものがありましたら教えてもらえないでしょうか?
よろしくお願いします
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
tkow様
丁寧なご回答ありがとうございました。
頂いた回答を参考にサンプルを作成してみました。
他に良い方法があれば教えて下さい。
よろしくお願いします。
<要件>
・サインイン(新規ユーザー作成時)に関連するグループを自動で作成。
・ログインしたユーザーの所属するグループ以外の顧客情報は閲覧編集不可とする。
<モデル>
class Group < ActiveRecord::Base has_many :users has_many :customers end
class Customer < ActiveRecord::Base belongs_to :group end
class User < ActiveRecord::Base # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable acts_as_voter devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable belongs_to :group attr_accessor :new_group_name # バリデーション前にグループのバリデーションをする before_validation :build_group def build_group @group = Group.new name: new_group_name if @group.valid? # グループのバリデーションエラーが発生しなかった場合、 # 値を設定しておく。Userを保存するときにグループも一緒に作成される self.group = @group else # グループのバリデーションエラーが発生した場合、 # グループのバリデーションエラーのメッセージをUserモデルに設定 @group.errors.each do |_, message| errors.add :new_group_name, message end end end end
<コントローラー>
class CustomersController < ApplicationController before_action :find_customer, only: [:show,:edit,:update,:destroy] def index #ログインしたユーザーグループ情報のみ抽出 @customers = Customer.where(group_id: User.find(current_user).group_id) end def new @group = User.find(current_user).group_id @customer = Customer.new end def create @customer = Customer.new(customer_params) if @customer.save redirect_to @customer else render 'new' end end def update if @customer.update(customer_params) redirect_to @customer else render 'new' end end def edit end def destroy @customer.destroy respond_to do |format| format.html { redirect_to customers_url, notice: 'Group was successfully destroyed.' } format.json { head :no_content } end end def show end private def find_customer #URLに直にidを入力された場合の対処 if Customer.exists?(group_id: User.find(current_user).group_id, id: params[:id]) then @customer = Customer.find(params[:id]) else respond_to do |format| format.html { redirect_to customers_url, notice: 'レコードが存在しません' } format.json { head :no_content } end end end def customer_params params.require(:customer).permit(:name,:zip_code,:address,:tel,:fax,:remarks,:group_id) end end
<View>
= simple_form_for @customer do |f| =f.input :name =f.input :zip_code =f.input :address =f.input :tel =f.input :fax =f.input :remarks =f.input :group_id, :as => :hidden, :input_html => { :value => @group} =f.button :submit
投稿2016/05/13 06:37
総合スコア107
0
ベストアンサー
アソシエーション参照が重複し過ぎたりしないように多数の参照から多数の参照にアクセスする頻度を出来るだけ避けるために適切に中間テーブルを入れたり,正規化したり,インデックスを張るなど,基本的な知識を除けば定石というほど定石というものはありません。その辺りの知識が不足されていると思われるようでしたらここで答えられるものを待つよりも書籍やネット等から知識を得たほうが効率がいいでしょう。
本当に基礎ですが知らない話題があれば技術評論社の記事が参考になると思います。
優れているデザインパターンというものは有りますが大体はユーザーの使い方に合わせたアドホックな設計になることの方が多くデータ構造の問題よりも効率の悪いクエリを書いていたり,インデックスを張ってなかったり等の凡ミスが多いと思います。ただ確かに設計を間違えると後で修正しにくいので,大失敗をしない程度に基礎を押さえて,そこから先のチューニングは基本的にはデータをどのように管理したいかで,設計者がその都度スキーマを考えなければいけません。
今回の例ですが,まずはデータが正規化されていなければ正規化すると良いでしょう。これによってgroupテーブルでgroup_idを利用して参照すべきリレーションが絞られるはずです。逆に言うならば第三正規形まで変形させた時データ構造の重複がほとんど排除された状態になるはずなのでこの場合はどんなに量が多くてもすべてのテーブルにカラムを追加するべきです。
それらの基本を理解した上でアクセスを高速にしたいのであれば,グループ毎にユーザーのクラスを別々に設計してテーブルをクラス毎に作成するという工夫があったり,データ集計などを気にするのであればポリモーフィズムを許可して同系統のデータを同じデータベースに保存するなども出来ますし,ある程度日常的なアクセスの高速化を図りつつ集計もしたいのであれば別々のグループに個別のデータベースを作成しつつ,グループテーブルには参照先の集計済みデータを保持するカラムを作ると言った工夫が考えられます。
投稿2016/05/11 19:48
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。