Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

ActiveRecord::Relation select problem #6331

Closed
kot-begemot opened this Issue May 15, 2012 · 1 comment

Comments

Projects
None yet
2 participants

I am currently writing a gem that dump destroying records. The idea of the gem is that it will provide several ways to dump the deleted data for most popular ORMs, and one of them is to move record into remote database. Currently, I am integrating it with ActiveRecord. I am trying to us ActiveRecord::Relation for communication with database. So far I am facing two big major problems:

First obstacle I faced so far is, that is it's really hard to replace the connection. I have managed to do so by duplicating a model object internally and overwriting several methods and feeding this duplication to ActiveRecord::Relation instance on creation, but it seems to be a hackish solution. So, now I am truing to use ActiveRecord::Relation for the full power, but it turns out that the communication with database happens in several places. The easiest example is:

Inserting works pretty good, (but still only after I moved connection into separate method and used this method in the class: kot-begemot/rails@ea515fe, I tested this solution by executing all 4 test sets for ActiveRecord and they went well.) but selecting is not.

So for inserting the connection is following(examples with fixed code, assuming active_record 3.2):

module ActiveRecord
  class Relation
    ...
    def insert(values)
      ...
      conn = connection
      ...
      conn.insert(
        im,
        'SQL',
        primary_key,
        primary_key_value,
        nil,
        binds)
    end
  end
end

While selecting happens:

module ActiveRecord
  class Relation
    ...
    def exec_queries
      ...
      @records = if @readonly_value.nil? && !@klass.locking_enabled?
        eager_loading? ? find_with_associations : @klass.find_by_sql(arel, @bind_values)
      else
      ...
    end
  end
end

Which literally means No more overwritten connection. Well at least unless there no eager loading involved.
Internally, @klass.find_by_sql(arel, @bind_values) looks like:

module ActiveRecord
  module Querying
    ...
    def find_by_sql(sql, binds = [])
      logging_query_plan do
        connection.select_all(sanitize_sql(sql), "#{name} Load", binds).collect! { |record| instantiate(record) }
      end
    end
  end
end

So the connection appears here, but now this is a class method. Opposite situation if eager loading is enabled:

module ActiveRecord
  module FinderMethods
    ...
    def find_with_associations
      ...
      rows = connection.select_all(relation, 'SQL', relation.bind_values.dup)
      ...
    end
  end
end

In that case it is overridden connection, which is fine.

Well, potentially, I can skip the part with selection, although it would be nice to have it.
So can you advise me any solution for this problem, cos I thought it would be nice to have a selection within same class, and not distributed across several. I can try to implement my, but I want to hear an expert's advise first.

I will explain second problem in a separate issue

Member

steveklabnik commented Dec 18, 2012

Hey @kot-begemot ! Since this isn't really a bug report, and there isn't really any discussion here, I'm closing this. If you'd like to get some feedback about implementing a way to replace a connection, please post to rails-core, or if you want to find a work around, discuss it on rubyonrails-talk. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment