Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of ActiveRecord::Relation#bind?

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?

like image 690
m_x Avatar asked Feb 19 '13 14:02

m_x


1 Answers

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.

like image 91
David Grayson Avatar answered Sep 18 '22 01:09

David Grayson