Ruby / Rails-链数未知的方法调用

时间:2019-01-07 06:24:14

标签: ruby-on-rails ruby

我想根据作为参数传递给方法的2D数组动态创建(可能很复杂)Active Record查询。换句话说,我想这样做:

arr = [
    ['join', :comments],
    ['where', :author => 'Bob']
]

并创建与此等效的内容:

Articles.join(:comments).where(:author => 'Bob')

一种方法是:

Articles.send(*arr[0]).send(*arr[1])

但是,如果arr包含3个嵌套数组,或者4,或5,该怎么办?一种非常精致的方法是:

case arr.length
    when 1
        Articles.send(*arr[0])
    when 2
        Articles.send(*arr[0]).send(*arr[1])
    when 3
        Articles.send(*arr[0]).send(*arr[1]).send(*arr[2])
    # etc.
end

但是是否有一种更简洁,更简洁的方式(不必多次访问数据库)?也许有一些方法可以在执行之前构造方法调用链?

3 个答案:

答案 0 :(得分:2)

一种方便的方法是使用散列而不是2D数组。

类似这样的东西

my_subroutine.for:4:6:

      subroutine uel(rhs, amatrx, svars, energy, ndofel, nrhs, nsvars,
      1
Error: Bad continuation line at (1)
my_subroutine.for:4:6:

      subroutine uel(rhs, amatrx, svars, energy, ndofel, nrhs, nsvars,
      1
Error: Unclassifiable statement at (1)
my_subroutine.for:5:6:

     1 props, nprops, coords, mcrd, nnode, u, du, v, a, jtype, time, dtime,
      1
Error: Unclassifiable statement at (1)
my_subroutine.for:6:6:

     2 kstep, kinc, jelem, params, nload, jdltyp, adlmag, predef, npredf,
      1
Error: Unclassifiable statement at (1)
my_subroutine.for:7:6:

     3 lfoags, mlvarx, ddlmag, mdload, pnewdt, jprops, njprop, period)
      1
Error: Unclassifiable statement at (1)
aba_param.inc:17:57:

       PARAMETER(IALLD=0,IRMMD=4,NEMPTY=0,ISPIND=2,IGRAD=0)
                                                         1
Error: Unexpected characters in PARAMETER statement at (1)
my_subroutine.for:12:6:

     1 energy(7), coord(mcrd, nnode), u(ndofel), du(mlvarx, *), v(ndofel),
      1
Error: Unclassifiable statement at (1)
my_subroutine.for:13:6:

     2 a(ndofel), time(2), params(*), jdltyp(mdload, *), adlmag(mdload, *),
      1
Error: Unclassifiable statement at (1)
my_subroutine.for:14:6:

     4 ddlag(mdload, *), predef(2, npredf, nnode), lflags(4), jprops(*)
      1
Error: Unclassifiable statement at (1)
my_subroutine.for:46:6:

  svars(2) = fHolder
      1
Error: Unclassifiable statement at (1)
my_subroutine.for:47:6:

  rhs(3,1) = -fHolder
      1
Error: Unclassifiable statement at (1)
my_subroutine.for:48:5:

     else if(kstep.eq.3) then
     1
Error: Non-numeric character in statement label at (1)
my_subroutine.for:48:5:

     else if(kstep.eq.3) then
     1
Error: Unclassifiable statement at (1)
my_subroutine.for:79:6:

  rhs(3,1) = -fHolderNew
      1
Error: Unclassifiable statement at (1)
my_subroutine.for:83:11: Error: 'svars' at (1) is not a variable
my_subroutine.for:84:11: Error: 'svars' at (1) is not a variable
my_subroutine.for:85:11: Error: 'svars' at (1) is not a variable
f951.exe: Error: Unexpected end of file in 'my_subroutine.for'

这种方法并不复杂,您不必担心密钥是否未提供或为空

query = {
  join: [:comments],
  where: {:author => 'Bob'}
}

如果键为空或根本不存在

Article.joins(query[:join]).where(query[:where])
#=> "SELECT  `articles`.* FROM `articles` INNER JOIN `comments` ON `comments`.`article_id` = `articles`.`id` WHERE `articles`.`author` = 'Bob'"

或嵌套

query = {
  join: []
}

Article.joins(query[:join]).where(query[:where])
#=> "SELECT  `articles`.* FROM `articles`"

答案 1 :(得分:1)

我创建了以下查询,该查询将适用于任何模型和关联的链接查询数组。

def chain_queries_on(klass, arr)
  arr.inject(klass) do |relation, query|
    begin
      relation.send(query[0], *query[1..-1])
    rescue
      break;
    end
  end
end

我在本地进行了以下测试,

arr = [['where', {id: [1,2]}], ['where', {first_name: 'Shobiz'}]]

chain_queries_on(Article, arr)

触发的查询如下所示,以返回正确的输出,

Article Load (0.9ms)  SELECT `article`.* FROM `article` WHERE `article`.`id` IN (1, 2) AND `article`.`first_name` = 'Shobiz'  ORDER BY created_at desc

注意-1:少数明显的情况

  1. 对于空的arr,它将返回我们在方法中作为第一个参数传递的class

  2. 如果出现错误,它将返回nil。如果我们使用pluck会返回数组(输出不是可链接的),或者不将类作为第一个参数传递,则可能会发生错误。

可以对上面的内容进行更多的修改以改进并避免出现极端情况。

注2:改进

您也可以使用一个参数(即数组)将此方法定义为Object类的类方法,并直接在类似这样的类上调用

# renamed to make concise
Article.chain_queries(arr)
User.chain_queries(arr)

内部方法,使用self代替klass

答案 2 :(得分:0)

template<>
double get_data_at_timepoint<Foo>(const Foo &obj, size_t index) {
    // Foo related implementation
}