I have a Person ActiveRecord model that has_many Orders.
class Person < ActiveRecord::Base
has_many :orders
end
I am building out a simple reporting tool. The tool allows the user
to set criteria for which People they want to see. For example, "show
only the People/Orders where the Order's value is greater than $100"
When the user sets this criteria on a web form, I now need to modify
my has_many association. I now need the association to be:
class Person < ActiveRecord::Base
has_many :orders, :conditions => "ORDER_VALUE > 100"
end
This way, when I do a person.orders.count, I should only get the count
of orders where the Order Value is greater than $100.
Is there any way I can do what I'm describing here? I'm open to any/
all possibilities here.
Thanks for your help! I'm very close to selling my company on using
Rails for some bigger projects!
Robert H. Goretsky
Hoboken, NJ
-Michael
http://javathehutt.blogspot.com
person.orders.find(:all, :conditions => ['order_value > ?', 100])
is:
a) It does not remove all of the Person records that do not have an
order_value > 100 from the collection of People. So, my report would
end up showing a lot of parent Person records that have no children.
b) It does not update the person.orders count correctly to only count
the children with order_value > 100.
c) (I know this is somewhat outside the scope of this discussion, but
figure I list it to be fair) -- I'm using ActiveScaffold, which just
wraps associated parent/children models into beautiful nested view
code. I'd rather not put tons of ugly customizations in if all I
really need is this one silly condition added to the has_many
association.
Any ideas on how to accomplish what I'm going after here?
Thanks again,
Rob
http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/5199cea1d6267c5c/06a1f5da4203a11d
http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/7f7f715d917b9faa/426c768dd282929f
--
We develop, watch us RoR, in numbers too big to ignore.
Your not finding orders then, your finding people. So you don't want to
directly mess with the association like that. Try this:
Person.find(:all,
:include => :orders,
:conditions => ['order.value >= ?', 100])
You can include the association in the SQL query and reference it in the
conditions. But since your calling find on Person, it will return
people, not orders.
--
Posted via http://www.ruby-forum.com/.
I was looking for a way to dynamically modify has_many conditions, and
the answer you linked to, using the reflect_on_association class
method of ActiveRecord, was the way to go.
Person.reflect_on_association(:conditional_orders).options[:conditions]
= ....(new dynamic conditions)...
Thanks again for your help!
-Rob
I'm assuming that using the reflect_on_association method is giving me
access to a class variable of the Person class that holds the
conditions.
I have read that class variables are SHARED across user instances in a
production Mongrel/Webrick environment. So, if I have > 1 concurrent
web users, when one web user sets a condition, now all web users will
have this condition set!
Am I misunderstanding ActiveRecord's implementation of associations as
class varibles here, or am I correct?
Thanks again..
-Rob
I would very much recommend you look into an alternative implementation
of what you are trying to do, associations are not meant to be used in
this way. You should either implement a new method on the Person class,
for example:
class Person < ActiveRecord::Base
has_many :orders
def orders_greater_than(value)
orders.find(:all, :conditions => ['ORDER_VALUE > ?', value])
end
end
or, something using an association proxy extension, which is documented
here:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html.
You could potentially then do something like:
person.orders.with_value_higher_than(params[:value])
There are also other ways to implement what you seek, but I think the
current path you're going down is a problematic one.
- Gabriel
--
Posted via http://www.ruby-forum.com/.
Rob, yes, the condition will change for all requests on that Rails
process, but requests are currently handled serially on each of these
processes, so you can set the condition, do the find, then set it back,
perhaps using an automatic wrapper around the finds through a custom
find method, or by putting finds in a block that is yielded-to by a
condition-setting method. If and when Rails becomes multi-threaded,
some locks can be added to the condition-setting method.
And you only need to reset the condition if the find sometimes needs
to be done without condition. If that's the case, an alternative to
condition reset would be to define the association twice, one fixed
and condition-less, and one with a name suffix that indicates use of
a dynamic condition.