Coder Social home page Coder Social logo

activerecord-hackery / squeel Goto Github PK

View Code? Open in Web Editor NEW
2.4K 2.4K 215.0 622 KB

Active Record, improved. Live again :)

Home Page: http://erniemiller.org/2013/11/17/anyone-interested-in-activerecord-hackery/

License: MIT License

Ruby 100.00%

squeel's People

Contributors

bigxiang avatar danielrhodes avatar ernie avatar estum avatar fxn avatar iamvery avatar janko avatar joseluistorres avatar mariovisic avatar meskallito avatar peternixey avatar radar avatar richguk avatar scarroll32 avatar simi avatar snkashis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

squeel's Issues

Use object's attributes inside squeel block

I've stumbled upon an issue (rather a missing feature I guess) where I wasn't able to do something like this:

class Post < ActiveRecord::Base
  belongs_to :parent, :class_name => 'Post' # so it has a parent_id attribute

  def posts_without_current_parent
    Post.where{id != parent_id} # => SELECT `posts`.* FROM `posts` WHERE `posts`.`id` != `posts`.`parent_id`
  end
end

As you can see it sees parent_id as an attribute for the new query and not an attribute coming from the main Post object. Doing something like self.parent_id did not resolve it either.
A workaround for this can be:

def posts_without_current_parent
  the_id = parent_id # => 1
  Post.where{id != the_id} # => SELECT `posts`.* FROM `posts` WHERE `posts`.`id` != 1
end

This works as expected but is less clean.

Am I overlooking something or is this intended not to work? Anyway it would be cool to be able to use attributes inside the Squeel block.

[0.7.4] .as() doesn't appear to alias selected columns

When attempting to alias a selected field as a different name I'm trying this:

>> Account.select{test.as(my_field_name)}.debug_sql
=> "SELECT as(\"test\".\"my_field_name\") FROM \"accounts\""

However, if I use the .op syntax to do a whole lot of nothing, it seems to work:

>> Account.select{test.op('||', '').as(my_field_name)}.debug_sql
=> "SELECT \"accounts\".\"test\" || '' AS my_field_name FROM \"accounts\""

Is there a way using the squeel DSL to generate this SQL:

SELECT "accounts"."test" AS my_field_name FROM "accounts"

Note that the reason I want this is because I'm joining a table to itself and pulling the same attribute from the two different tables, and would like the named specifically.

Also the .as() doesn't appear to alias joined association table names. For instance:

>> Account.joins{negative_overflow_account.as(test_relation)}.debug_sql
ActiveRecord::ConfigurationError: #<Squeel::Nodes::Function:0x00000100ea3750 @name=:as, @args=[test_relation]>

Is this behavior expected in a future version? Thanks!

More issues with has_many :through

I found today that squeel breaks creation of has_many through records

In model:

class Survey < ActiveRecord::Base
  has_many :survey_questions, :dependent => :destroy
  has_many :questions, :through => :survey_questions
end

In console:

Survey.first.questions.create

Results in:

ActiveRecord::UnknownAttributeError: unknown attribute: survey_id

is NULL

how can i check if an attribute is null?

breaks has_one :through in Rails 3.1

Squeel throws an "ArgumentException: Unable to get table for [join_table]" when attempting to query through an aliased has_one :through association

class Team < ActiveRecord::Base
  has_many :team_memberships
  has_many :members, through: :team_memberships

  has_one :captaincy, class_name: 'TeamMembership', conditions: {captaincy: true}
  has_one :captain, through: :captaincy, source: :member
end

(the join table TeamMembership has a boolean column captaincy)

When using squeel, Team.captain throws "Unable to get table for team_memberships" on Rails 3.1 (but works on 3.0, and 3.1 without squeel); Team.captaincy works in all cases.

Stack trace: http://pastie.org/1913012

prepending table name when is already set causing invalid sql

Hi Ernie I have the following issue:

Code:

    Volume.select('DISTINCT volumes.*').
      joins(:measurements, :typology).
      includes(:volume_type, :typology).
      where('typologies.project_id' => typology.project_id).
      where('volumes.volume_type_id' => volume_type_id)

Generated sql:

SELECT DISTINCT volumes.* FROM "volumes" INNER JOIN 
"measurements" ON "measurements"."volume_id" = "volumes"."id" INNER JOIN
 "typologies" ON "typologies"."id" = "volumes"."typology_id" WHERE
 "volumes"."typologies.project_id" = 799 AND "volumes"."volumes.volume_type_id" = 225

As you can see Squeel is prepending the "volumes" table name when this value is already set to a different table in the join, without Squeel this code works perfect.

Support order on column of joined table

How can I order on a column of a joined table? Is this supported? I couldn't find it documented nor by trial and error.. :(

Comment.joins(:user).order(:user => {:firstname.desc})

SELECT * FROM comments JOIN users ON (comments.user_id=users.id) ORDER BY users.firstname DESC

find_by_columnname(:symbol) error or incorrect usage?

This likely could be me trying to use things incorrectly--I was just a bit surprised by it:

ree-1.8.7-2011.03 :001 > Partner.find_by_shortname('foo')
Partner Load (0.8ms) SELECT "partners".* FROM "partners" WHERE "partners"."shortname" = 'foo' LIMIT 1

ree-1.8.7-2011.03 :002 > Partner.find_by_shortname(:foo)
Partner Load (0.7ms) SELECT "partners".* FROM "partners" WHERE "partners"."shortname" = "partners"."foo" LIMIT 1
ActiveRecord::StatementInvalid: PGError: ERROR: column partners.foo does not exist
LINE 1: ...* FROM "partners" WHERE "partners"."shortname" = "partners"...

