Need help with model logic

Hi all -

Ruby 1.8.7 / Rails 2.3.5

Schedule model: course_id, starts_at, ends_at, capacity
has_many :requests

Request model: user_id, schedule_id, state_id
belongs_to :schedule

request.state_id indicates whether the request has been approved.
(state_id = 2 = pending my approval, state_id = 3 = approved)

I want to list all requests pending my approval, along with the
remaining seats available.

def listPendingRequest
@allRequests = Request.find(:all, :conditions => [“state_id = ?”,
2]).each{
|request|
@schedule = Schedule.find(:first, :conditions => [“id =
?”,request.schedule_id])
@num = Request.find(:all, :conditions => [“state_id = ? AND schedule_id
= ?”, ‘3’, @schedule.id]).nitems
@remaining = @schedule.capacity - @num
}
@request = Array.new
@allRequests.each do |r|
if (r.state_id == 2 and r.approver_id == current_user.id)
@request << r
end
end
if @request.empty?
flash.now[:alert] = “You have no pending requests to approve.”
end
end

I currently have this method in my request controller, but I think it
belongs in a model. I don’t know which model, though.

Also, this method shows the remaining seats for the first schedule on
all of the requests, regardless of which schedule is being requested.
When I do a @schedule = Schedule.find(:all…), I get an error:
“undefined method ‘capacity’ for Array”.

What am I doing wrong? And where should I put the method?

Thanks in advance for your help!!

On 1 September 2010 17:59, Charlie B99 [email protected] wrote:

Hi all -

Ruby 1.8.7 / Rails 2.3.5

I have not worked right through your code but have got some comments
that may help (or not).

I want to list all requests pending my approval, along with the
remaining seats available.

What is a seat? This is the first time you have mentioned it.

def listPendingRequest

I would advise using the rails convention for naming things, so this
would be list_pending_requests

@allRequests = Request.find(:all, :conditions => [“state_id = ?”,
2]).each{
|request|
@schedule = Schedule.find(:first, :conditions => [“id =
?”,request.schedule_id])

If the above is finding the schedule for request you don’t need to do
a find, just use
@schedule = request.schedule.

@num = Request.find(:all, :conditions => [“state_id = ? AND schedule_id
= ?”, ‘3’, @schedule.id]).nitems

Now that you have a schedule, the requests for that schedule are
@schedule.requests, so you can do something like
@num = @schedule.requests.find(:all, “state_id = ?”, 3).count

Unless you need @num to be an instance variable of whatever class this
ends up in then just make it a simple variable - num

Is there a reason why you are using nitems rather than count?

@remaining = @schedule.capacity - @num
}

You have now dropped out of the block. Note that you overwrote
@remaining each time round. so it will now have the value of the last
time round. I am not sure that the block contents have achieved
anything at all.

@request = Array.new

If @request is going to contain a number of items call it @requests.

@allRequests.each do |r|
if (r.state_id == 2 and r.approver_id == current_user.id)

I am not sure what is going on here as I am running out of time. You
have not told us the relationships between Request and User. If you
find yourself using something.id then very often you just need to
setup the relationships in the right way and you can do the same sort
of thing as with schedules and requests above. So you may need
something like User has_many approved_requests with approver_id as the
foreign key, then User.approved_requests will give you the requests
that user has approved.

belongs in a model. I don’t know which model, though.
I suspect that it may be User method as it returns his pending
requests, but maybe not. Also consider whether this is really the
functionality you want. Often when the return from a method is
defined as returns something along with something else (as you have
done here) you actually want two separate methods. So maybe one that
gives the users unnaproved requests (which would be a User method
probably, and may have involve no code if you get the relationships
right) and a separate one to return remaining seats available
(whatever that means).

Also, this method shows the remaining seats for the first schedule on
all of the requests, regardless of which schedule is being requested.
When I do a @schedule = Schedule.find(:all…), I get an error:
“undefined method ‘capacity’ for Array”.

Does that only happen in the above code or do you mean that you just
cannot do Schedule.find(:all)? If you can do a simple find all then
gradually add bits to the working one till you get the problem. How
can the method be showing anything if you get that error?

Sorry I have probably not been able to give this the thought it
deserves but maybe this will at least be of some help.

Colin

On 2 September 2010 16:37, Charlie B99 [email protected] wrote:

