rails 3.2 delete object url order - ruby-on-rails

When I call the delete action on my on my index.html.erb page for images, it references the correct id's and such, but it does not order them in the url correctly. The url should look like http://localhost:3000/admin/albums/33/images/1, but it displays as http://localhost:3000/admin/albums/33/images.1. I know it has something to do with the .:format, but I'm not sure how to fix it. When I put this in the delete action, admin_album_images_path([#album, image]), it results in http://localhost:3000/admin/albums/33/1/images.
routes
Admin::Application.routes.draw do
get "albums/index"
get "dashboard/index"
namespace :admin do
root :to => "dashboard#index"
resources :dashboard
resources :albums do
resources :images
end
get "admin/album"
end
get "logout" => "sessions#destroy", :as => "logout"
get "login" => "sessions#new", :as => "login"
get "signup" => "users#new", :as => "signup"
# resources :users
resources :basic
root :to => "basic#index"
Controller
class Admin::ImagesController < ApplicationController
def index
#album = Album.find(params[:album_id])
#image = #album.images(params[:id])
#images = Image.all
end
def new
#album = Album.find(params[:album_id])
#image = #album.images.new
end
def create
#album = Album.find(params[:album_id])
#image = #album.images.build(params[:image])
if #image.save
flash[:notice] = "Successfully added image!"
redirect_to [:admin, :albums]
else
render :action => 'new'
end
end
def show
#album = Album.find(params[:id])
#image = #album.images(params[:id])
end
def destroy
#album = Album.find(params[:album_id])
#image = #album.images(params[:id])
#image.destroy
redirect_to admin_albums_path
end
end
View
<% #images.each do |image|%>
<%= image.title %> </br>
<%= image.description %> </br>
<%= image.image_name %> </br>
<%= button_to "Delete", admin_album_images_path(#album, image), :method => :delete, :style => "display: block; float: left;" %>
<%= debug #image %>
<% end %>

you should use
admin_album_image_path(#album, image)
note that both are singular. you can also change that to [:admin, #album, image] so you don't have to worry about the name of the route
An additional parameter will by default become the format so
admin_album_image_path(#album, image, :csv)
will be converted to
/admin/albums/1/images/1.csv

Related

Missing required key :id on new photo form

I have Photo model which belongs to User model. Rails returns this error whenever I try to access new view for /users/4/photos/new:
No route matches {:action=>"index", :controller=>"photos", :user_id=>"4"} missing required keys: [:id]
This is my PhotosController:
class PhotosController < ApplicationController
def index
find_user
#photos = #user.photos
end
def new
find_user
#photo = #user.photos.build
end
def show
find_photo
end
def create
#photo = Photo.new(params[:photo])
if #photo.save
if params[:images]
params[:images].each { |image|
#user.photos.create(image: image)
}
end
else
render 'new'
end
end
def update
find_user
#photo = #user.photos.find(params[:id])
if #photo.update
redirect_to photos_path
else
render 'edit'
end
end
def destroy
find_photo
#photo.destroy
redirect_to photos_path
end
private
def find_user
#user = User.find(params[:user_id])
end
def find_photo
#photo = Photo.find(params[:id])
end
def photo_params
require(:photo).permit(:title, :image, :user_id)
end
end
And this is my _form partial for photos views.
<%= form_for #photo, :html => { class: 'form-horizontal', multipart: true } do |f| %>
<%= f.label :title %>
<%= f.text_field :title, class: "input-field form-control" %>
<%= f.label :pictures %>
<%= file_field_tag "images[]", type: :file, multiplue: true %>
<%= f.submit nil, class: "btn btn-primary" %>
I don't understand how ID is missing, I'm providing it via find_user method.
Update:
# routes.rb
Rails.application.routes.draw do
root 'welcome#index'
# prevedene rute
get "/pocetna" => "welcome#index", as: "index"
get "/o-sajtu" => "welcome#about", as: "about"
get "/moj-profil" => "users#show", as: "profile"
post "/users" => "users#create"
get "/users" => "users#index", as: "users"
get "/user" => "users#index"
get "/users/:id" => "users#show", as: "user"
get "/users/:id/edit" => "users#edit", as: "edit_user"
patch "/users/:id" => "users#update"
get "/users/add" => "users#new", as: "new_user"
resources :sessions, only: [:new, :create, :destroy]
get "/login" => "sessions#new", as: "login"
post "/login" => "sessions#create"
get "/logout" => "sessions#destroy", as: "logout"
delete "/logout" => "sessions#destroy"
resources :users do
resources :photos
end
end
Update
I get new error now
undefined method `photos_path' for #<<Class:0x007f4f14f16160>:0x00000004f040e8>
First line of the form is marked.
change your form_for in _form partial to
form_for([#user, #photo]) do |f|
#rest of your code
end
How do you call the /users/4/photos/new in your view? Ideally you should pass the user_id as id not as user_id. Once, you do that this issue should be resolved.

First argument in form cannot contain nil or be empty (acts_as_commentable error)

So I'm trying to get the acts_as_commentable_with_threading gem working in my app. I would like to allow the users to comment on specific events (events/show.html). I don't think I've set it up properly as I'm getting the below error.
error:
Showing /Users/user/Sites/new_work/app/views/events/show.html.erb where line #36 raised:
First argument in form cannot contain nil or be empty
</div>
<div class="name"></div>
<div id="comments">
<%= form_for #comment do |f| %> <---- it's referring to this line
<div><%= f.hidden_field :event_id, value: #event.id %></div>
<div><%= f.text_field :body, row: 20, placeholder: "Leave a comment" %></div>
<%= f.submit "Post Comment" %>
comments_controller.rb
class CommentsController < ApplicationController
before_filter :load_commentable
def index
#comments = #commentable.current_user.comments
end
def new
#comment = #commentable.current_user.comments.new
end
def create
#comment = #commentable.current_user.comments.new(params[:comment])
if #comment.save
redirect_to #commentable, notice: "Comment created."
else
render :new
end
end
private
def load_commentable
resource, id = request.path.split('/')[1, 2]
#commentable = resource.singularize.classify.constantize.find(id)
end
end
comment.rb snippit only
class Comment < ActiveRecord::Base
attr_accessible :title, :body, :subject
acts_as_nested_set :scope => [:commentable_id, :commentable_type]
validates :body, :presence => true
validates :user, :presence => true
# NOTE: install the acts_as_votable plugin if you
# want user to vote on the quality of comments.
#acts_as_votable
belongs_to :commentable, :polymorphic => true
# NOTE: Comments belong to a user
belongs_to :user
event.rb
class Event < ActiveRecord::Base
attr_accessible :title, :description, :location, :date, :time, :event_date
acts_as_commentable
has_many :comments, as: :commentable
belongs_to :user
after_create :update_event_date
def update_event_date
date = self.date.to_s
time = self.time
hour = Time.parse(time).strftime("%H:%M:%S").to_s
event_date = (date + ' ' + hour).to_time
self.update_attributes(event_date: event_date)
end
end
comments/form.html.erb
<%= form_for [#commentable, #comment] do |f| %>
<% if #comment.errors.any? %>
<div class="error_messages">
<h3>Please correct the following errors.</h3>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
</ul>
</div>
<% end %>
<div class="field">
<%= f.text_field :body, rows: 10, placeholder: "Leave a comment" %>
</div>
<div class="actions">
<%= f.submit "Post comment", class: "btn" %>
</div>
<% end %>
events_controller.rb
class EventsController < ApplicationController
before_filter :authenticate_user!
def index
#user = current_user
#events = Event.all
end
def new
#event = Event.new
end
# def create
# #event = Event.new(params[:event])
# if #event.save
# redirect_to :action => 'index'
# else
# #events = Event.find(:all)
# render :action => 'new'
# end
# end
def create
#event = current_user.events.new(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to :back, notice: 'Event was successfully created.' }
format.json { render action: 'show', status: :created, location: #event }
format.js
else
format.html { render action: 'new' }
format.json { render json: #event.errors, status: :unprocessable_entity }
format.js
end
end
end
def show
#event = Event.find(params[:id])
end
def edit
#event = Event.find(params[:id])
end
def update
#event = Event.find(params[:id])
if #event.update_attributes(params[:event])
flash[:success] = "Event updated."
redirect_to #event
else
render 'edit'
end
end
def destroy
#event = Event.find(params[:id])
#event.destroy
respond_to do |format|
format.html {redirect_to :back}
format.js
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_event
#event = Event.find(params[:id])
end
routes.rb
New_app::Application.routes.draw do
# get 'auth/:provider/callback', to: 'sessions#create'
# get 'auth/failure', to: redirect('/')
root to: "home#landing"
devise_for :users, :controllers => {:registrations => "users/registrations",
:sessions => "users/sessions",
:passwords => "users/passwords",
:omniauth_callbacks => "users/omniauth_callbacks"
}
get "welcome", to: "home#welcome", as: 'welcome'
devise_scope :user do
# get "edit/edit_account", :to => "devise/registrations#edit_account", :as => "account_registration"
get 'edit/edit_account' => 'users/registrations#account_registration', as: :edit_account
end
# patch '/users/:id', to: 'users#update', as: 'user'
get 'profile/:id' => "users#show", as: :profile
get 'disconnect' => 'users#disconnect'
resources :users do
resources :questions
end
resources :photos
resources :events do
resources :comments
end
post "/events/add_new_comment" => "events#add_new_comment", :as => "add_new_comment_to_events", :via => [:event]
resources :questions
end
rake routes for comments
event_comments GET /events/:event_id/comments(.:format) comments#index
POST /events/:event_id/comments(.:format) comments#create
new_event_comment GET /events/:event_id/comments/new(.:format) comments#new
edit_event_comment GET /events/:event_id/comments/:id/edit(.:format) comments#edit
event_comment GET /events/:event_id/comments/:id(.:format) comments#show
PATCH /events/:event_id/comments/:id(.:format) comments#update
PUT /events/:event_id/comments/:id(.:format) comments#update
DELETE /events/:event_id/comments/:id(.:format) comments#destroy
Is #comment defined in the "show" action in your Events controller? Can you post the Events controller code as well?
One thing to double check is to ensure that the action that renders the view for show.html.erb has the #comment variable defined. You seem to be getting the message because the #comment variable in
<%= form_for #comment do |f| %>
Is currently nil when you render the view.
In the "show" action for the events controller, try setting the #comment variable by adding:
#comment = #event.comments.new
Edit 2: Make sure you've setup your routes.rb file to handle comments on events, so assuming youre using RESTful routes, something like this below in your routes.rb. If you could post the routes file that would be helpful too.
resources :events do
resources :comments
end
The error is on app/views/events/show.html.erb which means that your Events controller's show action is missing the #comment variable
def show
#event = Event.find(params[:id])
#comment = ....what ever you need to pull in the comments....
end

Routing Error Nested Resources

I'm build forum rails app, I have problem with nested resources.
here's controller/school/forums_controller.rb
def index
#forums = Forum.all
end
def show
#forum = Forum.find(params[:id])
#per_page = params[:per_page] || 15
#topics = #forum.topics.search(params[:search]).paginate(:per_page => #per_page, :page => params[:page])
end
here's controller/school/topics_controller.rb
def new
#forum = Forum.find(params[:forum_id])
#topik = #forum.topiks.build
end
def create
#forum = Forum.find(params[:forum_id])
#topic = #forum.topics.build(params[:topic])
if #topic.save
redirect_to school_forum_topic_path(#topic)
else
render :action => "new"
end
end
def show
#forum = Forum.find(params[:forum_id])
#topic = Topic.find(params[:id])
end
Here's routes.rb
get '/forum' => 'school/forums#index', :as => :forum_subdomain
namespace :school, :path => '/' do
resources :forums, :path => '/forum', :only => [:show] do
resources :topics
end
end
forum_subdomain GET /forum(.:format)
school/forums#index {:subdomain=>/.+/}
school_forum_topics GET /fr/:forum_id/topics(.:
format) school/topics#index {:subdomain=>/.+/}
POST /forum/:forum_id/topics(.:
format) school/topics#create {:subdomain=>/.+/}
new_school_forum_topic GET /forum/:forum_id/topics/ne
w(.:format) school/topics#new {:subdomain=>/.+/}
edit_school_forum_topic GET /forum/:forum_id/topics/:i
d/edit(.:format) school/topics#edit {:subdomain=>/.+/}
school_forum_topic GET /forum/:forum_id/topics/:i
d(.:format) school/topics#show {:subdomain=>/.+/}
PUT /forum/:forum_id/topics/:i
d(.:format) school/topics#update {:subdomain=>/.+/}
DELETE /forum/:forum_id/topics/:i
d(.:format) school/topics#destroy {:subdomain=>/.+/}
school_forum GET /forum/:id(.:format)
school/forums#show {:subdomain=>/.+/}
when I access subdomain.lvh.me:3000/forum/1-room-biology
Routing Error
No route matches {:action=>"new", :controller=>"school/topics"}
here's views/school/forums/show.html.erb
<%= link_to new_school_forum_topic_path , :class => "btn btn-inverse btn-medium" do %>
New Topic
<% end %>
<% for topic in #topics %>
<%= link_to topic.title, school_forum_topic_path(topic) %>
<% end %>
How do I do this correctly and/or what is the correct way to route all of this?
Your call to new_school_forum_topic_path needs to have the forum provided, eg. new_school_forum_topic_path(#forum).
For more information on nested resource routing in Rails: http://guides.rubyonrails.org/routing.html#nested-resources

undefined method for gallery id

I was following the Railscast tutorial for CarrierWave (#253). However immediately noticed that the creator had already made the gallery model/controller. This was never shown in the video or explained in a different tutorial. I have been creating the gallery and have just about everything working except for this page /photos/new?gallery_id=3 which is suppose to show me a field to upload a photo.
I can go to /galleries and it will list all Galleries created. I can then click on one of the galleries and be taken to /galleries/3 which will present links to Add, Remove, and View Galleries.
The error I am receiving is "undefined method `key?' for nil:NilClass". NoMethodError in PhotosController#new is title of page.
Can someone take a look and point me in the right direction? Thanks.
photos_controller:
class PhotosController < ApplicationController
def new
#photo = Photo.new(:gallery_id => params[:gallery_id])
end
def create
#photo = Photo.new(params[:photo])
if #photo.save
flash[:notice] = "Successfully created photos."
redirect_to #photo.gallery
else
render :action => 'new'
end
end
def edit
#photo = Photo.find(params[:id])
end
def update
#photo = Photo.find(params[:id])
if #photo.update_attributes(paramas[:photo])
flash[:notice] = "Successfully updated photo."
redirect_to #photo.gallery
else
render :action => 'edit'
end
end
def destroy
#photo = Photo.find(params[:id])
#photo.destroy
flash[:notice] = "Successfully destroyed photo."
redirect_to #photo.gallery
end
end
_form.html in views/photos
<%= form_for #photo, :html => {:multipart => true} do |f| %>
<%= f.error_messages %>
<%= f.hidden_field :gallery_id %>
<p>
<%= f.label :name %><br/>
<%= f.text_field :name %>
</p>
<p>
<%= f.file_field :image %>
</p>
<p><%= f.submit %></p>
<% end %>
new.html
<% title "New Photo " %>
<%= render 'form' %>
<p><%= link_to "Back to Gallery", #photo.gallery %></p>
routes.rb
Dating::Application.routes.draw do
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
get 'logout' => 'sessions#destroy'
get 'edit' => 'users#edit'
get "/profile/:id" => "users#show"
resources :users
resources :sessions
resources :password_resets
resources :galleries
resources :photos
root to: 'users#new'
root to: 'galleries#index'

Update database using 'update_attributes' through 'has_many'

I'm having a problem getting my first app (I'm a total newbie) to save a new associated record. I have two models (users and pictures) with a has_many/belongs_to association. I have set up the userController so that it can create a new picture as below:
def new_picture
#user = User.find(current_user.id)
#picture = #user.pictures.build
end
def create_picture
#user = User.find(params[:id])
#picture = #user.pictures.build(params[:picture])
if #picture.save
flash[:notice] = "Your picture was successfully added."
redirect_to :action => 'show', :id => #user.id
else
render :template => "new_picture"
end
end
and I use
<%= link_to("add picture", :action => 'new_picture', :id => #user.id) if current_user %>
to add a new one. But I'd also like to be able to edit. So I updated the usercontroller with some new code:
def edit_picture
#user = User.find(current_user.id)
#picture = #user.pictures.find(params[:id])
end
# When the user clicks the save button update record
def update_picture
#user = User.find(current_user.id)
#picture = #user.pictures.find(params[:picture])
respond_to do |format|
if #picture.update_attributes(params[:picture])
flash[:notice] = "Your picture was successfully updated."
redirect_to :action => 'show', :id => #user.id
else
render :template => "new_picture"
end
end
end
and added the edit link to show.erb:
<%= link_to("edit picture", :action => 'edit_picture', :id => picture.id) if current_user %>
It loads the edit form fine, with the data all in the right place, but on save all it's doing is giving me the error 'ArgumentError in UsersController#update_picture' with a bunch of Unknown key(s) from my pictures table.
Could somebody explain why? I feel like there is one piece of the jigsaw I haven't quite understood here....
Thanks in advance!
UPDATE: View code is as follows:
<h1>New picture for <%= #user.name %></h1>
<% form_for :picture, #picture, :html => { :multipart => true }, :url => {:action => 'update_picture', :id => #user.id} do |f| %>
Can't seem to see your problem in the view code, however you can do the same thing more elegantly (RESTful) as a nested route. That way you might be able to see the problem more clearly.
config/routes.rb:
resources :users do
member do
resources :pictures
end
end
app/controllers/pictures_controller.rb:
class PicturesController < ApplicationController
before_filter :find_picture, :only => [:edit, :update]
def edit
end
def update
if #picture.update_attributes params[:picture]
flash[:notice] = "Your picture was successfully updated."
redirect_to user_path(current_user)
else
render :edit
end
end
protected
def find_picture
#picture = current_user.pictures.find params[:id]
end
end
app/views/pictures/edit.html.erb:
<%= form_for [current_user, #picture] do |f| %>
<!-- some stuff -->
<% end %>
and to link to your edit form:
<%= link_to_if current_user, 'edit picture',
edit_user_picture_path(:user => current_user, :id => picture) %>
I suggest adding 'accepts_nested_attributes_for :pictures to the user model, and then do
<%= form_for #user do |form| %>
.. user fields
<%= form.fields_for :pictures do |picture_form| %>
.. picture fields
<% end %>
<%= form.submit %>
<% end %>
in the view.
Another option is to create a new controller for the pictures. That may be simpler.

Resources