Is that expected?

This was with

config.load_core_extensions :hash

but not

config.load_core_extensions :symbol

Not in with empty array

Hi,
As you can see from this debug session:
Account.where{id.not_in []}.to_sql => "SELECT accounts.* FROM accounts WHERE accounts.id NOT IN (NULL)"
Account.where{id.not_in [nil]}.to_sql => "SELECT accounts.* FROM accounts WHERE accounts.id NOT IN (NULL)"
Account.where{id.not_in [nil,nil,nil]}.to_sql => "SELECT accounts.* FROM accounts WHERE accounts.id NOT IN (NULL, NULL, NULL)"

the behaviour is the same when the array is empty and when the array includes only a nil element.

The behaviour should be (IMHO):
Account.where{id.not_in []}.to_sql => "SELECT accounts.* FROM accounts"
Account.where{id.not_in [nil]}.to_sql => "SELECT accounts.* FROM accounts WHERE accounts.id NOT IN (NULL)"

undefined method `|' for Squeel::Nodes::Function

Hi,

I do some calculations and tests on dates and postgresql provides functions for all that, like "date_le(date1, date2)" which all in all does a "date1 < date2" but allows you to bypass some casting. (Like using 'now' which will be casted to a date in the first case but won't in the second case.)

So, I tried :

where{(timestamptz_ge(date_creation, timestamptz_mi_interval('now', '10 hour'))) | (date_le(date(date_modif), date_mii('now', 7)))}

which I'd love it to generate :

((timestamptz_ge("domaine_handle"."date_creation", timestamptz_mi_interval('now', '10 hour')) OR date_le(date("domaine_handle"."date_modif"), date_mii('now', 7))))

but right now, well, does not work :-)

ActiveRecord::StatementInvalid

user = User.where{ {login => params[:login]} | {email => params[:login]} }.first

produces
PGError: ERROR: syntax error at or near "[" LINE 1: SELECT "users".* FROM "users" WHERE (([]("params"."login")...

How to search with 'matches %...%' ?

Hello,

When I do

Person.search(:name_matches => 'Boo').result

the SQL request looks like

SELECT "people".* FROM "people" WHERE "people"."name" LIKE 'Boo'

The :name_matches => 'Boo' part is what I get in params[:q]. What's the easiest way to generate the same SQL request with value surrounded by % ?

Thankyou

Name Error

It's not called EQL.

Sorry, couldn't resist.

invalid date format in gemspec

When installing the squeel gem on our build server (debian, rvm, ruby 1.9.2), I get the following error:

Invalid gemspec in [/home/bamboo/.rvm/gems/ruby-1.9.2-p136@rem2/specifications/squeel-0.8.4.gemspec]: invalid date format in specification: "2011-06-20 00:00:00.000000000Z"

No problems on my local OSX. After editing the gemspec file manually on the server, everything runs fine.

Rewriting meta_where to squeel

Hey ernie,

I am trying to rewrite some of my old meta_where queries to squeel queries as part of an upgrade to Rails 3.1 but I am running into problems:

Here is a query I am trying to rewrite:

account.pages.where(parent_id: parent_id_was, :id.not_eq => id, :position.gt => position).each do |page|
  page.decrement!(:position)
end

As you can see it is a mix of the new Ruby 1.9 syntax and the old meta_where (which can't be used with the 1.9 syntax).

I tried the following but it gives me an error saying there is no column parent_id_was, which obviously is not what I want. I am trying to use Dirty objects

any idea what I am doing wrong?

account.pages.where{(parent_id.eq parent_id_was) & (id.not_eq id) & (position.gt position)}.each do |page|
  page.decrement!(:position)
end
ActiveRecord::StatementInvalid (SQLite3::SQLException: no such column: pages.parent_id_was: SELECT "pages".* FROM "pages" INNER JOIN "themes" ON "pages"."theme_id" = "themes"."id" WHERE "themes"."account_id" = 1 AND (("pages"."parent_id" = "pages"."parent_id_was" AND "pages"."id" != "pages"."id" AND "pages"."position" > "pages"."position")) ORDER BY position ASC):
  app/models/page.rb:240:in `update_positions'
  app/controllers/pages_controller.rb:41:in `update'

The name 'squeel' is kind of lame.

(This is opinion.)

So I was talking to the rest of my team about the new version of metawhere, which is called "squeel". The moment I mentioned the name, everyone started laughing, somewhat derisively.. My friend says, "It'll go great with HAML!"

Ok, that was kind of funny. But, honestly, being a little embarrassed about the name actually makes me slightly less likely to use it. Even though I've used metawhere and I know the quality of Ernie's code and dedication to making the plugin awesome is completely top-notch. I thought Metawhere was really a kickass name.

I strongly encourage a Metawhere 2.0... I'll probably keep using the plugin regardless of what it's called, but if I was a new user perusing options, I'd probably just pass Squeel right over because it just sounds kind of lame.

(end opinion)

cannot handle custom range classes

I have a custom date range class, derived from Range that lives in lib/extensions:

class DateRange < Range
...
end

class Person < ActiveRecord::Base
scope :born_within, lambda { |date_range| where {{ date_of_birth => date_range }}}
end

In the rails console:

range = DateRange.new Date.new(1960,1,1), Date.new(170,12,31)
people = Person.born_within range

TypeError: Cannot visit DateRange
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/visitor.rb:25:in rescue in visit' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/visitor.rb:19:invisit'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:347:in visit_Arel_Nodes_Equality' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/visitor.rb:19:invisit'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:329:in block in visit_Arel_Nodes_And' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:329:inmap'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:329:in visit_Arel_Nodes_And' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/visitor.rb:19:invisit'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:138:in block in visit_Arel_Nodes_SelectCore' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:138:inmap'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:138:in visit_Arel_Nodes_SelectCore' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:123:inblock in visit_Arel_Nodes_SelectStatement'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:123:in map' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:123:invisit_Arel_Nodes_SelectStatement'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/sqlite.rb:7:in visit_Arel_Nodes_SelectStatement' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/visitor.rb:19:invisit'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/visitor.rb:5:in accept' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:20:inblock in accept'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/activerecord-3.1.0.rc4/lib/active_record/connection_adapters/abstract/connection_pool.rb:174:in with_connection' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/visitors/to_sql.rb:18:inaccept'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/arel-2.1.3/lib/arel/tree_manager.rb:21:in to_sql' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/activerecord-3.1.0.rc4/lib/active_record/relation.rb:109:into_a'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/activerecord-3.1.0.rc4/lib/active_record/relation.rb:423:in inspect' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/railties-3.1.0.rc4/lib/rails/commands/console.rb:45:instart'
from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/railties-3.1.0.rc4/lib/rails/commands/console.rb:8:in start' from /Users/gernot/.rvm/gems/ruby-1.9.2-p180@global/gems/railties-3.1.0.rc4/lib/rails/commands.rb:40:in<top (required)>'
from script/rails:6:in `require'

