El lunes, 28 de febrero de 2022 22:41:00 (CET) 'Dennis Bulgatz' via ActiveScaffold : Ruby on Rails Gem escribió:
> Hello,
>
> I am using the "conditions for collection" method in the controller to add
> sql for security trimming. This works fine for a straight list, but when a
> user runs a search, it appears that the search form, which has some of the
> same params used for security trimming, will override the security settings
> in the conditions for collection method.
The method building the query is find_page, it gets options for query calling finder_options, which return a hash, and then build the query passing those options to append_to_query method. The hash returned by finder_options has :conditions key with the value returned by all_conditions, this method collect conditions returned by several methods, including conditions_for_collection and active_scaffold_conditions (the conditions from search params):
def all_conditions(include_id_condition = true)
[
(id_condition if include_id_condition), # for list with id (e.g. /users/:id/index)
active_scaffold_conditions, # from the search modules
conditions_for_collection, # from the dev
conditions_from_params, # from the parameters (e.g. /users/list?first_name=Fred)
conditions_from_constraints, # from any constraints (embedded scaffolds)
active_scaffold_embedded_conditions # embedding conditions (weaker constraints)
].reject(&:blank?)
end
>
> A few specific questions:
> 1. How can I *log* the sql statement used to get results for a search? Is
> there some method in the controller that is run last that I could put a
> Logger.Info statement to get an FinderMethods.to_sql ?
You can override find_page, call super to get the page and use it to call .to_sql on items:
def find_page(*)
super.tap do |page|
logger.info page.items.to_sql
end
end
Or override do_list, call super and log @records.to_sql, @records is @page.items:
def do_list
super
logger.info @records.to_sql
end
> 2. Is there any way to set a priority on the "conditions for collections"
> to override search params?
It shouldn't be needed, FieldSearch and Search modules have do_search action, which builds conditions for search params, and add them to active_scaffold_conditions which keeps an array in the variable @active_scaffold_conditions:
def active_scaffold_conditions
@active_scaffold_conditions ||= []
end
And all_conditions method collects result both from active_scaffold_conditions and conditions_for_collection, so both conditions should be present in the query. I have tested now and I can see both conditions in the SQL query.
You can debug the value returned by all_conditions method, or finder_options method:
def all_conditions(*)
super.tap do |conditions|
logger.info conditions.inspect
end
end
def finder_options(*)
super.tap do |options|
logger.info options.inspect
end
end
> 3. Does it matter if the "conditions for collection" is a sql string, vs
> an array or hash?
Append_to_query will call apply_conditions, which loops over array, it will call where with each item if item is hash, string, or array where first element is string, so every value is valid, any of these would work:
{column1: value1, column2: value2}
['column1 = ? and column2 = ?', value1, value2]
'column1 = 0'
I think an array combining hashes, sql strings, or array with sql string and values would work too, if first item is not string.
def apply_conditions(relation, *conditions)
conditions.reject(&:blank?).inject(relation) do |rel, condition|
if condition.is_a?(Array) && !condition.first.is_a?(String) # multiple conditions
apply_conditions(rel, *condition)
else
rel.where(condition)
end
end
end