Suggestion for Rails 4

52 views
Skip to first unread message

Abram

unread,
Nov 3, 2012, 5:43:29 PM11/3/12
to rubyonra...@googlegroups.com

When I began learning rails I found it frustrating that array and active record relation objects could not be queried in the same fashion as database tables. Before too much confusion let me explain.


When I want something from a database table I simply write something like: Product.where(:color=>'black') NOW, if I put a .to_sql after that statement I see something like "SELECT \"styles\".* FROM \"styles\" WHERE \"styles\".\"color\" = 'black'"


So clearly, rails is magically converting that friendly statement into something more meaningful to the backend. That's fantastic and makes my life wonderful.


So here's my problem.. after running the query I am returned an active record relation, which let's say is called @products. Now, let's say I want to further break that list of products into products that are big and small. This would require one of two things.. either I must hit the database twice being more selective, or I must iterate over @products using a block and such ruby magic as collect/map/select/etc...


To me neither of the above is a great option, and I must admit while learning ruby on rails this was one of the biggest stumbling blocks for me, and one that has produced a massive amount of stackoverflow headaches for many others.


My suggestion to rails developers is to make rails more accessible to beginners by allowing programmers to apply the same simplicity of writing an active record query to querying an active record relation object or array of model objects.


For example, I want to now take @products and say:


@products.where(:size=>"small") and have this converted automagically by rails to the appropriate statement @products.select{|product| product.size == 'small'}


I suppose this could work if rails were to query the object type first before performing the query. Is the object type an array or active record relation, and is it in the expected format (collection of appropriate objects)? If it is, then treat it as a virtual table and instead of performing an sql query, hit it with a select block, etc.


I know understanding the underlying ruby code is good, and at times would be preferable to using active record style commands.. but for new users getting off the ground, I think having both options would be beneficial. Also, I feel it would be more consistency to the framework generally.


I have also posted this at reddit http://www.reddit.com/r/rails/comments/12kyho/suggestion_for_rails_4_what_are_pros_and_cons/

Colin Law

unread,
Nov 3, 2012, 5:55:35 PM11/3/12
to rubyonra...@googlegroups.com
That should work, does it not for you?

Colin

and have this converted automagically by
> rails to the appropriate statement @products.select{|product| product.size
> == 'small'}
>
>
> I suppose this could work if rails were to query the object type first
> before performing the query. Is the object type an array or active record
> relation, and is it in the expected format (collection of appropriate
> objects)? If it is, then treat it as a virtual table and instead of
> performing an sql query, hit it with a select block, etc.
>
>
> I know understanding the underlying ruby code is good, and at times would be
> preferable to using active record style commands.. but for new users getting
> off the ground, I think having both options would be beneficial. Also, I
> feel it would be more consistency to the framework generally.
>
>
> I have also posted this at reddit
> http://www.reddit.com/r/rails/comments/12kyho/suggestion_for_rails_4_what_are_pros_and_cons/
>
> --
> You received this message because you are subscribed to the Google Groups
> "Ruby on Rails: Talk" group.
> To post to this group, send email to rubyonra...@googlegroups.com.
> To unsubscribe from this group, send email to
> rubyonrails-ta...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/rubyonrails-talk/-/NXanwmpoOAcJ.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Abram

unread,
Nov 3, 2012, 6:00:28 PM11/3/12
to rubyonra...@googlegroups.com
Well, it does, but it hits the DB again.

Abram

unread,
Nov 3, 2012, 6:02:45 PM11/3/12
to rubyonra...@googlegroups.com
Basically it just chains on to the previous db query, but still runs a new one.. it doesn't query the active record relation object. Also, you cannot query an array of objects.. say @products = Product.all ... then say @products.where(:color=>"black") .. You will get NoMethodError: undefined method `where' for #<Array:0x00000003918108>

Jim Ruther Nill

unread,
Nov 4, 2012, 12:13:49 AM11/4/12
to rubyonra...@googlegroups.com
On Sun, Nov 4, 2012 at 6:02 AM, Abram <funkd...@gmail.com> wrote:
Basically it just chains on to the previous db query, but still runs a new one.. it doesn't query the active record relation object. Also, you cannot query an array of objects.. say @products = Product.all ... then say @products.where(:color=>"black") .. You will get NoMethodError: undefined method `where' for #<Array:0x00000003918108>

If you're running the code in the console, it hits the db immediately.  But if it's in the actual application, it won't hit the db until you need to access the records
which usually happens when you call each or map or collect on the active relation object.  So given your code, if you want to get all black and small objects, you can

@products = Product.where(color: 'black')
@products = @products.where(size: 'small')

these two lines will not actually create the product records and will not yet hit the db until you want to iterate each of the products.

As for calling Product.all, I checked the api and it doesn't explicitly say that #all returns an array.  But if you know that beforehand, you shouldn't have any issues
with chaining methods.
 


On Sunday, November 4, 2012 11:00:29 AM UTC+13, Abram wrote:
Well, it does, but it hits the DB again.

On Sunday, November 4, 2012 10:43:29 AM UTC+13, Abram wrote:

When I began learning rails I found it frustrating that array and active record relation objects could not be queried in the same fashion as database tables. Before too much confusion let me explain.


When I want something from a database table I simply write something like: Product.where(:color=>'black') NOW, if I put a .to_sql after that statement I see something like "SELECT \"styles\".* FROM \"styles\" WHERE \"styles\".\"color\" = 'black'"


So clearly, rails is magically converting that friendly statement into something more meaningful to the backend. That's fantastic and makes my life wonderful.


