Where to put additional code for model


#1

Hi,
I have written a method to map three ‘virtual’ fields in my form to one
‘proper’ field in my model.
It looks like this:

class Class
def map_three_fields(var1, var2, var3)
string_val = “…do stuff…”
self.class_eval string_val
end
end

At the moment it is sitting at the top of my model, but the method is
quite long and this looks a bit ugly / cluttered.

Is there anywhere else I can put this code?
And if so, will it work out of the box or do I need to add a “require”
somewhere or alter any configuration files.

Thanks for your help


#2

Jim B. wrote:

Hi,
I have written a method to map three ‘virtual’ fields in my form to one
‘proper’ field in my model.
It looks like this:

class Class
def map_three_fields(var1, var2, var3)
string_val = “…do stuff…”
self.class_eval string_val
end
end

At the moment it is sitting at the top of my model, but the method is
quite long and this looks a bit ugly / cluttered.

Is there anywhere else I can put this code?

In my opinion (backed by zero experience), models are serfs, and
controllers are the aristocrats that command the serfs to do various
chores. So if you think a controller is going to get its hands dirty
doing the work of a serf, well…you better think again.

Of course you could create another model–one not hooked up to a
database–that has a class method that you could call like this:

Utilities.map_three_fields()

And no, you wouldn’t need a require.


#3

2009/5/12 Jim B. removed_email_address@domain.invalid

end
end

At the moment it is sitting at the top of my model, but the method is
quite long and this looks a bit ugly / cluttered.

You could put it down the end of the model, it should be in the private
section anyway, presumably.
If it is that ugly/cluttered you could refactor it.
Colin


#4

Hi,

Thanks very much for the replies.
I will follow Michael’s advice and stick it in a module.

I hope you know what you’re doing.

Probably nowhere near as much as I should

What if one of the strings is
%x{echo gotcha}
or worse?

It’s a date input which is mapped.
In the model the field is :dob and is a string.
In the form this is split into :dob_day, :dob_month, :dob_year

Using the method I wrote (currently) in my model I can them write:
map_three_fields :dob_day, :dob_month, :dob_year

and they are returned as a string containing a date in the form of
“dd-mm-yyyy” (including hyphens).

In the form the maximum length of dob_day and dob_year are 2 characters.
The maximum length of dob_year is 4 characters.

Therefore (I hope) it is not possible to enter “%x{echo gotcha}”.

Now the question to make you slap your hand on your head and look at the
ceiling:
What would this do, anyway?

Do you have any comments, ideas, criticism about doing things this way?

I found relatively little on the inputing of dates in forms using Rails
online (date select is genuinely rubbish) and the form should also run
without javascript. Therefore I put this method together myself and
would be very grateful if anyone could point out if there are any
massive security exploits that I have overlooked.

If it would help I can post the full code of what I have done.

Thanks very much in advance.


#5

On Tuesday 12 May 2009, Jim B. wrote:

end
I hope you know what you’re doing. What if one of the strings is

%x{echo gotcha}

or worse?

At the moment it is sitting at the top of my model, but the method is
quite long and this looks a bit ugly / cluttered.

Then move it down to the bottom, or if you want to hide it even more,
put it in a module:

class MyModel < ActiveRecord::Base
include ComplicatedStuff

end

And if so, will it work out of the box or do I need to add a
“require” somewhere or alter any configuration files.

As long as it is in one of the “usual” directories, i.e. app/models,
lib, the module will be found automatically.

Michael


Michael S.
mailto:removed_email_address@domain.invalid
http://www.schuerig.de/michael/


#6

On Tuesday 12 May 2009, Jim B. wrote:

%x{echo gotcha}
“dd-mm-yyyy” (including hyphens).
Why? IMHO, the best you can do is have a look at how date_select works,
you’ll notice that it already does what you’re trying to do. For the
long story see the code in date_helper.rb and date_helper_test.rb
somewhere in ActionView and
Activerecord::Base#assign_multiparameter_attributes. For the short
story, name your fields

dob(1i), dob(2i), and dob(3i) and have ActiveRecord put together these
parts.

In the form the maximum length of dob_day and dob_year are 2
characters. The maximum length of dob_year is 4 characters.

Therefore (I hope) it is not possible to enter “%x{echo gotcha}”.

Careful! It may not be possible to enter anything exceeding the max
length in the average browser, but that doesn’t stop anyone to submit
requests to your app with other tools.

Now the question to make you slap your hand on your head and look at
the ceiling:
What would this do, anyway?

%x{echo gotcha} is another way of writing echo gotcha. Each of these
executes the given command(s) with the right of the current user. It’s
like that you wouldn’t enter cd $HOME; rm -rf by yourself, so you’d
better not give someone else an opportunity to enter %x{cd $HOME, rm -
rf} for you.

Do you have any comments, ideas, criticism about doing things this
way?

I found relatively little on the inputing of dates in forms using
Rails online (date select is genuinely rubbish) and the form should
also run without javascript. Therefore I put this method together
myself and would be very grateful if anyone could point out if there
are any massive security exploits that I have overlooked.

Passing arbitrary, user-provided strings to eval or class_eval is a
huge security hole.

Michael