.order causes failure when used with kaminari's .page

Using kaminari for pagination, I have a Squeel line to render a message inbox. This was working fine for weeks, until my project decided to switch from SQLite to the Postgres adapter, 'pg version 0.11.0'.

  1. For testing, I went back and checked it again on a SQLite DB, and it's fine.

  2. Without the ".page" call, this statement is fine.

  3. Without the .order clause, this statement is fine.

  4. A really simple combination, User.order{created_at}.page 1, works fine.

    class MessageThread
    has_many :messages, :order => 'created_at', :dependent => :destroy
    belongs_to :user

    def self.in_inbox
    where{message_thread_users.hidden_at == nil}.
    where{ exists( Message.where{ (user_id ^ message_thread_users.user_id) & (message_thread_id == message_threads.id)}.select{1}) }
    end

    def self.by_recency
    includes{:messages}.order{[message_threads.updated_at.desc, messages.created_at.desc, message_threads.id.desc]}
    end

    end

    class User
    has_many :message_thread_users
    has_many :message_threads, :through => :message_thread_users
    end

    irb(main):013:0> current_user.message_threads.in_inbox.includes{:messages}.order{message_threads.updated_at.desc}.page 1

    Hirb Error: undefined method index' for #<Arel::Nodes::Ordering:0xb580914c> /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/postgresql.rb:51:inaliased_orders'
    /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:17:in each_with_index' /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/postgresql.rb:47:ineach'
    /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/postgresql.rb:47:in each_with_index' /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/postgresql.rb:47:inaliased_orders'
    /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/postgresql.rb:19:in visit_Arel_Nodes_SelectStatement' /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:15:insend'
    /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:15:in visit' /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:5:inaccept'
    /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:18:in accept' /var/lib/gems/1.8/gems/activerecord-3.0.9/lib/active_record/connection_adapters/abstract/connection_pool.rb:111:inwith_connection'
    /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:16:in accept' /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/tree_manager.rb:20:into_sql'
    /var/lib/gems/1.8/gems/activerecord-3.0.9/lib/active_record/relation.rb:64:in to_a' /var/lib/gems/1.8/gems/activerecord-3.0.9/lib/active_record/relation.rb:15:incollect'
    /var/lib/gems/1.8/gems/activerecord-3.0.9/lib/active_record/relation/finder_methods.rb:236:in construct_limited_ids_condition' /var/lib/gems/1.8/gems/activerecord-3.0.9/lib/active_record/relation/finder_methods.rb:223:inapply_join_dependency'
    /var/lib/gems/1.8/gems/activerecord-3.0.9/lib/active_record/relation/finder_methods.rb:212:in construct_relation_for_association_find' /var/lib/gems/1.8/gems/activerecord-3.0.9/lib/active_record/relation/finder_methods.rb:192:infind_with_associations'
    /var/lib/gems/1.8/gems/activerecord-3.0.9/lib/active_record/relation.rb:64:in to_a' /var/lib/gems/1.8/gems/activerecord-3.0.9/lib/active_record/relation.rb:366:inmethod_missing'
    /var/lib/gems/1.8/gems/hirb-0.4.5/lib/hirb/formatter.rb:88:in Array' /var/lib/gems/1.8/gems/hirb-0.4.5/lib/hirb/formatter.rb:88:indetermine_output_class'
    /var/lib/gems/1.8/gems/hirb-0.4.5/lib/hirb/formatter.rb:53:in format_output' /var/lib/gems/1.8/gems/hirb-0.4.5/lib/hirb/view.rb:204:inrender_output'
    /var/lib/gems/1.8/gems/hirb-0.4.5/lib/hirb/view.rb:123:in view_output' /var/lib/gems/1.8/gems/hirb-0.4.5/lib/hirb/view.rb:200:inview_or_page_output'
    /var/lib/gems/1.8/gems/hirb-0.4.5/lib/hirb/view.rb:186:in output_value' /usr/lib/ruby/1.8/irb.rb:159:ineval_input'
    /usr/lib/ruby/1.8/irb.rb:271:in signal_status' /usr/lib/ruby/1.8/irb.rb:155:ineval_input'
    /usr/lib/ruby/1.8/irb/ruby-lex.rb:244:in each_top_level_statement' /usr/lib/ruby/1.8/irb/ruby-lex.rb:230:inloop'
    /usr/lib/ruby/1.8/irb/ruby-lex.rb:230:in each_top_level_statement' /usr/lib/ruby/1.8/irb/ruby-lex.rb:229:incatch'
    /usr/lib/ruby/1.8/irb/ruby-lex.rb:229:in each_top_level_statement' /usr/lib/ruby/1.8/irb.rb:154:ineval_input'
    /usr/lib/ruby/1.8/irb.rb:71:in start' /usr/lib/ruby/1.8/irb.rb:70:incatch'
    /usr/lib/ruby/1.8/irb.rb:70:in start' /var/lib/gems/1.8/gems/railties-3.0.9/lib/rails/commands/console.rb:44:instart'
    /var/lib/gems/1.8/gems/railties-3.0.9/lib/rails/commands/console.rb:8:in start' /var/lib/gems/1.8/gems/railties-3.0.9/lib/rails/commands.rb:23 script/rails:6:inrequire'
    script/rails:6

