janosrusiczki
janosrusiczki

Reputation: 1931

Rails route default weirdness

I have the following route:

get 'calendar(/:month(/:year))' => 'calendar#show', as: :calendar,
  constraints: { month: /[a-z]+/, year: /\d{4}/ },
  defaults: { month: Date::MONTHNAMES[Date.today.month].downcase, year: Date.today.year }

Using this route in the console I get:

app.calendar_path(month: 'september', year: '2017')
=> "/calendar"

Which is OK, since it realizes these parameters are the defaults when I'm writing this so it removes them from the generated path.

But I don't understand why:

app.calendar_path(month: 'september', year: '2018')
=> "/calendar"

2018 is the next year, so I would expect the path to be "/calendar/september/2018". The behaviour is the same for 2019, and for any year with the month being the current one.

Edit: Only reproduces in Rails 4.2.6, Rails 4.2.8 - Seems to be fixed in Rails 5+

Upvotes: 2

Views: 49

Answers (1)

ulferts
ulferts

Reputation: 2242

It looks like it is the combination of having optional parts in the path and having defaults. At least from a rendering perspective, that combination does make no sense wenn you think about it. I haven't checked dispatching where I can see why you would want to have the optional parts but you might get away with specifying a separate route for that purpose:

get 'calendar/:month/:year' => 'calendar#show', 
    as: :calendar,
    constraints: { month: /[a-z]+/, year: /\d{4}/ },
    defaults: { month: Date::MONTHNAMES[Date.today.month].downcase, 
                year: Date.today.year }
# :year can be omitted here as the route before would have caught that
get 'calendar(/:month)' => 'calendar#show', 
    as: :calendar_fallback,
    constraints: { month: /[a-z]+/ }

Upvotes: 1

Related Questions