So here's my problem.. after running the query I am returned an active record relation, which let's say is called @products. Now, let's say I want to further break that list of products into products that are big and small. This would require one of two things.. either I must hit the database twice being more selective, or I must iterate over @products using a block and such ruby magic as collect/map/select/etc...


To me neither of the above is a great option, and I must admit while learning ruby on rails this was one of the biggest stumbling blocks for me, and one that has produced a massive amount of stackoverflow headaches for many others.


My suggestion to rails developers is to make rails more accessible to beginners by allowing programmers to apply the same simplicity of writing an active record query to querying an active record relation object or array of model objects.


For example, I want to now take @products and say:


@products.where(:size=>"small") and have this converted automagically by rails to the appropriate statement @products.select{|product| product.size == 'small'}


I suppose this could work if rails were to query the object type first before performing the query. Is the object type an array or active record relation, and is it in the expected format (collection of appropriate objects)? If it is, then treat it as a virtual table and instead of performing an sql query, hit it with a select block, etc.


I know understanding the underlying ruby code is good, and at times would be preferable to using active record style commands.. but for new users getting off the ground, I think having both options would be beneficial. Also, I feel it would be more consistency to the framework generally.


I have also posted this at reddit http://www.reddit.com/r/rails/comments/12kyho/suggestion_for_rails_4_what_are_pros_and_cons/

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonra...@googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/qNPHumto-yYJ.

For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
-------------------------------------------------------------
visit my blog at http://jimlabs.heroku.com

Abram

unread,
Nov 4, 2012, 3:38:56 AM11/4/12
to rubyonra...@googlegroups.com
Jim, Thanks for that. 

What I mean is I want small and large black products attached to two separate variables, say @blacksmall and @blacklarge.. both separated out from @products which initially resulted from the Product.where(:color => 'black) query. I know it's a stupid example, but I'm just wanting that functionality, and think it would be an improvement in rails to enable using active record queries on objects that are arrays of objects as they are represented in the table. If rails treats table rows as model objects why not treat a collection of model objects in the same way, allowing the same dsl for access/limiting what's within the collection. 

Thanks


On Sunday, November 4, 2012 10:43:29 AM UTC+13, Abram wrote:

Tommaso Visconti

unread,
Nov 4, 2012, 5:19:57 AM11/4/12
to rubyonra...@googlegroups.com
Abram ha scritto:
> Jim, Thanks for that.
>
> What I mean is I want small and large black products attached to two
> separate variables, say @blacksmall and @blacklarge.. both separated out
> from @products which initially resulted from the Product.where(:color =>
> 'black) query. I know it's a stupid example, but I'm just wanting that
> functionality, and think it would be an improvement in rails to enable
> using active record queries on objects that are arrays of objects as
> they are represented in the table. If rails treats table rows as model
> objects why not treat a collection of model objects in the same way,
> allowing the same dsl for access/limiting what's within the collection.

I'm not an expert of performances, but maybe databases like postgres or
mysql are faster than other solutions to retrieve data from a complex
query, so the solution to run a new query is better than filtering a
ruby collection, which can be simple but can already be very very
complex (think to db like openstreetmaps and you want to calculate a
path...)

Colin Law

unread,
Nov 4, 2012, 5:31:53 AM11/4/12
to rubyonra...@googlegroups.com
On 4 November 2012 08:38, Abram <funkd...@gmail.com> wrote:
> Jim, Thanks for that.
>
> What I mean is I want small and large black products attached to two
> separate variables, say @blacksmall and @blacklarge.. both separated out
> from @products which initially resulted from the Product.where(:color =>
> 'black) query. I know it's a stupid example, but I'm just wanting that
> functionality, and think it would be an improvement in rails to enable using
> active record queries on objects that are arrays of objects as they are
> represented in the table. If rails treats table rows as model objects why
> not treat a collection of model objects in the same way, allowing the same
> dsl for access/limiting what's within the collection.

Once you convert to an array then you have lost the knowledge about
the database. Just keep everthing as activerecord collections and all
will be well. Rails will defer running queries until it has to as far
as it can in order to keep everything reasonably efficient.

So
@products = Product.where :color => 'black'
@smallproducts = @products.where :size => 'small'
@largeproducts = @products.where :size => 'large'

What is the problem?

Colin
> --
> You received this message because you are subscribed to the Google Groups
> "Ruby on Rails: Talk" group.
> To post to this group, send email to rubyonra...@googlegroups.com.
> To unsubscribe from this group, send email to
> rubyonrails-ta...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/rubyonrails-talk/-/tMSqIOhtcMYJ.

Matt Jones

unread,
Nov 4, 2012, 6:54:35 PM11/4/12
to rubyonra...@googlegroups.com


On Sunday, 4 November 2012 03:38:56 UTC-5, Abram wrote:
Jim, Thanks for that. 

What I mean is I want small and large black products attached to two separate variables, say @blacksmall and @blacklarge.. both separated out from @products which initially resulted from the Product.where(:color => 'black) query. I know it's a stupid example, but I'm just wanting that functionality, and think it would be an improvement in rails to enable using active record queries on objects that are arrays of objects as they are represented in the table. If rails treats table rows as model objects why not treat a collection of model objects in the same way, allowing the same dsl for access/limiting what's within the collection. 

An interesting idea, but by the time you've written enough code to support things like joins you've basically recreated an RDBMS inside of ActiveRecord. The alternative would be to support only a subset, but that seems *worse* than no support at all...

--Matt Jones
 

Abram

unread,
Nov 5, 2012, 3:38:09 AM11/5/12
to rubyonra...@googlegroups.com
Matt, 

I appreciate your answer... a good explanation :)

I'll drop it now

Abram
Reply all
Reply to author
Forward
0 new messages