Rails 3.0.9, ruby 1.8.7, Squeel 0.8.5, kaminari 0.12.4

1.9.2 issues with multiple joins to the same table

I'm getting some strange behavior running ruby 1.9.2 with the latest squeel 0.8.6 and rails 3.0.9.

I have a scope which works fine most of the time but other times gives a TypeError: Cannot visit FalseClass error with the same input arguments.
I've included the relavent code below. I would investigate further but my squeel + AR knowledge is a bit limited.

# app/models/blocking.rb
class Blocking < ActiveRecord::Base
  belongs_to :blocker, :class_name => 'User'
  belongs_to :blockee, :class_name => 'User'
end

# app/models/user.rb
class User < ActiveRecord::Base
  has_many :outgoing_blocks, :class_name => 'Blocking', :foreign_key => :blocker_id
  has_many :incoming_blocks, :class_name => 'Blocking', :foreign_key => :blockee_id

  def self.unblocked(our_user)
    unblocked = joins{[outgoing_blocks.outer, incoming_blocks.outer]}
    unblocked = unblocked.where{ ((outgoing_blocks.blocker_id.not_eq our_user.id) & (incoming_blocks.blocker_id.not_eq our_user.id)) }
    unblocked = unblocked.where{ ((outgoing_blocks.blockee_id.not_eq our_user.id) & (incoming_blocks.blockee_id.not_eq our_user.id)) }
  end
end

# db/schema.rb
ActiveRecord::Schema.define(:version => 20110804072533) do
  create_table "users", :force => true do |t|
  end
  create_table "blockings", :force => true do |t|
    t.integer  "blocker_id", :null => false
    t.integer  "blockee_id", :null => false
  end
end

Here is the stack trace:

ruby-1.9.2-p290 :050 > User.unblocked(User.first)
TypeError: Cannot visit FalseClass
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/base.rb:104:in `rescue in visit'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/base.rb:97:in `visit'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/predicate_visitor.rb:64:in `visit_Squeel_Nodes_KeyPath'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/base.rb:97:in `visit'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/predicate_visitor.rb:43:in `block in visit_Array'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/predicate_visitor.rb:43:in `map'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/predicate_visitor.rb:43:in `visit_Array'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/base.rb:97:in `visit'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/predicate_visitor.rb:197:in `visit_Squeel_Nodes_And'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/base.rb:97:in `visit'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/predicate_visitor.rb:43:in `block in visit_Array'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/predicate_visitor.rb:43:in `map'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/predicate_visitor.rb:43:in `visit_Array'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/base.rb:97:in `visit'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/visitors/base.rb:26:in `accept'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/squeel-0.8.6/lib/squeel/adapters/active_record/3.0/relation.rb:82:in `build_arel'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/activerecord-3.0.9/lib/active_record/relation/query_methods.rb:149:in `arel'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/activerecord-3.0.9/lib/active_record/relation.rb:64:in `to_a'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/activerecord-3.0.9/lib/active_record/relation.rb:359:in `inspect'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/railties-3.0.9/lib/rails/commands/console.rb:44:in `start'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/railties-3.0.9/lib/rails/commands/console.rb:8:in `start'
  from /Users/mariovisic/.rvm/gems/[email protected]/gems/railties-3.0.9/lib/rails/commands.rb:23:in `<top (required)>'
  from script/rails:6:in `require'
  from script/rails:6:in `<main>'ruby-1.9.2-p290 :051 > User.unblocked(User.first)

If you could point me in the right direction that would help, I might be able to patch it myself. Let me know if you need any further info.

Cheers

KeyPaths not responding to !=

Hiya, found an issue trying to use != on a fully qualified attribute; here's a minimal example.

Person.where{first_name != 'Andy'}.to_sql
#=> SELECT "people".* FROM "people" WHERE "people"."first_name" != 'Andy'

Person.where{person.first_name != 'Andy'}.to_sql
#=> SELECT "people".* FROM "people" 

person.first_name == 'Andy' produces the WHERE clause correctly.

Same issue whether on edge Rails or Rails 3.0.7 (both under Ruby 1.9.2)

Ordering bug

Found this annoying issue today:

User.order(:created_at).first
=> SELECT `users`.* FROM `users` ORDER BY `users`.`created_at` LIMIT 1

User.order(:created_at).last
=> SELECT `users`.* FROM `users` ORDER BY `users`.`created_at` LIMIT 1

User.order("created_at").last
=> SELECT `users`.* FROM `users` ORDER BY created_at DESC LIMIT 1

When using squeel symbols, .last doesn't change the direction of the ORDER BY clause and issues a result that is the same as calling .first

(My)SQL BETWEEN syntax

Is it possible to use the BETWEEN syntax? I've tried various things but it seems to be unsupported:

Post.where{created_at = 1.week.ago..Time.zone.now} # => TypeError: Cannot visit Range
Post.where{created_at >> 1.week.ago..Time.zone.now} # => ArgumentError: bad value for range

If not supported yet, are there any plans to do so?

Thanks

private method `desc' called for :created_at:Symbol

