Skip to content
New issue

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

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't chain other operators or #as, etc from addition or subtraction #89

Closed
stevecj opened this issue Oct 21, 2011 · 9 comments
Closed

Comments

@stevecj
Copy link

stevecj commented Oct 21, 2011

An addition or subtraction results in a Nodes::Grouping instance, and that class does not have the mixins to support chaining additional methods. I can't even specify a column name using #as (e.g. (foo_table[:value] + 1).as(foo_plus_one). Attempting to do so results in...

NoMethodError: undefined method `as' for #Arel::Nodes::Grouping:0x00000102e9b968

Likewise, I can't chain an addition to an addition, etc. The same problem does not exist for multiplication and division, because those return instances of Nodes::Binary subclasses rather than Nodes::Grouping.

It seems to me that the addition and subtraction operators should return instances of something like a MathGrouping class that includes the same mixins that Nodes::Binary and Attributes::Attribute do (and maybe there should be another module that encapsulates that combination of inclusions).

@ngokli
Copy link

ngokli commented Sep 17, 2012

This seems... important? But there are no responses to this issue, so maybe I'm just missing something (I'm fairly new to ARel).

Given:

    t = Users.arel_table
    Users.select(t[:name]).select(t[:post_count] + t[:comment_count])

... can I access the (post_count + comment_count) here without an alias?

Am I just using this "wrong"?

@ngokli
Copy link

ngokli commented Sep 17, 2012

Ah, it seems I can do this:

    t = Users.arel_table
    Arel::Nodes::InfixOperation.new(:+, t[:post_count], t[:comment_count]).as('post_plus_comment_count')

@parndt
Copy link

parndt commented Jun 29, 2013

This may have been fixed by c78227d though I am unsure.

@ur5us
Copy link

ur5us commented Jan 6, 2015

@parndt Nope, it doesn't work, not even in arel -v "6.0.0".

@drakmail
Copy link

Same problem 😞

I'm need to get subtraction of 3 columns as quantity:

 (items[:quantity] - items[:available_quantity] - items[:to_back_order]).as("quantity")

and I'm get this error:

NoMethodError: undefined method `-' for #<Arel::Nodes::Grouping:0x007fb9332a3ed0>

because first substraction operation returns Arel::Nodes::Grouping

@drakmail
Copy link

Workaround for my case:

Arel::Nodes::TableAlias.new(Arel::Nodes::Grouping.new(
  Arel::Nodes::Subtraction.new(
    Arel::Nodes::Subtraction.new(
      items[:quantity],
      items[:available_quantity]
    ),
    items[:to_back_order]
  )
), Arel::Nodes::SqlLiteral.new("AS quantity"))

@ansonhoyt
Copy link

My case is similiar to @drakmail. I wanted to get:

(activities.logged_at - root_ancestor.logged_at) AS duration

I worked around by converting the calculation to SQL and wrapping in Arel.sql:

# activities = Activity.arel_table
# root_ancestor is an Arel::Table object
...
duration_term = (root_ancestor[:logged_at] - activities[:logged_at]).to_sql
...
@activities.arel
.project(Arel.sql(duration_term).as('duration'))
...

@spiralnegative
Copy link

spiralnegative commented Jun 16, 2016

Thanks, @drakmail! I extended your solution to match my case in which I have to prioritize operators:

# (current_revenue - last_month_revenue) / last_month_revenue * 100

revenue_change = Arel::Nodes::Grouping.new(
  Arel::Nodes::Subtraction.new(
    arel_table[:current_revenue],
    arel_table[:last_month_revenue]
  )
)

Arel::Nodes::TableAlias.new(Arel::Nodes::Grouping.new(
  Arel::Nodes::Multiplication.new(
    Arel::Nodes::Division.new(
      revenue_change,
      arel_table[:last_month_revenue]
    ),
    100
  )
), Arel::Nodes::SqlLiteral.new('AS monthly_revenue_change'))

@matthewd
Copy link
Member

Per #523, Arel development is moving to rails/rails.

If this issue is still relevant, please consider reopening it over there. (Note that the Rails repository does not accept feature request issues, and requires reproduction steps that rely on Active Record's documented API.)

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

No branches or pull requests

8 participants