How to pass a string to has_many: finder_sql parameter?

In my application, the user has several tickets. Unfortunately, the ticket table does not have user_id: it has user_login (this is an outdated database). I am going to change this someday, but at the moment this change will have too many consequences.

So how can I create the association "user_many: tickets" through the login column ?

I tried the following finder_sql, but it does not work.

class User  < ActiveRecord::Base
  has_many :tickets,
      :finder_sql => 'select t.* from tickets t where t.user_login=#{login}'
  ...
end

I get a weird error:

ArgumentError: /var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:402:in `to_constant_name': Anonymous modules have no name to be referenced by
    from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:2355:in `interpolate_sql'
    from /var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:214:in `qualified_name_for'
    from /var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:477:in `const_missing'
    from (eval):1:in `interpolate_sql'
    from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_proxy.rb:95:in `send'
    from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_proxy.rb:95:in `interpolate_sql'
    from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/has_many_association.rb:143:in `construct_sql'
    from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/has_many_association.rb:6:in `initialize'
    from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations.rb:1032:in `new'
    from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations.rb:1032:in `tickets'
    from (irb):1

I also tried this finder_sql (with double quotes around the login):

:finder_sql => 'select t.* from tickets t where t.user_login="#{login}"'

But it does not work the same way (and in any case, if it works, it will be vulnerable to SQL injection).

In the test database, I added the user_id column in the ticket table and tried to find finder_sql:

:finder_sql => 'select t.* from tickets t where t.user_login=#{id}'

. -, , , , , .

... .

finder_sql :

has_many :tickets_since_subscription,
:finder_sql => ['select t.* from tickets t where t.user_login=?'+
     ' and t.created_at>=?', '#{login}', '#{subscription_date}']

: : foreign_key has_many, id, .

β„– 2: , : has_many : primary_key, , ( id). , , ! , :

has_many tickets, :primary_key="login", :foreign_key="user_login"

, has_many: association_since_subscription.

+5
4

, :primary_key has_many. , :foreign_key .

has_many :tickets, :foreign_key => "user_login", :primary_key => "login"

, has_many docs.

+4

- has_many: tickets_since_subscription, named_scopes:

add:

named_scope :since_subscription, lambda { |subscription_date| { :conditions => ['created_at > ?', subscription_date] }

, :

user.tickets.since_subscription 3.days.ago

user.tickets.since_subscription user.subscription_date

(, subscription_date ).

.

named_scopes, , :

user.tickets.all(:conditions => ['created_at > ?', subscription_date]) 
+2

, :foreign_key has_many. , user_id, user_login, .

. ActiveRecord has_many.

+1

, . has_many, . : some_user.tickets, has_many ( : clear, delete, < <,... ).

def tickets
    return Ticket.find(:all, :conditions=>["user_login = ?", login])
end

, - .

0

All Articles