Rails 3.0.7

<class:InfoBox>': private methoddesc' called for :created_at:Symbol (NoMethodError)

When switching back to meta_where works ok.

Here's scope:

default_scope where("status != 'Deleted'").order(:created_at.desc)

Thx 4 reply :)

NoMethodError: undefined method `outer' for #<Class:0xa5a698c>

Hi Ernie, I have the following issue:

Given that:

class Measurement < ActiveRecord::Base
  belongs_to :project
end

In console:

  1. working with symbols everything is ok:
Measurement.joins {:project.outer}
=> Measurement Load (0.8ms)  SELECT "measurements".* FROM "measurements" LEFT OUTER JOIN "projects" ON "projects"."id" = "measurements"."project_id"
  1. working with the new syntax throws the following error:
Measurement.joins {project.outer}
=> NoMethodError: undefined method `outer' for #<Class:0xa5a698c>
    from /home/diego/.rvm/gems/ruby-1.9.2-p180/gems/activerecord-3.0.7/lib/active_record/base.rb:1009:in `method_missing'
    from (irb):4:in `block in irb_binding'
    from /home/diego/.rvm/gems/ruby-1.9.2-p180/gems/squeel-0.6.0/lib/squeel/dsl.rb:31:in `instance_eval'
    from /home/diego/.rvm/gems/ruby-1.9.2-p180/gems/squeel-0.6.0/lib/squeel/dsl.rb:31:in `eval'
    from /home/diego/.rvm/gems/ruby-1.9.2-p180/gems/squeel-0.6.0/lib/squeel/adapters/active_record/3.0/relation.rb:199:in `joins'
    from /home/diego/.rvm/gems/ruby-1.9.2-p180/gems/activerecord-3.0.7/lib/active_record/base.rb:442:in `joins'
    from (irb):4
    from /home/diego/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.7/lib/rails/commands/console.rb:44:in `start'
    from /home/diego/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.7/lib/rails/commands/console.rb:8:in `start'
    from /home/diego/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.7/lib/rails/commands.rb:23:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

[Feature request] Time calculation

For both MetaWhere and Squeel it would be really nice to have database independent date computation.
Normally databases have methods such as HOUR, MINUTES, DAY, etc. For application doing a lot of querying on date, having the possibility to write where(:date.hour.gte => 8).where(:date.hour.lte => 12) would be a great thing !
I don't know how difficult this can be ... so just creating an issue to propose the idea.

aliased columns do not work in where conditions

class Award < ActiveRecord::Base
    # has a column  :type, :string
end

Award.select{type.as foo}.where{foo == 'SimpleAward'}

generates the error

  Award Load (0.1ms)  SELECT "awards"."type" AS foo FROM "awards" WHERE "awards"."foo" = 'SimpleAward'
SQLite3::SQLException: no such column: awards.foo: SELECT "awards"."type" AS foo FROM "awards"  WHERE "awards"."foo" = 'SimpleAward'
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: awards.foo: SELECT "awards"."type" AS foo FROM "awards"  WHERE "awards"."foo" = 'SimpleAward'

however I'd expect it to generate the SQL

  SELECT "awards"."type" AS foo FROM "awards" WHERE "foo" = 'SimpleAward'

dropping the prefix.

Is this possible or does it contradict with another use case of SQUEEL. My use case is a bit more complex than the above. I'm actually creating an extension to ActiveRecord with objects not backed by a table.

class VirtualRecord < ActiveRecord::Base
  def self.columns() 
    @columns ||= [] 
  end  

  def self.columns_hash()
    @columns_hash ||= {}
  end

  def self.column(name, sql_type = :string, default = nil, null = true)  
    column = ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)  

    columns << column
    columns_hash[name.to_s] = column   
  end  

  self.abstract_class = true

  def self.table_name
    to_s.underscore.pluralize
  end

  def readonly?
    true
  end

end

and

class AwardTypeView < VirtualRecord
  column :award_type, :string

  default_scope do
    select{awards.type.as award_type}.from("awards")
  end
end

where

AwardTypeView.all

returns data as expected but

AwardTypeView.where{award_type="SimpleAward"}

generates the same error as the first example

AwardTypeView.where{award_type=="SimpleAward"}

SELECT "awards"."type" AS award_type FROM awards WHERE  "award_type_views"."award_type" = 'SimpleAward'

again the aliased virtual column award_type is prefixed by the class name of the object **award_type_views".

The problem is not specific to my hacking active record but I thought you might be interested in my use case.

Regards

Brad

Support subqueries in select

May be it's already suppored and I'm only to dump to get it working.... otherwise it'd be nice if it'd be supported :)

