2017-08-04 58 views
0

措辭十足,但我很困惑。Rails 5 Model.where(user_id) - 兩個級別向上

我有一個User模型誰has_many Clientshas_many statements, through: :clients然後statementsbelongs_to clientsbelongs to user

在控制檯我可以做任何我想要的查詢。 User.statementsUser.client.first.statements等等 - 我正在掙扎是Controller restrictions

現在很簡單 - 用戶應該只能夠看到ClientsStatements在他們自己。

對於客戶我做 客戶機控制器

def index 
    @clients = Client.where(user_id: current_user.id) 
end 

這似乎很好地工作。客戶端有一個用於user_id的字段

我很困惑如何模擬這個語句。語句不 - 沒有user_id字段。我不太確定我是否也想要它們,因爲在不久的將來,我希望客戶端belongs_to_many:用戶和語句不受限制。

聲明控制器

def index 
    @clients = Client.where(user_id: current_user.id) 
    @statements = Statement.where(params[:client_id]) 
    end 

我只是真的不知道要放什麼東西 - 我知道params[:client_id]沒有任何意義,但什麼是實現這一正確的方法是什麼?我是否以一種不安全的方式去做?

客戶端模式

class Client < ApplicationRecord 
    has_many :statements 
    has_many :client_notes, inverse_of: :client 
    belongs_to :user 
    validates :name, presence: true 
    validates :status, presence: true 
    accepts_nested_attributes_for :client_notes, reject_if: :all_blank, allow_destroy: true 
end 

聲明模型研究

class Statement < ApplicationRecord 
    belongs_to :client 
    belongs_to :user 
    validates :name, presence: true 
    validates :statement_type, presence: true 
    validates :client_id, presence: true 
    validates :start_date, presence: true 
    validates :end_date, presence: true 
end 

用戶模型

class User < ApplicationRecord 

    has_many :clients 
    has_many :statements, through: :clients 
end 

下面我提供的答覆正在使用

def index 
    if params[:client][:user_id] == @current_user.id 
     @clients = Client.includes(:statements).where(user_id: params[:client][:user_id]) 
     @statements = @clients.statements 
    else 
     return 'error' 
    end 
    end 

不能確定這是否是邏輯正確

+0

你可以添加模型來查看他們的關係嗎? –

+0

@SebastiánPalma完成。 – DNorthrup

+0

爲什麼投票反對? – DNorthrup

回答

2

使用includes避免[N + 1]的查詢。

而且對於「用戶應該只能看到他們擁有的客戶端和語句」

if params[:client][:user_id] == @current_user.id 
    @clients = Client.includes(:statements).where(user_id: params[:client][:user_id]) 
    # do more 
else 
    # Type your error message 
end 

此外,您可能需要使用strong paramsscope

+0

它是「@ current_user」還是「current_user」? –

+0

取決於您的使用,@current_user是實例變量,current_user是局部變量,並且不在其範圍之外訪問 – 2017-08-04 01:45:23

+1

我想是Devise'current_user',這就是原因。 –

0

做到這一點,最好的辦法是使用包括:

@clients = Client.where(user_id: current_user.id) 
@statements = Statement.includes(clients: :users}).where('users.id = ?', current_user.id) 

你可以在這裏看看:https://apidock.com/rails/ActiveRecord/QueryMethods/includes

+0

這個查詢邏輯讓我困惑。 client_id不應該是我們與user_id比較的。他們不一樣。 用戶有聲明的客戶。或者它在做我不知道的事情? – DNorthrup

+0

對不起,是user_id而不是client_id。我編輯答案。 –

+0

謝謝,但仍然有問題。 對於#' '未定義的方法'語句'在您的第二行 – DNorthrup

0

在這種情況下,由於提醒current_user是設計一個幫手,以及我所展示的關係結構,它實際上就像

def index 
    @statements = current_user.statements 
end 

解決了我的問題。

由於@BigB引起了我的注意的[N+1] Queries issue,雖然此方法有效,但我不會爲相當大的交易提出建議。

+1

瞭解這一點,如果您希望客戶端表記錄與語句表記錄一起保留[N + 1]查詢問題(如前面描述過您的問題所述),則需要「#includes」,current_user在您的代碼上下文中設計幫手。 – 2017-08-04 16:08:03

+0

@BigB感謝您的見解。我實際上谷歌搜索這個詞來理解。我不知道它是如何運作的。我很欣賞提及。我會嘗試找出使用你的方法。 – DNorthrup