How to create "custom" fields in Model?

How to create “custom” fields in Model? like sum, based on quantity
and price.
I guess it should be something like:

    def summ
            price * quantity
    end

Am I right?

If so, How to use them in :conditions parameter of the
ActiveRecord::Base::find method? Is it possible it all?

if you want to do that, you’re gonna have to learn some SQL.

open up your SQL browser/command line and try

SELECT (price * quantity) FROM table_name;

SELECT table_name.*, (price * quantity) FROM table_name;

SELECT table_name.*, (price * quantity) AS total_price FROM table_name;

SELECT * FROM table_name WHERE (price * quantity) > 30.00;

now go into ruby script/console

===========================
object = Model.find(:first, :select => "(price * quantity) AS
total_price)
object.total_price

object = Model.find(:all, :conditions => “(price * quantity) > 30”)

hopefully that’ll give you a good start

:slight_smile:

gneeot wrote:

How to create “custom” fields in Model? like sum, based on quantity
and price.
I guess it should be something like:

    def summ
            price * quantity
    end

Am I right?

If so, How to use them in :conditions parameter of the
ActiveRecord::Base::find method? Is it possible it all?

Thnak you Matthew, I know SQL a bit :), but what to do if field is
much more complicated, for ex. I have few more complex fields in my
Order model:

def number_of_produced_items
total = 0
productions.each do |p|
total += p.quantity if p.start_time and p.finish_time
end
total
end

def number_of_dispatched_items
total = 0
dispatches.each do |p|
total += p.quantity
end
total
end

def number_of_items_in_progress
total = 0
productions.each do |p|
total += p.quantity if not p.finish_time
end
total
end

def enough_items_to_be_dispatched?
if (number_of_produced_items > 0 and number_of_dispatched_items <
number_of_produced_items) then true else false end
end

,and don’t want to redefine them in every find method, it takes a lot
of time :slight_smile:

for ex., one of these fields I redefined for one of the combo boxes as
quite long SQL:

select(“dispatch”, “order_id”,
Order.find_by_sql("SELECT * FROM orders o WHERE id in
(
SELECT p.order_id FROM productions p
WHERE p.start_time is not NULL and p.finish_time is not NULL
GROUP BY p.order_id
HAVING sum(p.quantity) > IFNULL(
(
SELECT sum(d.quantity) FROM dispatches d
WHERE d.order_id = p.order_id
GROUP BY d.order_id
) ,0)
)

Does anyone have any Idea how to simplify it all?


Yuriy

On Jul 16, 12:22 pm, Matthew R. [email protected]

Yuriy,

I think in certain cases it’s absolutely kosher to just add methods like
you
did. Just make sure it doesn’t create additional SQL select calls for
you,
for example, use :include => :productions when calling find for your
model.

Cheers,
Yuri

On 7/16/07, gneeot [email protected] wrote:

p.finish_time
end
if (number_of_produced_items > 0 and number_of_dispatched_items
select(“dispatch”, “order_id”,
) ,0)

hopefully that’ll give you a good start

    end


Best regards,
Yuri L.

Thank you. I think :include is what I’ve been missing sometimes. Will
consider rewriting some staff to SQL.

Regards,
Yuriy

Hi

It depends on the size of the related record set (productions).
Looping through a huge recordset will probably be less performant
(and more cpu and memory intensive) than using SQL to get what you
want. However, don’t look for problems and bottlenecks as long as
they’re not there. Switching these methods in your model to an SQL
query instead of what you have now should be a trivial task, so if
there’s ever a need to increase performance, it will be the time to
look at other options such as an SQL query. For now, this is probably
just fine.

On 16 Jul 2007, at 16:59, Yuri L. wrote:

Thnak you Matthew, I know SQL a bit :), but what to do if field is
end
total = 0
end
Best regards

Peter De Berdt

as I was saying before;

object = Model.find(:first, :select => "(price * quantity) AS
total_price)

you could refactor this

def self.find_with_total_price(args)
self.with_scope(:find => {
:select => "
," + total_price_select
}) do
self.find(*args)
end
end

def total_price_select
“(price * quantity) AS total_price”
end

make sure our reader method outputs an int

else it’d just return a string

def total_price
read_attribute(:total_price).to_i
end

and do something similar for the rest.

gneeot wrote:

Looks like :find only constructs SQL. I’m wondering is It possible to
rewrite some of fields in my model using SQL, e.g.
“number_of_items_in_progress” and then use them in :find?

Looks like :find only constructs SQL. I’m wondering is It possible to
rewrite some of fields in my model using SQL, e.g.
“number_of_items_in_progress” and then use them in :find?