latest_post = Comment.select([:id]).where{user_id == user.id}.order{id.desc}.limit(1)
User.select([:id, username, latest_post => :latest_post_id])

Should produce something like

SELECT id,username,(SELECT id FROM comments WHERE user_id=users.id ORDER BY id DESC LIMIT 1) AS latest_post_id FROM users

set_table_name

It is not work with set_table_name, only with real db table name. It is needed to work with legacy databases.

Gemspec seems to have an invalid date (0.8.0)

Getting this error while trying to use the gem in my project:
Invalid gemspec in [/Users/tanel/.rvm/gems/ruby-1.9.2-p180/specifications/squeel-0.8.0.gemspec]: invalid date format in specification: "2011-06-13 00:00:00.000000000Z"

Note that this causes bundler to cry about the gem not being installed although it really is.

Support references across clauses

It would be great to be able to symbolically reference across clauses, just like in SQL. For example, if I'm transforming a column value with a function in the SELECT clause and aliasing it with a name, it would be nice to be able to refer to that name in the WHERE clause, without repeating the transformation. Also, if the transformation is complex or unfamiliar, the name helps to communicate the transformation's intent into the future.

I don't expect this is a performance issue (hopefully the RDBMS will not recalculate the value for ever appearance of the transformation), but it would aid maintainability to be able to use symbolic references.

Support Postgres casting functions

Postgres casting functions come in two flavors, to my knowledge. The first is for general typecasting/coercion, and uses either a postfix notation (literal_value_or_variable::new_type) or a function-call style (CAST(literal_value_or_variable AS new_type)). The second is for time/date/interval typecasting/coercion, and uses a prefix notation: interval '1 week'; this notation cannot include parentheses.

Maybe I missed something, but it looks like its currently impossible to capture either of these function types in Squeel.

Here are some docs on CAST:
http://www.postgresql.org/docs/8.0/static/sql-expressions.html#SQL-SYNTAX-TYPE-CASTS

Here are docs on time/date/interval:
http://www.postgresql.org/docs/8.0/static/datatype-datetime.html

TypeError: Cannot visit Arel::SelectManager

Hi,

I'm trying to do the following:

class Shoutout < ActiveRecord::Base
  scope :during_room_availability, lambda { |room|
    where{
      datediff(check_out, check_in).eq  
      Availability.select{count(`*`)}.where{
        (room_id.eq room.id) & (inquiry_id.eq nil) & 
        (date.gte shoutouts.check_in) & (date.lte date_add(shoutouts.check_out, `INTERVAL -1 DAY`))} }
}
end

and am expecting the following SQL output:

WHERE datediff(shoutouts.check_out, shoutouts.check_in) = 
(SELECT COUNT(*) FROM availabilities WHERE 
  availabilities.room_id = #{room.id} AND availabilities.inquiry_id IS NULL AND 
  availabilities.date >= `shoutouts`.check_in AND availabilities.date <= date_add(shoutouts.check_out, INTERVAL -1 DAY))

But unfortunately this fails with TypeError: Cannot visit Arel::SelectManager

Any other way I can achieve this?

Parent.includes(:children) breaks with Squeel (when no primary key)

For a legacy "Parent" model with no primary key, the .includes() method works correctly without Squeel:

`````` Parent.includes(:children)```
gives

SELECT children.* FROM children WHERE (children.id IN (x1, x2, x3, ...))```

With Squeel, the same command gives
```SELECT parents.* FROM parents
SELECT children.* FROM children WHERE (children.id = x1)```
where x1 is the same id in both cases.

This is also the case when using Squeel notation,
```Parent.includes{children}```

Can't call the lower SQL function

Hi,

first, thanks for this awesome gem!

We are moving from MetaWhere to Squeel but we run into the issue where we can't call the lower SQL function (other SQL functions can't be called too, but we are mainly interested in lower right now), like this:

User.where { lower(email) == "[email protected]" }

We got a undefined method 'with_connection' for ActiveRecord::Base:Class exception when we try to call this.

We are using Ruby 1.9.2, Rails 3.1 edge on the '3-1-stable' branch and Squeel edge.

Any idea why it's failing?

Thanks!

cannot access member variables inside a squeel block

This might be by design, but anyway: Inside a squeel block I obviously have a different context. Therefore, I cannot access member variables from the class containing the squeel query (the following code does not make much sense, just wants to show the the problem):

class Repository

def initialize(name)
@name = name
end

def get_people
# @name is nil inside the squeel block
Person.where { name == @name }
end

end

no support for 'exists' subqueries

You can do:

Article.where{author_id.in( awesome_people.select{id} )} 

But the support for functions doesn't allow this:

Article.where{(author_id == 1) & ( exists(awesome_people.select{id.gt 1}) ) }

Error Stack:

TypeError: Cannot visit ActiveRecord::Relation
from /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:21:in visit' from /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:5:inaccept'
from /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:18:in accept' from /var/lib/gems/1.8/gems/activerecord-3.0.9.rc5/lib/active_record/connection_adapters/abstract/connection_pool.rb:111:inwith_connection'
from /var/lib/gems/1.8/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:16:in accept' from /var/lib/gems/1.8/gems/squeel-0.8.0/lib/squeel/visitors/base.rb:85:inquote'
from /var/lib/gems/1.8/gems/squeel-0.8.0/lib/squeel/visitors/predicate_visitor.rb:123:in visit_Squeel_Nodes_Function' from /var/lib/gems/1.8/gems/squeel-0.8.0/lib/squeel/visitors/predicate_visitor.rb:114:inmap'
from /var/lib/gems/1.8/gems/squeel-0.8.0/lib/squeel/visitors/predicate_visitor.rb:114:in visit_Squeel_Nodes_Function' from /var/lib/gems/1.8/gems/squeel-0.8.0/lib/squeel/visitors/base.rb:98:insend'

etc.

Conflicting syntax with validations

Squeel does use the correct value due to conflicting syntax when used with custom validations.

validate :custom_validation

Ruby code

private 
  def custom_validation
    if Flag.where("flags.id != ?", id).exists?
      errors.add :base, 'Error"
    end
  end
end
#SQL: SELECT 1 FROM `flags` WHERE `flags`.`id` != 1 LIMIT 1

Squeel Code

private 
  def custom_validation
     if Flag.where{id != id}).exists?
       errors.add :base, 'Error"
    end
  end
end
#SQL: SELECT 1 FROM `flags` WHERE `flags`.`id` != `flags`.`id` LIMIT 1

Note: This is a shortened version of my actual code, I have additional where clauses in the validation

has_many :through with :source broken (undefined method `klass' for nil:NilClass)

Hi there,

I tried using squeel today and it broke my has_many :through associations when I manually specify a :source. e.g.

has_many :memberships, :class_name => "Community::Membership", :dependent => :destroy
has_many :members, :through => :memberships, :source => :user

I don't have time to look into what's going on atm, but thought I'd post my stack trace, in case it's of interest to you.

Thanks,
iHiD

NoMethodError: undefined method `klass' for nil:NilClass
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activesupport/lib/active_support/whiny_nil.rb:48:in `method_missing'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activerecord/lib/active_record/reflection.rb:391:in `block in source_reflection'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activerecord/lib/active_record/reflection.rb:391:in `collect'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activerecord/lib/active_record/reflection.rb:391:in `source_reflection'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activerecord/lib/active_record/reflection.rb:538:in `derive_class_name'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activerecord/lib/active_record/reflection.rb:128:in `class_name'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/squeel-67edfcb84837/lib/squeel/adapters/active_record/relation.rb:59:in `block in infer_association_for_relation_merge'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/squeel-67edfcb84837/lib/squeel/adapters/active_record/relation.rb:59:in `each'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/squeel-67edfcb84837/lib/squeel/adapters/active_record/relation.rb:59:in `detect'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/squeel-67edfcb84837/lib/squeel/adapters/active_record/relation.rb:59:in `infer_association_for_relation_merge'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/squeel-67edfcb84837/lib/squeel/adapters/active_record/relation.rb:46:in `merge'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activerecord/lib/active_record/associations/through_association.rb:17:in `block in target_scope'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activerecord/lib/active_record/associations/through_association.rb:16:in `each'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activerecord/lib/active_record/associations/through_association.rb:16:in `target_scope'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activerecord/lib/active_record/associations/association.rb:88:in `scoped'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activerecord/lib/active_record/associations/collection_proxy.rb:47:in `scoped'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/activerecord/lib/active_record/associations/collection_proxy.rb:102:in `method_missing'
    from (irb):1
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/railties/lib/rails/commands/console.rb:45:in `start'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/railties/lib/rails/commands/console.rb:8:in `start'
    from /Users/iHiD/.rvm/gems/ruby-1.9.2-p180/bundler/gems/rails-7ee15e8a0f84/railties/lib/rails/commands.rb:40:in `<top (required)>'

unable to generate subquery

Hi,

I'm trying to generate :

SELECT "contrat".*
FROM "contrat"
WHERE nb_doms("contrat"."contrat") != (select count(id) from domains where domains.contrat_id = contrat.id_contrat);

but I can't get my way around having it generate the right subquery, most of the time, it generate something that does not make sense like if I do :

nb_doms(contrat.contrat) != domains.select{count(id)}

it does :

nb_doms("contrat"."contrat") != "domains"."select"

and the rest of the time, it gives me a "Cannot visit Arel::SelectManager", like if I do :

nb_doms(contrat.contrat) != Domain.where{contrat_id == contrat.id}.select{count(id)}

OCIError: ORA-01704: string literal too long

Hi,

I'm receiving the following error when using the activerecord-oracle_enhanced-adapter and squeel:

OCIError: ORA-01704: string literal too long

I'm using ActiveRecord/Rails 3.0.9, activerecord-oracle_enhanced-adapter 1.3.2 and squeel 0.8.5.

To reproduce this error:

$ cat Gemfile
source 'http://rubygems.org'
gem 'rails', '3.0.9'
gem 'ruby-oci8'
gem 'activerecord-oracle_enhanced-adapter'
gem "squeel"

$ rails generate model Post content:text

$ rake db:migrate

$ rails console
$> p = Post.create(:content => "a")
$> p.content = "b" * 4001
$> p.save

The problem is that the value is longer than 4000 characters even though it is a clob that allows for more, and the value is placed directly in the SQL query as a string which is not allowed. The weird thing is that the create call with a value for content that is longer than 4000 characters works perfectly.

If I don't put squeel in the Gemfile, then the save above works perfectly.

inner join mentioned twice in acts-as-taggable-on, blows up postgres

hey Ernie,

Just had a bit of a mind bender before tracking this down. Was sure it was a rails edge thing, but then created a new app and things were fine there.

When I include squeel in a postgres/rails edge project, and try to use acts-as-taggable-on, I get the following

"taggable_type" = 'Board' AND (taggings.context = 'interests' AND taggings.tagger_id IS NULL)
ActiveRecord::StatementInvalid: PGError: ERROR: table name "taggings" specified more than once
: SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "taggings"."tag_id" = "tags"."id" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" IS NULL AND "taggings"."taggable_type" = 'Board' AND (taggings.context = 'interests' AND taggings.tagger_id IS NULL)

without squeel it's normal:

ActsAsTaggableOn::Tag Load (5.1ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" IS NULL AND "taggings"."taggable_type" = 'Board' AND (taggings.context = 'interests' AND taggings.tagger_id IS NULL)
=> []
ree-1.8.7-2011.03 :005 > exit

has many through and 'Not unique table/alias'

When joining on the table used in the through portion of a has_many :through=>... the sequel joins the same table twice
Simplifying my query down and using the schema from the specs it is similar to (but with more conditions) Person.first.authored_article_comments.joins{article.tags} which produces the following invalid sequel and throws a 'Not unique table/alias' error due to joining on "articles" twice

SELECT "comments".* FROM "comments" INNER JOIN "articles" ON "articles"."id" = "comments"."article_id" INNER JOIN "articles_tags" ON "articles_tags"."article_id" = "articles"."id" INNER JOIN "tags" ON "tags"."id" = "articles_tags"."tag_id" INNER JOIN "articles" ON "comments"."article_id" = "articles"."id" WHERE "articles"."person_id" = 1

Is there a solution/workaround for this?

Cannot visit String

I'm getting this error just after installing squeel gem. I'm on Rails 3.1.rc5.

Cannot visit String


Extracted source (around line #22): 
19:         %th End time
20:         %th Spent
21: 
22:       = render :partial => 'task', :collection => @tasks

Complex joins are translated wrongly in PostgreSQL

Hi Ernie,
I was experiencing your good gem, and I've been able to write a quite complex query. Here's the scenario:
I've ModelA which has many ModelB
What I needed is to count B occurrences for every A item. I came up with this:

ModelA.joins{modelb}.group{modelb.modela_id}.select{"modela_id.*, count("modelbs"."modela_id") as modelb_count"}.order{"modelb_count desc"}

Which works well in sqlite and mysql as well.
In PostgreSQL it doesn't works. It gets translated this way:

SELECT modelas.*, count("modelbs"."modela_id") as modelbs_count FROM "modelas" INNER JOIN "modelbs" ON "modelbs"."modela_id" = "modelas"."id" GROUP BY "modelbs"."modela_id" ORDER BY modelbs_count desc

One "right" translations, according with [this][http://stackoverflow.com/questions/1769361/postgresql-group-by-different-from-mysql] should be:

SELECT modelas.*, countt from modelas, (SELECT modelbs.modela_id, count(modelbs.modela_id) as countt FROM modelbs GROUP BY modelbs.modela_id) modelbs where modelas.id=modelbs.modela_id ORDER BY countt DESC ;

Another solution should be to join non related data, this way (WARNING: not working):

ModelA.joins{Modelbs.select{"modelbs.modela_id, count(modelbs.modela_id) as countt"}.group{modelbs.modela_id}.order("countt DESC")}

But this, of course, fails due non existance of ModelB for ModelA.

I'll provide an step-by-step to reproduce the issue asap.

Self referential many to many join with aliased keys

Hey Ernie,

First, thanks for the awesome gem! It's helping to make ActiveRecord more bearable after working with DataMapper for a while.

After adding squeel to one of my projects I'm getting an undefined method 'class_name' for nil:NilClass error on a self referential many to many join with aliased keys.

Its coming from Squeel::Adapters::ActiveRecord::Relation#infer_association_for_relation_merge squeel-0.8.5/lib/squeel/adapters/active_record/relation.rb:59 which is calling .class_name on a non-existent class target.

Here's the codz.

class Product < ActiveRecord::Base
  has_many  :product_relations, :foreign_key => :source_id
  has_many  :products, :through => :product_relations, :source => :target
end
class ProductRelation < ActiveRecord::Base
  belongs_to :source, :class_name => 'Product'
  belongs_to :target, :class_name => 'Product'
end
class CreateProductRelations < ActiveRecord::Migration
  def change
    create_table :product_relations do |t|
      t.integer :source_id, :null => false
      t.integer :target_id, :null => false
    end
  end
end

The error occurs when calling @product.products.

I wish I had the time to get stuck into this but I don't

Aliased column for aggregated results and (missing) subselects

Domain.group(:publication_id).select { count('*').as(cnt) }.where { cnt > 1 }

should generate a subquery instead of

SELECT count('*') AS cnt FROM "domains" WHERE "domains"."cnt" > 1 GROUP BY "domains"."publication_id"

which obviously fails due to the scoping of cnt.

Cannot visit error when using normal ARel interface

If I do:

Post.where(:network_id => networks, :author_id => current_user).order('scheduled_at DESC, created_at DESC')

while using squeel, I get a cannot visit error on the User class.
If I change current_user to current_user.id, the error changes to 'cannot visit Arel::SelectManager'
Which in turn goes away if I change networks to networks.collect {|n| n.id}.

Which, put together makes:

Post.where(:network_id => networks.collect {|n| n.id}, :author_id => current_user.id).order('scheduled_at DESC, created_at DESC')

So it appears that squeel presently breaks the normal ARel where function's ability to implicity call id on a model or collection of models.

This occured while using Rails 3.0.7, Ruby 1.8.7-p334, Ubuntu 11.04 and squeel 0.5.5

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.