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'
Related
I tried to use paperclip to include Images in my design of a blog. I keep getting the error :
ActionController::UrlGenerationError in ArticlesController#create
No route matches {:action=>"show", :controller=>"articles"} missing required keys: [:id]
Now, whenever I click on the submit button to create a new article, it says "Could not find article without id". I tried also accessing the view for the show page through a link and I could not.
Extracted source (around line #30):
Here is my Articles Controller
class ArticlesController < ApplicationController
def index
#articles = Article.all
end
def show
#article = Article.find(params[:id])
#comment = Comment.new
#comment.article_id = #article.id
end
def new
#article = Article.new
end
def create
#article = Article.new(article_params)
#article.save
redirect_to article_path
end
def edit
#article = Article.find(params[:id])
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
def update
#article = Article.find(params[:id])
#article.update(article_params)
flash.notice = "Article '#{#article.title}' Updated!"
redirect_to article_path
end
def article_params
params.require(:article).permit(:title, :body, :tag_list, :image)
end
end
Here is my articles Helper:
module ArticlesHelper
def article_params
params.require(:article).permit(:title, :body, :tag_list, :image)
end
end
Here is my articles/show.html.erb
<h1><%= #article.title %></h1>
<p>
Tags:
<% #article.tags.each do |tag| %> <%= link_to tag.name, tag_path(tag) %>
<% end %>
</p>
<% if #article.image.exists? %>
<p><%= image_tag #article.image.url %></p>
<% end %>
<p><%= #article.body %></p>
<h3>Comments (<%= #article.comments.size %>)</h3>
<%= render partial: 'articles/comment', collection: #article.comments %>
<%= render partial: 'comments/form' %>
<%= link_to "<< Back to Articles List", articles_path %>
<%= link_to "delete", article_path(#article), method: :delete, data: {confirm: "Really delete the article?"} %>
<%= link_to "edit", edit_article_path(#article) %>
And here is my routes file
TheBlog::Application.routes.draw do
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
get 'article' => 'articles#show'
resources :users
resources :articles do
resources :comments
end
resources :tags
end
The error is telling you that you're missing the :id parameter when attempting to generate the article show route in your ArticlesController.
The resources :articles line in your config/routes file will generate a number of routes helper methods, including article_path for the show route. By default, this helper method requires one argument - one that is can translate into the aforementioned :id param. This argument should be an article id or, more commonly, an instance of an article. You need to tell Rails to which article show page to send the user, right?
Hence, you need to pass an article instance to your call to article_path in your create action (and update it appears). Here is a rewrite of your create action:
def create
#article = Article.new(article_params)
#article.save
redirect_to article_path(#article)
end
I am having trouble setting the user_id on the creation of a post
def create
#post = Post.new(post_params)
#post.user_id = session[:id]
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render action: 'show', status: :created, location: #post }
else
format.html { render action: 'new' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
The error I get is specifically undefined method 'username' for nil:NilClass when redirected to the show action. A look at the database shows that no user_id is set.
I also tried passing the user_id as a hidden field. but this did not work either (a look at the logs showed the hidden field wasn't even being passed for some reason).
Would appreciate a point in the right direction,
Thank you !
EDIT: as requested here is the show controller
def show
#post = Post.find(params[:id])
#original_id = params[:original_id]
#comment = Comment.new
end
<%= form_for [:admin, #post] do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Below is the form
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :content %><br>
<%= f.text_area :content %>
</div>
<div class="field">
<%= f.label :category %><br>
<%= f.text_field :category %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Routes:
root 'posts#index'
resources :posts do
resources :comments, shallow: true
end
resources :users, only: [:create]
#Posts
get "/meta", to: "posts#meta"
#User Routes
get "/signup", to: "users#new"
get "/success", to: "users#index"
#login Routes
get "/login", to: "sessions#login"
post "/sessions/login_attempt", to: "sessions#login_attempt"
#session routes
get "/sessions/home", to: "sessions#home"
get "/sessions/logout", to: "sessions#logout"
#admin routes
#resources :posts, module: 'admin', except: [:show, :index]
namespace :admin do
root 'posts#new'
resources :posts, except: [:show, :index]
end
Inside of your create method add
#post = Post.build(params[:post])
#post.user_id = current_user.id
This will grab the current user id for the given post.
If you have a has_many relationship between posts and users, why not do something like this:
#user = User.find(params[:id])
#post = #user.posts.new(params[:post])
The params might be different but this is the 'more ruby' way do do things. It explicitly notes the relationships between the two models. The above code should be in the #new action and then you would save it within the create action.
I feel like an idiot now but the issue was I was using session[:id] as opposed to session[:user_id]
Set in my sessions controller
def login_attempt
authorized_user = RegisteredUser.authenticate(params[:username_or_email],params[:login_password])
if authorized_user
session[:user_id] = authorized_user.id
flash[:notice] = "Wow Welcome again, you logged in as #{authorized_user.username}"
redirect_to(:action => 'index', :controller => "users")
else
flash[:notice] = "Invalid Username or Password"
flash[:color]= "invalid"
render "login"
end
end
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
Having a bit of trouble with the following ruby on rails code snippet - I have books and would like to update a book's name, here is how I try to do it:
<h1>Edit the book "<%= #book.name %>"</h1>
<%= form_tag action: :update, id: #book do %>
<p>
<label for="book_name">Name</label>
<%= text_field :book, :name %>
<%= submit_tag 'Save changes' %>
</p>
<% end %>
This is what I do in the books controller:
def edit
#book = Book.find(params[:id])
end
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to :action => 'show', id => #book
else
#subjects = Subject.find(:all)
render :action => 'edit'
end
end
These are my routes:
root to: 'authors#index'
resources :books, :authors
When I click the submit button in the form, it gives me No route matches [POST] "/books/5" and directs to localhost:3000/books/5 instead of staying and localhost:3000/books/5/edit
What am I doing wrong here? Shouldn't there be a put method for updating stuff somewhere rather than a post method?
Updates should use put not post.
<%= form_tag( { :controller => :books, :action => :update, :id => #book.id }, { :method => :put } ) do %>
or better yet use form_for
<%= form_for #book do |f| %>
On your console run "rake routes" and it will print out all available routes.
Please try this:
We need to specify match in routes file.
match "/books/:id" => "books#update"
resources :books should do the job. you dont have to explicitly use "match".
def edit
#book = Book.find(params[:id])
end
form.html
form_for #book, :method => :put do |f|
def update
#book = Book.find(params[:id])
#book.update_attributes(params[:book])
end
this should do the job.
I had this issue before. Everything was right but still getting the error then I found out it was
gem 'rails-api'
Removed it and it all worked fine.
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.