7

Just out of curiosity - I was reading the docs of the Relation::QueryMethods module and found that method:

def bind(value)
  relation = clone
  relation.bind_values += [value]
  relation
end

Does anyone know what is this? I tried to find by myself, but failed.

UPDATE

I tracked down usage of @bind_values to the bottomless depth of ActiveRecord::ConnectionAdapters - the values get passed on and on till low-level SQL statement executions. Seems that the individual adapters may use these. My guess is that it has to do with prepared statements like SELECT * FROM 'table' WHERE 'field' = ?, but I'm stuck here. Anyone?

Dmitry
  • 279
  • 2
  • 10
m_x
  • 12,357
  • 7
  • 46
  • 60

1 Answers1

9

First, I would like to explain the find_by_sql method provided by ActiveRecord. It looks like this method can used like this:

Post.find_by_sql("SELECT title FROM posts WHERE author_id = ?", [author_id])

The second parameter is called "binds" and it is an array of variables that correspond to the question marks in the query. You really want to use the binds array to insert parameters into your query, because it avoids a lot of SQL injection dangers that happen if you did the binding yourself:

Post.find_by_sql("SELECT title FROM posts WHERE author_id = #{author_id}")

So, how does this relate to an ActiveRecord::Relation? The point of AREL is that you can build up a query a little bit at a time by calling methods on an ActiveRecord::Relation object. There are a bunch of these methods, and here are some lists of them:

http://apidock.com/rails/v3.2.8/ActiveRecord/QueryMethods

So the bind method makes a new object by cloning the current one, adds the specified value to the list of bind_values, and then returns the new object. Eventually, when the relation is used to generate a query, that value will find itself being used to make a query. One example where bind_values get passed to find_by_sql is in the exec_queries method:

@records = eager_loading? ? find_with_associations : @klass.find_by_sql(arel, bind_values)

You can search for "bind_values" in the activerecord gem and you will find several similar places where it is being used.

I would have thought that the bind method would be called by where, but it doesn't seem to be called anywhere in activerecord. Maybe it is a left-over from an older design. I don't think you should call bind in your app.

David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • thanks, but i already figured that out (see the 'update' part of my question) - +1 for the effort though. I agree with you that it may be a left-over; one other hypothesis is that this facility is there for specific adapters that would need it. As far as wandered in the source of postgres adapter, i've not seen it actually use the values. I tried some things like `Model.where( "field = ?" ).bind( value ).to_sql` but the bind values do not appear in the query. So i guess it may be used by some adapters that would build prepared (precompiled) statements ? – m_x Feb 21 '13 at 19:54
  • i would not say that this is a complete answer, but you are the only one that tried, so the bounty is for you. thanks anyway – m_x Feb 28 '13 at 11:28
  • Thanks! Sorry I couldn't figure out anything more. You could ask the maintainers of Rails I suppose. – David Grayson Feb 28 '13 at 23:38