I've got shallow nested resource routes like below:
resources :venues, shallow: true do
#Halls
get "hall/:id/exhibition" => "halls#exhibition", as: :exhibition
get "hall/:id/visit" => "halls#visit", as: :hall_visit
get "structure", :to => "venues#venue_structure"
resources :asset_types, :booths_tags, :tags, :uploaded_files, :events, :chats
resources :halls do
resources :webcasts
resources :booths do
resources :chats
end
end
end
Below is a simple_form that is currently being used.
= simple_form_for(hall_booths_path(#booth), :html => { :class => "form-horizontal" }, :wrapper => "horizontal", defaults: { :input_html => { class: "form-control"}, label_html: { class: "col-lg-4" } } ) do |f|
= f.simple_fields_for #booth do |b|
The problem is that hall_booths_path(#booth) part is generating /halls/1/booths/new instead of /halls/1/booths
Is there something wrong here that needs fixing?
my booths routes:
hall_booths_path GET /halls/:hall_id/booths(.:format) booths#index
POST /halls/:hall_id/booths(.:format) booths#create
new_hall_booth_path GET /halls/:hall_id/booths/new(.:format) booths#new
edit_booth_path GET /booths/:id/edit(.:format) booths#edit
booth_path GET /booths/:id(.:format) booths#show
PATCH /booths/:id(.:format) booths#update
PUT /booths/:id(.:format) booths#update
DELETE /booths/:id(.:format) booths#destroy
Pass the path in the options hash, not as the first argument:
<%= simple_form_for :booth, :url => hall_booths_path(#hall) do |f| %>
...
<% end %>
Note that the argument to hall_booths_path is a Hall, not a Booth. When you create a child, you need to supply the parent.
Another option is to pass not the URL but the model objects. Assuming #hall is an existing Hall and #booth is a new Booth:
<%= simple_form_for [#hall, #booth] do %>
...
<% end %>
I find this approach much simpler.
Related
I'm developing a rails app with a landingpage. On the landingpage, the user can sign up for the app. For login, there is an extra view with an extra controller.
It looks like this:
views/landinpage/index.html --> sign up form
views/login/index.html --> login form
but I only want to have one controller
controllers/login_controller --> create new user from sign up form & check login data
so I have to get a connection between the landingpage view and the login_controller.
This is my attempt:
<%= form_for #login, :url => { :controller => "login_controller", :action => "create" }, :html => {:method => :post} do |f| %>
but it throws a route error:
No route matches {:controller=>"login_controller", :action=>"create"}
I already defined login resources in routes.rb, but it seems that the problem is elsewhere?
resources :logins
any ideas?
try this
class LoginsController < ApplicationController
def new
...
end
def create
...
end
...
end
in your route.rb file write
match '/login/create' => 'logins#create', :as => :create_login
or
resources :logins
in your console - write - rake routes and check your routes
then
<%= form_for #login, :url => create_login_path(#login) do |f| %>
I think your code should look like this:
<%= form_for #login, :url => { :controller => "login", :action => "create" }, :html => {:method => :post} do |f| %>
can't test this right now, but I believe the _controller part is not required.
Update:
Another thing that I'm using a lot and that works:
<%= form_for #login, :url => create_login_path(#login), :html => {:method => :post} do |f| %>
You may have to fix the create_login_path part to match your application's routes but that's how I usually define these views.
Try this
class LoginsController < ApplicationController
def new
...
end
def create
...
end
...
end
in your routes.rb file
resources :logins do
collection do
post :create
end
end
and in your views
<%= form_for #login, :url => create_login_path(#login) do |f| %>>
you can see the html form action part, you can see!
your config/routes has
resources :posts
namespace :admin do
resources :posts
end
I have this in my view:
<%= form_for #comment, :as => :post, :url => user_ticket_message_comments_path, :html => { :class => "add-comment", :id => "add-comment-" + #ticket.id.to_s } do |f| %>
<%= f.label :body, "Add comment" %>
<%= f.text_area :body %>
<%= f.submit "Add comment" %>
<% end %>
In my routes.rb:
resources :users do
resources :tickets do
resources :messages do
resources :comments
end
end
end
I get a routing error:
No route matches {:controller=>"comments"}
It looks like you are missing the user, ticket and message:
user_ticket_message_comments_path(#user, #ticket, #message)
You need those parameters, because the URL generated looks like this:
/users/:user_id/tickets/:ticket_id/messages/:message_id/comments
without the arguments, Rails doesn't know how to generate that URL.
Also, consider that the rule of thumb in Rails apps is that "Resources should never be nested more than 1 level deep."
This post by Jamis Buck suggests that instead of arbitrarily nesting resources, you only use one level of nesting like this:
resources :users do
resources :tickets
end
resources :tickets do
resources :messages
end
resources :messages do
resources :comments
end
I'm making a website with a page where users can sign up to win an iPad. I created a model ipad.rb and an ipads_controller.rb and there were three columns in the migration for name, email and twitter handle. I was surprised when Rails didn't create routes automatically (I thought it was supposed to do that always).
I added this in the routes file
resource :ipad
match '/signup', :to => 'ipads#new'
When I tried to create the sign up form, I got this error message before fully completing it
undefined method `ipads_path' for #<#<Class:0x00000103a64ec0>:0x00000103a49aa8>
This surprised me because why was it plural?
So far I've only created a form in new.html.erb and the model ipad.rb and two actions in the ipads_controller.rb new and create.
Can anyone see what i'm doing wrong? i.e. why does Rails think I need a method ipads_path. Also note that I had created a model IPad.rb but deleted it and the migrations.
new.html.erb
<h1>Win an iPad</h1>
<h1>Sign up for iPad</h1>
<%= form_for(#ipad) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
ipad.rb
class Ipad < ActiveRecord::Base
attr_accessible :name, :email, :twitter
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => true
end
ipads_controller.rb
class IpadsController < ApplicationController
def new
#ipad = Ipad.new
#title = "iPad Contest"
end
def create
#ipad = Ipad.new(params[:ipad])
if #ipad.save
# Handle a successful save.
else
#title = "iPad Contest"
render 'new'
end
end
end
routes.rb
Enki::Application.routes.draw do
namespace 'admin' do
resource :session
resources :posts, :pages do
post 'preview', :on => :collection
end
resources :comments
resources :undo_items do
post 'undo', :on => :member
end
match 'health(/:action)' => 'health', :action => 'index', :as => :health
root :to => 'dashboard#show'
end
resources :archives, :only => [:index]
resources :pages, :only => [:show]
resource :ipad
match '/signup', :to => 'ipads#new'
constraints :year => /\d{4}/, :month => /\d{2}/, :day => /\d{2}/ do
get ':year/:month/:day/:slug/comments' => 'comments#index'
post ':year/:month/:day/:slug/comments' => 'comments#create'
get ':year/:month/:day/:slug/comments/new' => 'comments#new'
get ':year/:month/:day/:slug' => 'posts#show'
end
scope :to => 'posts#index' do
get 'posts.:format', :as => :formatted_posts
get '(:tag)', :as => :posts
end
root :to => 'posts#index'
end
Your resource 'ipad' should be plural in the routes, i.e.
resources :ipads
In my routes i have:
resources :accounts do
resources :transfers
put '/transfers/:id(.:format)' => 'transfers#accept'
end
In my model:
class Transfer
include DataMapper::Resource
belongs_to :account
belongs_to :alias_from, "Alias"
belongs_to :alias_to, "Alias"
class Account
include DataMapper::Resource
belongs_to :user
has n, :transfers
In my view:
<% #transfers_in.each do |income|%>
Amount: <%= income.amount%> <%= income.account.currency%>
<% form_for ([???, income]), :as => :transfer, :url => {:controller=>'transfers', :action => 'accept'} do |f|%>
Choose the account <%= f.collection_select :account, #accounts, :name, :name %>
<%= f.submit :value => "Accept" %>
<% end %>
<% end %>
How should I call for the account here, if here #transfers_in is called by other association?
#aliases = #owner.aliases.all()
#transfers_in = #aliases.transfers_in.all()
I've tried something like
<% #acc = Account.all()%>
<% #trs = #acc.transfers.get(:id => income.account)%>
<% form_for ([#trs, income]), ....
but that gave me
No route matches
{:controller=>"transfers",
:action=>"accept"}
In rake routes such route exists.
Would be thankful for any help.
In your routes, you should have better results using the macros Rails provides for routing. Instead of doing the old-style route map, try:
resources :accounts do
resources :transfers do
put 'accept', :on => :member
end
end
The router is really smart when it comes to RESTful routes, but when you start manually mapping things, it can get confused... especially when you're doing it inside of nested, RESTful routes.
I have the following two models:
class PhotoAlbum < ActiveRecord::Base
belongs_to :project
has_many :photos, :dependent => :destroy
class Photo < ActiveRecord::Base
belongs_to :photo_album
When the user is viewing a photo, the URL is like follows: "/photo_albums/40/photos?page=6"
On this photo view page (inside an album) I want to give the user the option to update the image, so I'm using the following:
<% form_for [:photo, #photos.first], :url => photo_album_photos_path, :html => { :multipart => true } do |f| %>
<form method="post" id="edit_photo_124" enctype="multipart/form-data" class="edit_photo" action="/photo_albums/40/photos" accept-charset="UTF-8">
Which I think is right? Problem is, when I click update, I get the following error:
No route matches "/photo_albums/40/photos"
Here are my routes, which look good, no?
photo_album_photo PUT /photo_albums/:photo_album_id/photos/:id(.:format) {:action=>"update", :controller=>"photos"}
photo PUT /photos/:id(.:format) {:action=>"update", :controller=>"photos"}
Thoughts? thanks
UPDATE w config route file:
resources :photos do
resources :comments, :only => [:create, :update,:destroy], :constraint => {:context_type => "photos"}
collection do
post 'upload'
get 'search'
end
end
resources :photo_albums do
resources :comments, :only => [:create, :update,:destroy], :constraint => {:context_type => "photo_albums"}
resources :photos
collection do
get 'search'
end
end
Try to change your form to something like:
<% form_for [#photo_album, #photos.first], :html => { :multipart => true } do |f| %>
where #photo_album is your photo_album object, or
<% form_for #photos.first, :url => photo_album_photo_path(#photo_album, #photo), :html => { :multipart => true } do |f| %>
which is basically the same. To have this working, you should have the following in your route.rb:
resources :photo_albums do
resources :photos
end