Michael S.
mailto:removed_email_address@domain.invalid
http://www.schuerig.de/michael/


#7

On Tuesday 12 May 2009, Jim B. wrote:

giving date_select false input (eg. enetering 31st February with no
year. http://www.ruby-forum.com/topic/183310)

The app does not crash, it just reacts with an exception to malformed
input data. I think Fred Cheung’s suggestion in that thread is
completely right: Catch that exception and handle it. From the
ActiveRecord::MultiparameterAssignmentErrors exception you can even find
out which attributes were involved an generate a nice error message.

that make no difference?
You can, of course, do your own sanitizing of input data. But in this
particular case I don’t see the point. You still need to avoid anomalies
like February, 31st. I don’t see any advantage in doing this stuff
yourself instead of giving ActiveRecord a chance and mop up in case it
indicates a problem. Don’t get to enamored with your current approach.

Michael


Michael S.
mailto:removed_email_address@domain.invalid
http://www.schuerig.de/michael/


#8

Hi Michael,
Thanks for the reply.

“dd-mm-yyyy” (including hyphens).
Why? IMHO, the best you can do is have a look at how date_select works,
you’ll notice that it already does what you’re trying to do.

But isn’t date_select really feeble?
For example it is very easy to make the whole application crash by
giving date_select false input (eg. enetering 31st February with no
year. http://www.ruby-forum.com/topic/183310)

Careful! It may not be possible to enter anything exceeding the max
length in the average browser, but that doesn’t stop anyone to submit
requests to your app with other tools.

Good point.

%x{echo gotcha} is another way of writing echo gotcha. Each of these
executes the given command(s) with the right of the current user. It’s
like that you wouldn’t enter cd $HOME; rm -rf by yourself, so you’d
better not give someone else an opportunity to enter %x{cd $HOME, rm -
rf} for you.

Even better point.

Passing arbitrary, user-provided strings to eval or class_eval is a
huge security hole.

You’re right.
I did have everything working without using eval.
The method with eval was just intended to make everything that bit
neater.
Would it then be sufficient to check the user generated input for
numericality (ie. enduse that the user has only entered numbers as they
are supposed to) and only carry out eval in this case, or would that
make no difference?


#9

Jim B. wrote:

At the moment it is sitting at the top of my model, but the method is
quite long and this looks a bit ugly / cluttered.

Sometimes code is ugly no matter what… :wink:

I remember having to account for the difference between little-endian
veruss big-endian architectures on a project, and writing a whole
comment paragraph about just why I was twiddling two bytes of data in
the buffer stream before extracting it into the long int I wanted…

Is there anywhere else I can put this code?

If it belongs to the model, it should be in the model, unless it really
is a larger ‘sub-system’ that merits its own module.

Of course, it could always be just the first entry into your
‘application_extensions’ module as well, but when I find modules with
just one or two methods that are only used by one class, there’s a ‘Why
oh why?’ moment.

Just my $0.02.


#10

Ok, cheers for that.
I guess I will have to rethink my approach.
In defense of my current method, to make sure the date field doesn’t
accept incorrect input I use ruby’s ‘Date.strptime’ to parse the string
as a date. If it works then everything is ok, if it throws an error then
I catch this and output the error message that the date is invalid.

that make no difference?
You can, of course, do your own sanitizing of input data. But in this
particular case I don’t see the point. You still need to avoid anomalies
like February, 31st. I don’t see any advantage in doing this stuff
yourself instead of giving ActiveRecord a chance and mop up in case it
indicates a problem. Don’t get to enamored with your current approach.


#11

So this won’t fix the problem of user input outside the browser, but
what about implementing the date fields as 's instead of text
fields? You will still have to sanitize the data but at least you
have defined the format in which the user inputs it through the
browser.

On May 12, 10:09 am, Ar Chron removed_email_address@domain.invalid


#12

p_W wrote:

So this won’t fix the problem of user input outside the browser, but
what about implementing the date fields as 's instead of text
fields? You will still have to sanitize the data but at least you
have defined the format in which the user inputs it through the
browser.

I recommend this setup for date entry since it does help a little with
the input sanitizing: When you use a Select tag, the user input options
are known values and it allows you to be much more aggressive and
unforgiving with your input validation. Text box input requires some
fuzzy acceptance of values, but a Select/Options list does not - you can
validate against a fixed set of values and anything else must have come
from a Bad Guy.

  • Aaron

#13

I recommend this setup for date entry since it does help a little with
the input sanitizing: When you use a Select tag, the user input options
are known values and it allows you to be much more aggressive and
unforgiving with your input validation. Text box input requires some
fuzzy acceptance of values, but a Select/Options list does not - you can
validate against a fixed set of values and anything else must have come
from a Bad Guy.

Hi,
Thanksfor the replies.
I’ve just been chatting with my brother-in-law who is a ruby programmer
(considerably better than am I) and he pointed out that as I am calling
the method which uses “eval” thus:
map_three_fields :dob_day, :dob_month, :dob_year, “make_date”, “dob”
the method doesn’t accept any user input as arguments (only three
symbols and two strings) and is therefore harmless.

So I guess I can stick with my original method after all.

Cheers
Jim