Arel for any AR action?

There are times when it would be very useful to be able to get the Arel for any given ActiveRecord action such as a creation or update without actually carrying out the action.

I’m imagine something like…

the_arel = Fruit.arel{|f| f.create :name => ‘Banana’, :color => ‘Yellow’ }

Does anyone else think this would be nice to have (or know of a way to do it already)?

What would the usecase for this be?

The use case would be using AR semantics to define an action, but then using that in a larger context, such as concatenating the SQL for several updates together using “;” and executing them in a single round-trip to the server. Technically, this just means just needing the SQL, but it seems silly to provide the SQL rather than the Arel from which the SQL can be trivially retrieved.

I think this is way too specific for core. Looks like a great idea for a plugin, though :slight_smile:

Cheers,

-foca

Could that be done as a plugin and not rely on undocumented internal APIs that are likely to change without warning?

What would the usecase for this be?

I just had a similar need the other day, where I needed to build a separate query based on the current scope (not clone the current scope, but take the specific parameters of the scope to apply to another query which wasn’t a scope at all). The way I had to do what I needed was to grab the current scope and manually inspect the where_values, joins_values, etc.

I think this is way too specific for core. Looks like a great idea for a plugin, though :slight_smile:

I don’t disagree that this may be too specific for core. Just demonstrating that I think there’s a need, so might make a good gem.

Could that be done as a plugin and not rely on undocumented internal APIs that are likely to change without warning?

I would think so. Looking at the AR code for creating a record,

https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb#L32

you can trace the actual save down to this line:

https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb#L436

and if you look at the line above it, you get an array of Arel::Attributes values from this method:

https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods.rb#L323

which is just doing this (and note this method is protected, not private):

attrs = {}

arel_table = self.class.arel_table

attribute_names.each do |name|

attrs[arel_table[name]] = typecasted_attribute_value(name)

end

attrs

If you just want the array of attributes, then you could do the above and combine it with Fruit.unscoped to get a new Arel instance. There'd be nothing specific in this Arel instance about it being for `create`, i.e. `insert` in SQL. At this point you could jump over to Arel and build a new InsertManager instance I suppose:

[https://github.com/rails/arel/blob/master/lib/arel/crud.rb#L41](https://github.com/rails/arel/blob/master/lib/arel/crud.rb#L41) => [https://github.com/rails/arel/blob/master/lib/arel/insert_manager.rb](https://github.com/rails/arel/blob/master/lib/arel/insert_manager.rb)

Of course, at this point, the discussion would no longer be within the scope of rails-core, assuming no one has interest in putting this into Rails core.

-- Steve Schwartz

OK – that’s an avenue for further research. My suggestion is starting to seem like less of a good idea the more I think about it, however.

Perhaps, what’s really needed is simply more & better Arel documentation and usage examples (without sticking in lots of literal SQL bits that’ll break when table aliasing occurs). If it were easier to figure out how to do things directly in Arel, there would be little reason to use AR semantics to build Arel. I’m sure I don’t need any Rails Core group consensus to start working on more useful Arel docs.