简体   繁体   中英

Ruby on Rails: how can we execute activerecord query stored in database?

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)")

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 (eg 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.

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

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM