I started with Ruby on Rails a few weeks ago and am looking for a
'best practice' to handle the creation of objects that relate to
eachother. I will illustrate it with an example:
My model consists of 2 classes that are related, a model
Businesspartner and a model Ticket. Every ticket belongs_to one
Businesspartner, a businesspartner has_many tickets. The form to
create a new Ticket is different for different kind of users. Users
that have a role "customer" don't see anything for this relation (it
is assigned when creating the ticket), users with the role "employee"
get a select list of all businesspartners. There are a few things I
want to check on creating a new ticket:
*Check excistence of the supplied businesspartner by the form:
preventing illegal input
*Check if the user is a customer if this is true set the
businesspartner to the default for this user: ignore the fields in the
param hash
Is there a best practice how to implement a thing like this? Should it
be implemented in the controller or model? And are validation's
usefull for this or should I handle it in the constructor or use a
separate method?
Currently I created a method in the model that processes the logic and
returns a check instance of the Ticket , this works fine but I don't
see a nice way to notify the user that one of the related fields isn't
correct (I can't access the errors variable the way that validations
can). I guessed this is a common challenge but haven't find any best
practice on it yet.
My model consists of 2 classes that are related, a model
Businesspartner and a model Ticket.
Assuming you have your models:
class Businesspartner < ActiveRecord::Base
has_many :tickets
end
class Ticket < ActiveRecord::Base
belongs_to :businesspartner
end
There are a few things I
want to check on creating a new ticket:
*Check excistence of the supplied businesspartner by the form:
preventing illegal input
*Check if the user is a customer if this is true set the
businesspartner to the default for this user: ignore the fields in the
param hash
Is there a best practice how to implement a thing like this? Should it
be implemented in the controller or model? And are validation's
usefull for this or should I handle it in the constructor or use a
separate method?
First of all, the logic 'user is a customer' should be in your model.
I would create a method is_a_customer in the User model so whenever I
want to change conditions for a user to be a customer, I have to change
it in a single place:
def is_a_customer?
#Your conditions, like (assuming users.customer is a boolean row):
self.customer
end
So, you could write in your controller:
def create
@user = User.find(session[id])
@businesspartner = Businesspartner.find_by_name(params[:businesspartner])
unless @businesspartner
if @user.is_a_customer?
@user.businesspartner = @businesspartner
else
# I don't know, may be
params.delete(:businesspartner)
#blablabla
end
else
flash[:error] = 'Illegal input!'
redirect_to :action => :index
end
end
Thanks for your input! I have many different roles users can have, so
this can
become quite long. Suppose I create a Ticket object from something
other than
this controller (or method) then I would have to repeat the same
checking. That's
why I thought it would be better to implement this in the model, do
you see any drawbacks
on this aproach?
I have also thought of implementing this as a validator; invalid
objects can be created but
never saved and I thought displaying the error messages could be done
in the same
way other validators do this, which seems logical and consistent to
me. Or am I missing
some drawbacks on this aproach?