Reputation: 11
I have formula table which store the formula for retrieving the data, like below.
'select("clause").where(id: permitted_params[:id]).group("date(transaction_date)")'
How can I use above query string with ActiveRecord and generate the data.
Model.(above query string)
should produce below
Model.select("clause").where(id: permitted_params[:id]).group("date(transaction_date)")
Upvotes: 1
Views: 574
Reputation: 8646
As already has been pointed out: this is insecure and not practical when you have DB updates.
An easy way to execute raw SQL and have the result already converted to models is find_by_sql
:
Model.find_by_sql('select * from models where some complicated nasty SQL goes here')
Now if you provide the query and the user provides the arguments to that query, then this might be a bit different. I'd probably create a class per query and store all parameters (that have been provided by the user) as well as what query is to be executed in the DB and then construct the query at runtime. Something along those lines:
class QueryA
def initialize(params)
@params = params
end
def call
SomeModel.select(clause).where(permitted_ids: permitted_ids)
end
private
def clause
params[:clause].presence_in(%w{first_valid_value second_valid_value ...})
end
def permitted_ids
# access from params and whitelist
end
end
Upvotes: 1
Reputation: 15944
Your approach seems very insecure (unless you have absolute, total control of the queries in the db) and not very maintainable in the long run (e.g. a change in the db structure invalidates all queries that use it and you'd need to check all of them if they are still ok).
So, I would not do that, but if you insist, you can use class_eval
on the model class:
Model.class_eval('select("clause").where(id: permitted_params[:id]).group("date(transaction_date)')
is equivalent to:
Model.select("clause").where(id: permitted_params[:id]).group("date(transaction_date)")
But still, I'd vote against this approach: you say you need to query different types of products. There usually is a way to abstract such info into a few attributes and perhaps some join tables. Something like: a product can have many features and each feature has a name, type, etc... This would be the way to go for me. The long-term advantage is also that you would be building a detailed description of the product in your code / db which may come handy for various purposes later.
Upvotes: 1