Terribly worded, but I'm confusing it.
I have a User
model who has_many Clients
and has_many statements, through: :clients
and then statements
which belongs_to clients
and belongs to user
In Console I can do all the queries I want. User.statements
User.client.first.statements
etc - What I'm struggling on is Controller restrictions
For now it's simple - A user should only be able to see Clients
and Statements
in which they own.
For Clients I did Client Controller
def index
@clients = Client.where(user_id: current_user.id)
end
Which seems to work perfectly. Client has a field for user_id
I'm kind of stuck on how to emulate this for Statements. Statements do -not- have a user_id field. I'm not quite sure I want them too since in the very-soon-future I want clients to belongs_to_many
:users and Statements to not be bound.
Statement Controller
def index
@clients = Client.where(user_id: current_user.id)
@statements = Statement.where(params[:client_id])
end
I'm just genuinely not sure what to put - I know the params[:client_id]
doesn't make sense, but what is the proper way to fulfill this? Am I going about it an unsecure way?
Client Model
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
Statement Model
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
User Model
class User < ApplicationRecord
has_many :clients
has_many :statements, through: :clients
end
Based on the reply provided below I am using
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
Unsure if this logic is proper
Use includes to avoid [N+1] queries.
And regarding "A user should only be able to see Clients and Statements in which they own" .
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
Additionally, you might need to use strong params and scope .
The best way to do it is using includes:
@clients = Client.where(user_id: current_user.id)
@statements = Statement.includes(clients: :users}).where('users.id = ?', current_user.id)
You can take a look in here: https://apidock.com/rails/ActiveRecord/QueryMethods/includes
In this case, thanks to the reminder that current_user
is a helper from Devise, and the relational structure I showed, it was actually just as simple as
def index
@statements = current_user.statements
end
resolved my issue.
Due to the [N+1] Queries issue that @BigB has brought to my attention, while this method works, I wouldn't suggest it for a sizable transaction.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.