I upgraded an app I am working on from Rails 3.0.0.beta4 to Rails 3.0.0 and hit an unexpected error. I'm using authlogic for authentication, and after the upgrade the route for new user session form started throwing this error.
undefined method `user_sessions_path'
Ok, I'm using a singular controller name. Not sure what is different between beta4 and the new release that caused the problem.
In my routes.rb file I have this:
get "user_session/new", :as => :login
get "user_session/destroy", :as => :logout
resources :user_session, :controller => :user_session
Which defines my singular controller routes.
To fix the problem I had to change the first line of the form from this:
<%= form_for #user_session do |f| %>
to this:
<%= form_for #user_session, :url => user_session_index_path do |f| %>
What is striking me as weird is the name of the route. Running rake routes revealed the name of the route, but I don't understand why the index was needed. I was expecting something more like user_session_path for the post method. My user_session routes are the only ones acting this way. All of the other are as I expect.
Heres the output from rake routes:
user_session_index GET /user_session(.:format) {:action=>"index", :controller=>"user_session"}
user_session_index POST /user_session(.:format) {:action=>"create", :controller=>"user_session"}
This works, but I'm curious to know if anyone else has encountered this.
First of all, I don't understand, why do you specify the controller name, when it is the same as the resources name? Those two, are equivalent:
resources :user_session, :controller => :user_session
resources :user_session
AFAIR by design create just does POST onto the same path as index. By definition, when controller name is singular, router won't be able to create a plural version of the name. It works the other way around. Thus, theres a _index suffix in both index and create actions.
Singular name would suggest, that the resource is singular, so you should just use (sigular for resource):
resource :user_session
In this case there will be no index action (as it makes no sence for singular resource), and the name for create path will be user_session_path.
As a side note, singular resource doesn't imply, that there is only one instance of the model. It just specifies how do you access the resource. For example you can have multiple users with profiles, but there is perfect sense to use singular resource in order to manage the profiles, since each use can only access his own profile.
ps. I moved on to Devise for authentication before Rails 3 and I don't quite remember how routes used to be solved in Authlogic.
Related
I have some problem/issues with active admin on rails, specifically unpermitted params error:
existing active admin parameter
here is the existing active admin parameter
model associated with the main model im working with
As per active admin documentation I should be doin right, as the other attributes for dispatch_information model is being accepted by rails and I was able to read and write with out any issues. Just with this recently added attribute "custom_attorney". Associations already set. and with out declaring an attr_accessor on model file it says this error
No method error
as it seems it cannot read or detect the column that I added for dispatch_information model, while in my console its already there.
When I add it with attr_accessor "while it should not, just to proceed on the form page" then I fill in the attributes need, im getting weird stuff in my console
Console view
as you can see it seems it being added inside efile_order hash instead of dispatch_information_attribute hash, and at the bottom part of the image you can see it says unpermitted parameters, even I added it inside the correct attribute block, we can also notice that the other attributes pf dispatch_information works really fine, just this recently added custom_attorney attribute. I already did everything like migration and other stuff.
Form Input
here is my form where we can see that input is on the same block where dispatch_defendant and dispatch_plaintiff is included and those two attribute works fine as well.
I really dont know what I missed here. TIA
The problem is that custom_attorney should be nested under dispatch_information_attributes you have it in the wrong place so it's unpermitted.
The correct way to do that is to add a block for those attributes and nest them.
- f.simple_fields_for :dispatch_information do |d|
- d.input :custom_attorney, :input_html => { id: 'new-attorney' }
It may be a good idea to provide an object for dispatch_information if you care for existing data. Assuming your ivar is named #e_filling_order then you should have the following.
- f.simple_fields_for :dispatch_information, #e_filling_order.dispatch_information || #e_filling_order.build_dispatch_information do |d|
Ok first off I have to say I'm very new to Rails. I have spent the last few days going through tutorial after tutorial and still missing a few concepts. Mainly because I just want to start off with a simple site structure but every tutorial is either a shopping cart or a blog which are more applications within a site. I have some pages on my site that will have photo galleries that are database driven but for now I'm just trying to get some answers to these questions.
Site structure:
home | photos | about | work | contact
Work has sub pages for example:
html | ruby | rails | bla-bla
Controllers:
Do I need to set up a controller for every new page or could I have one controller that handles all main level pages.
If I could use one controller how would that work and would I need to define an action to handle each page ( view ) like
class MainController < ApplicationController
def index
end
def photos
end
def contact
end
# and so on ......
end
Routing:
How would I route the above.
Whats the difference between a resource and a *get
get "photos/photos"
resources :photos
When I setup a controller for a specific page like.
rails g controller Contact contact
It creates a folder inside my views called contact and inside it is a view called contact meaning my url is contact/contact
it also adds a route get "contact/contact"
Now what if I only want the user to type http://mydomain/contact then this is not going to work. How would I set it up so the user doesn't have to add http://mydomain/contact/contact
The only way I could find a way around this was to use the match verb.
match "contact" => 'contact#contact'
Does this mean I have to use the match for every page on my site to change the url path?
These are just a few of many question I have that are not so clear in most of the tutorials I have gone over. Please don't tell me to use the user guide as I have already and am felling overwhelmed right now. I just would love some clear answers from some developers who are working in rails and would go about setting up a structure like I have outlined above.
Thanks
You're going to get some conflicting advice I think, but here's what I'd do.
Create a MainController (I prefer HomeController as it will also handle the homepage, but that's just me). This controller will handle the actions for home, about, and contact.
Create a PhotosController since you said photos come from the database and there's a good chance there is an index/listing page and individual pages for each photo.
Create a WorksController that handles the work main page and all the sub pages.
Now.. some people would argue (myself included) that home, about, contact, and all the work pages (sub pages too) should be handled by a generic PagesController that is smart enough to know what to do. I'm not gonna get into that now though.
The difference between these two routes:
get "photos/photos"
resources :photos
Is that the first will only create a single route for a GET request to '/photos/photos'. The second will create the standard CRUD operations for '/photos'.
For your static pages, I probably would go ahead and just create:
match "about" => 'main#about'
match "contact" => 'main#contact'
...
It's harder to say for the photos and work since I don't know what all you'll be doing there. The above isn't as DRY as it could be, but unless you go the "smart pages controller" route it's the simplest.
I seem to require in Rails 3.1 for a nested resources both, instead of having photo just nested:
resources :photos
resources :gallery do
resources :photos
end
Otherwise my form_for will not work for photos to submit or galleries to view:
<%= form_for ([#gallery, #photo],:html => {:multipart => true}) do|f| %>
Complaining on show of gallery:
No route matches {:id=>#<Photo id: 23 ...
Is that normal behavior, I always want my users to only be able to create photos in the context of a gallery, but now they can also access photos/new while I would only let them access gallery/:id/photos/new
Routes can be tricky. Sometimes using the plural instead of the singular form causes an error, especially for path helpers. The plural of "Gallery" is "Galleries"
>> "Gallery".pluralize
=> "Galleries"
Check your routes with rake routes, I think for your purpose you should use the plural form
resources :galleries do
resources :photos
end
I'm currently having some problems with setting up the right routes for my application.
In short I would like to have URLs like so:
explanation:
Show actual page for the selected poll
abstract:
localhost:3000/polls/:category_slug/:poll_id
example:
localhost:3000/polls/technology/1337
routes.rb
get 'polls/:category_slug/:poll_id' => 'polls#show', :as => :poll
Furthermore the user should be able to filter the polls against some criteria, like show Top-Polls, New-Polls and so on...
explanation:
Show a list of polls, which are matching the selected criteria
abstract:
localhost:3000/polls/:category_slug/:filter_mode
example:
localhost:3000/polls/technology/top
routes.rb
get 'polls/:category_slug/:filter_mode' => 'filter#by_mode', :as => :polls_filter
And here's the problem
ActiveRecord::RecordNotFound : Couldn't find Poll with ID=top_all
The second route ('polls/:category_slug/:filter_mode') is overwriting the first route so Rails recognizes the :filter_mode as a :poll_id.
So my question is, how can I change this behavior, so both routes will actually work without overwriting each other ? (the first route will work perefectly, when I leave out the second one)
I hope someone understands my problem, appreciate every help.
You can set a constraint on the filter one to take only strings, and then put it before the other one. It will fall through to the poll_id one.
I'm getting strange output when using the following routing setup:
resources :warranty_types do
resources :decisions
end
resource :warranty_review, :only => [] do
resources :decisions
end
I have many warranty_types but only one warranty_review (thus the singular route declaration). The decisions are polymorphically associated with both. I have just a single decisions controller and a single _form.html.haml partial to render the form for a decision.
This is the view code:
= simple_form_for #decision, :url => [#decision_tree_owner, #decision.becomes(Decision)] do |form|
The warranty_type url looks like this (for a new decision):
/warranty_types/2/decisions
whereas the warranty_review url looks like this:
/admin/warranty_review/decisions.1
I think because the warranty_review id has no where to go, it's just getting appended to the end as an extension.
Can someone explain what's going on here and how I might be able to fix it?
I can work around it by trying to detect for a warranty_review class and substituting #decision_tree_owner with :warranty_review and this generates the correct url, but this is messy. I would have thought that the routing would be smart enough to realise that warranty_review is a singular resource and thus discard the id from the URL.
This is Rails 3 by the way :)
Apparently it's a long standing rails bug where polymorphic_url has no way of knowing whether a resource is singular or not from the routes setup:
https://rails.lighthouseapp.com/projects/8994/tickets/4077-wrong-redirect-after-creation-of-nested-singleton-resource-using-responder
I'm just going to resort to using a non-singular route even though there will only ever be one warranty_review. It's just aesthetics at the end of the day.