Could you not top post please - insert your comments at the
appropriate place in previous mail, it makes it easier to follow the
thread, particularly for those that find this thread in the future.
Thanks

Colin, thanks so much for all your input. As you can see, I’m just
muddling my way through all this, and all of your comments are very
helpful. I will go through them more when I get to the office…

“remaining seats” = schedule.capacity - number of approved requests.
So, if a schedule has a capacity of 10, and 8 requests with state_id = 3
(approved), then there are 2 available slots before the capacity reaches
0 and no more requests can be accepted.

Can I do request.schedule as a find in 2.3.5 or is that a 3.0 feature?

Most certainly you can. I think maybe you would benefit from reading
the rails guides at Ruby on Rails guides Those will
be ok for 2.3.5 (why are you not using the latest 2.3 I wonder?).
Particularly Getting Started, ActiveRecord Associations, Routing, and
Debugging.

Colin

Colin, thanks so much for all your input. As you can see, I’m just
muddling my way through all this, and all of your comments are very
helpful. I will go through them more when I get to the office…

“remaining seats” = schedule.capacity - number of approved requests.
So, if a schedule has a capacity of 10, and 8 requests with state_id = 3
(approved), then there are 2 available slots before the capacity reaches
0 and no more requests can be accepted.

Can I do request.schedule as a find in 2.3.5 or is that a 3.0 feature?

I used nitems because I didn’t know any better. :slight_smile:

You’ve got me pointed in the right direction now - I’m new and messy,
but I’m diggin it, so will keep pluggin away.

Thanks again!

Colin L. wrote:

On 1 September 2010 17:59, Charlie B99 [email protected] wrote:

Hi all -

Ruby 1.8.7 / Rails 2.3.5

I have not worked right through your code but have got some comments
that may help (or not).

I want to list all requests pending my approval, along with the
remaining seats available.

What is a seat? This is the first time you have mentioned it.

def listPendingRequest

I would advise using the rails convention for naming things, so this
would be list_pending_requests

@allRequests = Request.find(:all, :conditions => [“state_id = ?”,
2]).each{
|request|
@schedule = Schedule.find(:first, :conditions => [“id =
?”,request.schedule_id])

If the above is finding the schedule for request you don’t need to do
a find, just use
@schedule = request.schedule.

@num = Request.find(:all, :conditions => [“state_id = ? AND schedule_id
= ?”, ‘3’, @schedule.id]).nitems

Now that you have a schedule, the requests for that schedule are
@schedule.requests, so you can do something like
@num = @schedule.requests.find(:all, “state_id = ?”, 3).count

Unless you need @num to be an instance variable of whatever class this
ends up in then just make it a simple variable - num

Is there a reason why you are using nitems rather than count?

@remaining = @schedule.capacity - @num
}

You have now dropped out of the block. Note that you overwrote
@remaining each time round. so it will now have the value of the last
time round. I am not sure that the block contents have achieved
anything at all.

@request = Array.new

If @request is going to contain a number of items call it @requests.

@allRequests.each do |r|
if (r.state_id == 2 and r.approver_id == current_user.id)

I am not sure what is going on here as I am running out of time. You
have not told us the relationships between Request and User. If you
find yourself using something.id then very often you just need to
setup the relationships in the right way and you can do the same sort
of thing as with schedules and requests above. So you may need
something like User has_many approved_requests with approver_id as the
foreign key, then User.approved_requests will give you the requests
that user has approved.

belongs in a model. �I don’t know which model, though.
I suspect that it may be User method as it returns his pending
requests, but maybe not. Also consider whether this is really the
functionality you want. Often when the return from a method is
defined as returns something along with something else (as you have
done here) you actually want two separate methods. So maybe one that
gives the users unnaproved requests (which would be a User method
probably, and may have involve no code if you get the relationships
right) and a separate one to return remaining seats available
(whatever that means).

Also, this method shows the remaining seats for the first schedule on
all of the requests, regardless of which schedule is being requested.
When I do a @schedule = Schedule.find(:all…), I get an error:
“undefined method ‘capacity’ for Array”.

Does that only happen in the above code or do you mean that you just
cannot do Schedule.find(:all)? If you can do a simple find all then
gradually add bits to the working one till you get the problem. How
can the method be showing anything if you get that error?

Sorry I have probably not been able to give this the thought it
deserves but maybe this will at least be of some help.

Colin