Ruby on rails Rails SQL查询生成器。。。或ActiveRecord查询生成器

Ruby on rails Rails SQL查询生成器。。。或ActiveRecord查询生成器,ruby-on-rails,ruby,ruby-on-rails-3,activerecord,gem,Ruby On Rails,Ruby,Ruby On Rails 3,Activerecord,Gem,我需要像这样运行sql查询 sql = 'SELECT * FROM users WHERE id != ' + self.id.to_s + ' AND id NOT IN (SELECT artner_id FROM encounters WHERE user_id = ' + self.id.to_s + ')' sql += ' AND id NOT IN (SELECT user_id FROM encounters WHERE partner_id = ' + self.id.to_

我需要像这样运行sql查询

sql = 'SELECT * FROM users WHERE id != ' + self.id.to_s + ' AND id NOT IN (SELECT artner_id FROM encounters WHERE user_id = ' + self.id.to_s + ')'
sql += ' AND id NOT IN (SELECT user_id FROM encounters WHERE partner_id = ' + self.id.to_s + ' AND predisposition = ' + Encounter::Negative.to_s + ')'
sql += ' AND cfg_sex = ' + self.sex.to_s + ' AND cfg_country = ' + self.country.to_s + ' AND cfg_city = ' + self.city.to_s
sql += ' ORDER BY rand() LIMIT 1'
它可以由AR.find_by_sql执行,但之前的代码可读性差。 是否有任何查询生成器可以生成该查询

例如,Kohana it is PHP framework,我是PHP开发人员,但我想将该kid语言更改为ruby/rails,并提供一个查询生成器,其工作原理如下:

$sql = DB::select('*')->from('users');
$sql->where('id', 'NOT_IN', DB::expr('SELECT partner_id FROM encounters WHERE user_id = '.$user->id));
$sql->where('id', 'NOT_IN', DB::expr('SELECT user_id FROM encounters WHERE partner_id = '.$user->id.' AND predisposition = '.Encounter::Negative));
....
etc
...
使用查询生成器(类似于Kohana查询生成器)构建的查询更具可读性和可理解性


有什么gem可以解决这个问题吗?

有一个利用关系代数的ruby库。它被称为。如果您使用的是Rails3.x,那么您已经有了

ids   = Partner.where(user_id: self.id).pluck(:partner_id) << self.id
users = User.where("id NOT IN #{ ids.join(',') }")

下面是同样的查询,转换成rails AREL术语。这还不算完美——一般来说,这是一个复杂的查询

User.where("id = ? AND "
           "id NOT IN (SELECT artner_id FROM encounters WHERE user_id = ?) AND " +  
           "id NOT IN (SELECT user_id FROM encounters WHERE partner_id = ? AND predisposition = ? ) AND " + 
            "cfg_sex = ? AND cfg_country = ? AND cfg_city = ?)", 
            self.id, self.id, self.id, Encounter::Negative, 
            self.sex, self.country, self.city).order(" rand() ").limit(1)
我还没有测试过这个,所以可能有打字错误

我推荐几件事:

当你有复杂的where子句时,它们可以链接在一起,AREL通常会很好地将它们重新组合在一起。这允许您在模型类中使用作用域并将它们链接在一起

例如,您可以这样做:

类用户
User.is_of_sex(user.sex).in_city_state_country(user.city, user.state, user.country)
等等

将查询分解为更小的部分还可以更容易地使用RSpec测试特定的部分。它产生了更多模块化的、可维护的代码

有关更多详细信息,请查看您需要的宝石。它使用块扩展AR,并轻松地进行非常复杂的查询

只有几个功能:

# not_in == cool! )
Product.where{id.not_in LineItem.select{product_id}}
# SELECT "products".* FROM "products" WHERE "products"."id" NOT IN 
# (SELECT "line_items"."product_id" FROM "line_items" )

# outer joins on pure Ruby:
LineItem.joins{product.outer}
# LineItem Load (0.0ms)  SELECT "line_items".* FROM "line_items" 
# LEFT OUTER JOIN "products" ON "products"."id" = "line_items"."product_id"

# calcs, aliasing:
Product.select{[avg(price).as(middle)]}
# SELECT avg("products"."price") AS middle FROM "products"

# comparison
Product.where{id != 100500}
Product.where{price<10}

# logical OR
Product.where{(price<10) | (title.like '%rails%')}
# SELECT "products".* FROM "products" WHERE (("products"."price" < 10 OR
# "products"."title" LIKE '%rails%'))

# xxx_any feature (also available xxx_all)
Product.where{title.like_any %w[%ruby% %rails%]}
# SELECT "products".* FROM "products" WHERE (("products"."title" LIKE '%ruby%' OR 
# "products"."title" LIKE '%rails%'))    
注意使用块:{…}这里不是散列。还要注意没有符号


如果您决定选择它,请阅读以此开头的部分,其中包含一个重要的含义

它是否可以在查询中粘贴db表达式,以构建类似“从id!=”的用户中选择*”的查询+self.id.to_s+”和id不在SELECT artner_id FROM containments,其中user_id='+self.id.to_s+?在这种情况下为什么不进行左连接?