1

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)")
4
  • use scope in model Commented Apr 13, 2016 at 5:11
  • I have json like table which store different kind of product information and I need to query the data by using different set of clause for different products. As we have dynamic form to create different types products we need to retrieve product information with different clause based on requirement. So scope won't help here. Commented Apr 13, 2016 at 5:18
  • You are going to have really hard time trying to accomplish that, why not think it over? You could store the parameters you need to query and build them dynamically but you just can't store code and then try to execute it, the closest you can do is use send method. Commented Apr 13, 2016 at 5:33
  • Good point @Rubio , I will go with dynamic query build. Thanks :) Commented Apr 13, 2016 at 8:09

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.