Rails: form_for namespaced resource - ruby-on-rails

I want to set up the CRUD for users, available just for administrators of my web application.
So in routes.rb:
namespace :admin do
resources :user
end
which means this:
admin_user_index GET /admin/user(.:format) admin/user#index
POST /admin/user(.:format) admin/user#create
new_admin_user GET /admin/user/new(.:format) admin/user#new
edit_admin_user GET /admin/user/:id/edit(.:format) admin/user#edit
admin_user GET /admin/user/:id(.:format) admin/user#show
PUT /admin/user/:id(.:format) admin/user#update
DELETE /admin/user/:id(.:format) admin/user#destroy
Show, index work fine but edit and new don't. I keep getting this error in the _form first line:
undefined method `user_path' for #<#:0x007fb6645c6378>
which is this:
How can I use form_for with a namespaced resource?

You can add the namespace's name as a symbol:
<%= form_for [:admin, #user] do |f| %>

When you use form_for, it assumes that the appropriate path is [model_name]_path. You have to explicitly tell it the url with
form_for #user, url: admin_user_path

Related

No route matches [POST] "/articles/new" - Why?

I made the following introduction:
http://guides.rubyonrails.org/getting_started.html
And after that, I wanted to create a new field (like title) and got the error notification:
Here is my code:
routes.rb
Rails.application.routes.draw do
get 'welcome/index'
resources :articles do
resources :comments
resources :description
root 'welcome#index'
# For details on the DSL available within this file, see guides.rubyonrails.org/routing.html
end
end
I know that this question has been asked a lot but their solutions didn't helped me.
What should I do?
Regards
The problem is in your new.html.erb form, you are missing url: articles_path, if you don't specify it, the form will be sent to the same action (i.e. new). So, since submitting the form uses POST (by default) method, you get:
No route matches [POST] “/articles/new”
You need to change your form_for and specify the url, like this:
<%= form_for :article, url: articles_path do |f| %>
From the same link your provided:
There's one problem with this form though. If you inspect the HTML
that is generated, by viewing the source of the page, you will see
that the action attribute for the form is pointing at /articles/new1.
This is a problem because this route goes to the very page that you're
on right at the moment, and that route should only be used to display
the form for a new article.
1 My emphasis.
By default rails new resource route has a GET HTTP verb, not POST. Unless you specified otherwise.
Seems like you are using new_article_path or articles/new in the form
<%= form_for :article, url: new_articles_path do |f| %>
Change it to
<%= form_for :article, url: articles_path do |f| %>

Rails run :get route within /new and /edit _form

I have a _form for new and edit for a #Giveaway object. Within this form I have a field for a random winner.
I want to populate this field by calling the method giveaways#random_winner with <%= button_to "Randomly Pick Winner!", {:action => 'choose_winner'}, :method => :get %>, but I am getting this error No route matches {:action=>"choose_winner", :controller=>"giveaways"} when loading /giveaways/new.
Here is my controller:
def choose_winner
random_winner = SubscriberUser.where(user_id: current_user.id).pluck(:subscriber_id).sample(1)
session[:random_winner] = random_winner
redirect_to :back
end
Here are the routes that I have tried. I'm not very good at non-scaffold routes yet:
resources :giveaways do
member do
get 'choose_winner' => 'giveaways#choose_winner'
#tried get :choose_winner, as: :choose_winner
#tried get 'new/choose_winner'
#tried get 'choose_winner'
#tried get 'choose_winner', to: 'giveaways#choose_winner', as: 'choose_winner'
end
end
Question -- Why is the page not loading when I have defined the controller and action in the route? Will I have to reload the page when I do run that route... is there a better way to get at this data?
Your routes.rb is close
resources :giveaways do
member do
get :choose_winner
end
end
And then I would use a Rails route helper so you don't have to worry about setting the action/controller yourself.
<%= button_to "Randomly Pick Winner", choose_winner_giveaway_path(#giveaway), method: :get %>

Controller/Action not found although physically present?

My attempt to make a new-action which gives the user a form and a create-action to process it fails with the error message `.
View: app/views/studios/new.html.erb:
<%= form_for #studio, url: {action: 'create'} do |f| %>
<%= f.text_field :name %>
<%= f.submit 'Create' %>
<% end %>
Controller: app/controllers/studio_controller.rb:
def new
#studio = Studio.new
respond_to do |format|
format.html
format.json { render json: #studio }
end
end
def create
# TODO
end
Route: config/routes.rb
get 'studios/new' => 'studios#new', :as => 'new_studio'
On attempting to visit http://localhost:3000/studios/new, I am presented with the error
No route matches {:action=>"create", :controller=>"studios"}
As you can see, the create-action is present in the studios-controller. Why is it failing?
It's failing because you don't have route defined for the create action. You have a get action defined for the new action only.
Update your routes file to add a post route to the create action as:
post 'studios/create' => 'studios#create'
Or, you could choose to use resourceful routing and update your routes file as:
resources :studios, only: [ :new, :create ]
This will define the new and create route for your studio resource. To see the generated routes you can run rake routes.
The rails form helper, given the instance variable #studio, asks for the instance variable via the new action, and, upon clicking save, calls the create action to validate and save this new instance. It's failing because rails cannot find the action to submit the object to.
Try adding resources :studios for RESTful routes in config/routes.rb (index, new, create, show, edit, update, destroy) automagically routing to actions with the same name in the app/controllers/studio_controller.rb
Try visiting the docs for form helpers here: http://guides.rubyonrails.org/form_helpers.html#binding-a-form-to-an-object for a more in depth explaination.

NoMethodError when rendering a form Rails

routes.rb:
resources :shops
shop_controller.rb:
def new
#shop=Shop.new
end
new.html.erb:
<%= form_for(#shop) do |f| %>
....
<% end %>
error:
undefined method `shops_path' for:
<%= form_for(#shop) do |f| %>
The problem is that I already specify the shop resources in the routes file.
Why still get such kind of error?
Any help will be appreciated, thanks
You should use ShopsController not ShopController due to Rails naming convention.
Make sure you have these lines in your rake routes output:
shops GET /shops(.:format {:action=>"index", :controller=>"shops"}
POST /shops(.:format) {:action=>"create", :controller=>"shops"}
OR
shops POST /shops(.:format) {:action=>"create", :controller=>"shops"}
If they aren't present, look carefully at your routes.rb for possible with_options, scope or any other scoping that can affect your resources :shops in such a way that it doesn't generate default url helpers.
since u havent specified the method in the form tag, i guess it is going as a GET request. Try adding the method to ur form
<%= form_for(#shop), :method => :post do |f| %>

How do I render a partial for a view of a nested resource? - Rails 3.1

This is my route:
scope ":username" do
resources :feedbacks
end
I am on my home/index.html.erb view and I am trying to do this:
<%= render "feedbacks/form" %>
But this gives me this error:
ActionView::Template::Error (No route matches {:controller=>"feedbacks", :format=>nil}):
1: <%= form_for(#feedback) do |f| %>
2: <% if #feedback.errors.any? %>
3: <div id="error_explanation">
4: <h2><%= pluralize(#feedback.errors.count, "error") %> prohibited this feedback from being saved:</h2>
app/views/feedbacks/_form.html.erb:1:in `_app_views_feedbacks__form_html_erb__3181571289116259961_2487495480'
app/views/home/index.html.erb:18:in `_app_views_home_index_html_erb___397233383548615486_2487321620'
This is my rake routes for feedbacks:
feedbacks GET /:username/feedbacks(.:format) {:action=>"index", :controller=>"feedbacks"}
POST /:username/feedbacks(.:format) {:action=>"create", :controller=>"feedbacks"}
new_feedback GET /:username/feedbacks/new(.:format) {:action=>"new", :controller=>"feedbacks"}
edit_feedback GET /:username/feedbacks/:id/edit(.:format) {:action=>"edit", :controller=>"feedbacks"}
feedback GET /:username/feedbacks/:id(.:format) {:action=>"show", :controller=>"feedbacks"}
PUT /:username/feedbacks/:id(.:format) {:action=>"update", :controller=>"feedbacks"}
DELETE /:username/feedbacks/:id(.:format) {:action=>"destroy", :controller=>"feedbacks"}
Edit 1
When I pass in the local instance variable #feedback like this: <%= render "feedbacks/form", :local => #feedback %> which is pulling from my home controller, where it is declared like this:
class HomeController < ApplicationController
def index
#users = User.all
#feedback = Feedback.new
end
end
I still get this error:
Routing Error
No route matches {:controller=>"feedbacks", :format=>nil}
Edit 2
I also have a users resource specified in my routes file, that looks like this:
resources :users
scope ":username" do
resources :feedbacks
end
Seems like form_for can't find the correct route, this line suggests you don't have an instance variable #feedback set when trying to render that partial:
(No route matches {:controller=>"feedbacks", :format=>nil})
Notice there is no :id parameter in that hash (which is likely being passed to the router to generate the correct URL to submit the form to).
Do you define a #feedback somewhere in the controller action (preferable) or views you're using? If you think you are, try the following above line 1 of your partial:
logger.info "feedback object: #{#feedback.inspect}"
Edit:
First of all, locals should be passed not as :local => #feedback but as:
:locals => {:variable_name_in_partial => value_for_variable_name}
Second of all, you are trying to access #feedback which is an instance variable accessible to views even if it's not passed explicitly (as long as it's set). So as long as you set it in the HomeController#index method you don't need to pass it to any views locally.
Also, you are not using the correct syntax for rendering partials (wish I had noticed earlier!).
Change the following:
<%= render "feedbacks/form" %>
To this:
<%= render :partial => "feedbacks/form" %>
Aren't you forgetting to pass in :username? Your route says scope :username
If I add a route like yours, open up the Rails console, include Rails.application.routes.url_helpers and run feedbacks_path, I get a routing error, but feedbacks_path :username => 'bob' works fine.
> feedbacks_path(:username => 'bob')
=> "/bob/feedbacks"
Are you sure you want scope? What about a nested resource as per:
resources :users do
resources :feedbacks
end
Also, I've had trouble when using controllers with plural names. You might try renaming FeedbacksController to FeedbackController.

Resources