As a couple of people have said, looking at this in isolation won't
allow us to easily give suggestions of better solutions, but you could
certainly tidy that method a little.
Firstly, (personal preference time!) your variable names aren't
helping your code be "self documenting". Even in such a small method,
it's frustrating to try to remember what all those single-character
variables are supposed to be doing. If they're named to refer to what
they do, they will help other people (or you when you come back to it
in a couple of months!) understand what the intention behind their
existence is.
Every time you loop round, you calculate "st.beginning_of_month" - it
would be a bit more efficient to store the value for use in the
comparison each time. You never use "st" again, so I'd just overwrite
it.
The first element you populate the array with only has "st.month", all
the others have the year too - not sure if this is a typo or intended?
Another potential typo is in the array push; you refer to a "date"
variable which I can't see set anywhere. I assume this is actually
your "d" variable?
So, if I were writing your method to be clearer, it might look like this:
def get_months_and_years(start_date, end_date)
end_date = end_date.beginning_of_month
return_value = [start_date.month]
working_date = start_date.beginning_of_month
while working_date <= end_date
return_value << [working_date.month, working_date.year]
working_date = working_date.next_month
end
return return_value
end
But....
My inclination would be to be a bit more "Ruby"... assuming you want
an array of arrays of month and year for every month between two
dates:
def get_months_and_years(start_date, end_date)
# it would be worth checking that the parameters are both valid dates/times
(start_date..end_date).collect { date| [date.month, date.year] }.uniq
end
In that method I'm just taking the month and year for every date in
the range, and then returning unique values from the collection (so
one for each month/year combination. I've not got any time to look
into it, but I wonder if the Range.collect can step through
month-at-a-time rather than day-at-a-time...
I don't know if it's any quicker or much slower, but it's certainly
more concise, and (to my eye) a bit clearer in its intention, and
looks a lot less like PHP 
HTH
Michael