I keep getting a no method error. Why? How can I fix this?
NoMethodError in Articles#show
undefined method `photo' for #
I am using ruby on rails and I'm trying to use paperclip so i can upload photos on my app
part of my show file
<%= render #article.photos %> #source of error
<h3>Add a photo:</h3>
<%= render 'photos/form' %>
my photos controller
class PhotosController < ApplicationController
#Index action, photos gets listed in the order at which they were created
def index
#photos = Photo.order('created_at')
end
#New action for creating a new photo
def new
#photo = Photo.new
end
#Create action ensures that submitted photo gets created if it meets the requirements
def create
#article = Article.find(params[:article_id])
#photo = #article.photos.create(photo_params)
redirect_to article_path(#article)
end
def destroy
#article = Article.find(params[:article_id])
#photo = #article.photos.find(params[:id])
#photo.destroy
redirect_to article_path(#article)
end
private
#Permitted parameters when creating a photo. This is used for security reasons.
def photo_params
params.require(:photo).permit(:title, :image)
end
end
========= UPDATE =======
This is my
articles controller
class ArticlesController < ApplicationController
def new
#article = Article.new
end
def index
#articles = Article.all
end
def show
#article = Article.find(params[:id])
end
def create
#article = Article.new(article_params)
#article.save
redirect_to #article
end
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
end
private
def article_params
params.require(:article).permit(:title, :text)
end
article model
class Article < ApplicationRecord
has_many :comments
end
I fixed it now, but now i have another no method error
undefined method `article_photos_path' for #<#:0x007f17f052d0a0>
Did you mean? article_path
<%= form_for([#article, #article.photos.build]) do |f| %> #source of error
<div class="form-group">
<%= f.label :image %>
<%= f.file_field :image, class: 'form-control'%>
</div>
<p>
<%= f.submit 'Upload Photo' %>
</p>
<% end %>
</p>
<% end %>
Being Photo another model so, you need to make the proper relationship:
class Article < ApplicationRecord
has_many :comments
has_many :photos
end
class Photo < ApplicationRecord
belongs_to :article
end
As I see in your photo_params, you don't have the article_id attribute then you must add it, running a migration:
$ rails g migration add_article_to_photos article:references
$ rails db:migrate
After that you should update them:
params.require(:photo).permit(:title, :image, :article_id)
Related
I am building an app from an online tutorial. It tracks "Movies" and "Rentals." I am trying to set up the part where you create a new rental. When I submit the form, I get this error:
ActiveModel::ForbiddenAttributesError in RentalsController#create
Here is the full rentals controller:
class RentalsController < ApplicationController
def new
#movie = Movie.find(params[:id])
#rental = #movie.rentals.build
end
def create
#movie = Movie.find(params[:id])
#rental = #movie.rentals.build(params[:rental])
if #rental.save
redirect_to new_rental_path(:id => #movie.id)
end
end
end
It seems to take issue with this line in particular:
#rental = #movie.rentals.build(params[:rental])
Here is the Rental model:
class Rental < ApplicationRecord
has_one :movie
end
Here is the controller for Movies:
class MoviesController < ApplicationController
def new
#movie = Movie.new
#movies = Movie.all
end
def create
#movie = Movie.new(movie_params)
if #movie.save
redirect_to new_movie_path
end
end
private
def movie_params
params.require(:movie).permit(:title, :year)
end
end
Here is the Movie model:
class Movie < ApplicationRecord
has_many :rentals
end
Here are the routes:
Rails.application.routes.draw do
resources :movies, :rentals
root 'movies#new'
end
Here is the form:
<h1><%= #movie.title %></h1>
<%= form_for #rental, :url => {:action => :create, :id => #movie.id } do |r| %>
Borrowed on: <%= r.text_field :borrowed_on %><br />
Returned on: <%= r.text_field :returned_on %><br />
<br />
<%= r.button :submit %>
<% end %>
<br />
<%= link_to "back", new_movie_path %>
I'm not sure what is going on. From what I can tell, I am copying the tutorial exactly. Any help would be much appreciated!
You aren't using strong params for rentals, hence the ActiveModel::ForbiddenAttributesError error.
This should fix the error:
class RentalsController < ApplicationController
def new
#movie = Movie.find(params[:id])
#rental = #movie.rentals.build
end
def create
#movie = Movie.find(params[:id])
#rental = #movie.rentals.build(rental_params)
if #rental.save
redirect_to new_rental_path(:id => #movie.id)
end
end
private
def rental_params
params.require(:rental).permit(:borrowed_on, :rented_on)
end
end
I'm building my photography portfolio in Rails 4.1.6 and Ruby 2.0.0p576.
I have 'collections' which have many 'photos'.
I am using dragonfly 1.0.10 for image uploads.
Collections Model
class Collection < ActiveRecord::Base
belongs_to :admin
has_many :photos
end
Photos Model
class Photo < ActiveRecord::Base
belongs_to :collection
extend Dragonfly::Model
dragonfly_accessor :image
end
Collection Controller
class CollectionsController < ApplicationController
respond_to :html, :xml, :json
def index
#collections = Collection.all
end
def new
#collection = Collection.new
respond_with (#collection)
end
def create
#collection = Collection.new(collection_params)
#collection.save
respond_with (#collection)
end
def edit
#collection = Collection.find(params[:id])
end
def update
#collection = Collection.find(params[:id])
if #collection.update(collection_params)
redirect_to #collection
else
render 'edit'
end
end
def show
#collection = Collection.find(params[:id])
end
def destroy
#collection = Collection.find(params[:id])
#collection.destroy
respond_with (#collection)
end
private
def collection_params
params.require(:collection).permit(:name, :desc, photos: [:image] )
end
end
Photos Controller
class PhotosController < ApplicationController
def new
#collection = Collection.find(params[:id])
#photo = #collection.new
end
def create
#collection = Collection.find(params[:collection_id])
#photo = #collection.photos.create(photo_params)
redirect_to collection_path(#collection)
end
private
def photo_params
params.require(:photo).permit(:image)
end
end
This is storing my photos for me correctly.
But on my collection show page, I'm getting a "NoMethodError in Collections#show undefined method `image'.
In terminal, I get the following error:
ActionView::Template::Error (undefined method `image' for #):
Code for the show page is below:
collections/show.html.erb
<h1><%= #collection.name %></h1>
<p><%= #collection.desc %></p>
<% #collection.photos.each do |photo| %>
<div>
<%= image_tag #collection.photos.image.thumb('400x300#').url %>
</div>
<% end %>
I'm an absolute rails n00b and need some help as to how to fix this and be able to view all the photos of the collection on its show page.
Please help!
You have a wrong usage of the each loop:
<% #collection.photos.each do |photo| %>
<div>
<%= image_tag photo.image.thumb('400x300#').url %>
</div>
<% end %>
Read How does iteration work in Ruby?
I know there is a lot of similar posts where people have the same problem, but none of them helped me. If i create new article then it won't have a category. But if i edit article created earlier in seed.rb then the category is updated.
What's wrong?
Categories table:
class CreateCategories < ActiveRecord::Migration
def change
create_table :categories do |t|
t.string :name
t.timestamps
end
end
end
category.rb
class Category < ActiveRecord::Base
has_many :articles
end
article.rb
class Article < ActiveRecord::Base
belongs_to :category
end
and then i have a _form file
<%= form_for(#article) do |f| %>
<div class="title">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div class="content">
<%= f.label :content %>
<%= f.text_field :content %>
</div>
<div class="category">
<%= f.label :category %>
<%= collection_select(:article, :category_id, Category.all, :id, :name) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
There is a categories_controller file:
class CategoriesController < ApplicationController
def index
#categories = Category.all
end
def show
#category = Category.find(params[:id])
#articles = #category.articles
end
def new
#category = Category.new
end
def create
#category = Category.new(category_params)
if #category.save
redirect_to(:action => 'index')
else
render('new')
end
end
def edit
#category = Category.find(params[:id])
end
def update
#category = Category.find(params[:id])
if #category.update_attributes(category_params)
redirect_to(:action => 'show', :id => #category.id)
else
render('index')
end
end
def delete
#category = Category.find(params[:id])
end
def destroy
Category.find(params[:id]).destroy
redirect_to(:action => 'index')
end
private
def category_params
params.require(:category).permit(:name)
end
end
Articles controller file:
class ArticlesController < ApplicationController
def index
#articles = Article.all
end
def show
#article = Article.find(params[:id])
end
def new
#article = Article.new
end
def create
#article = Article.new(article_params)
if #article.save
redirect_to(:action => 'index')
else
render('new')
end
end
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
if #article.update_attributes(article_params)
redirect_to(:action => 'show', :id => #article.id)
else
render('index')
end
end
def delete
#article = Article.find(params[:id])
end
def destroy
Article.find(params[:id]).destroy
redirect_to(:action => 'index')
end
private
def article_params
params.require(:article).permit(:title, :content)
end
end
It looks like you're not building the association in the articles#create action. The category_id is being sent through your form, but you still need to to build the Active Record association. You could try something like this in the articles controller:
def create
#article = Article.new(article_params)
#category = Category.find(params[:category_id])
#article.category = #category
if #article.save
redirect_to(:action => 'index')
else
render('new')
end
end
Keep in mind, there are multiple ways to create an association. Your Article class has the following five methods to manipulate the association:
#article.category
#article.category=
#article.build_category
#article.create_category
#article.create_category!
I want to create a comments controller.But when rails render form, browser show an error 'First argument in form cannot contain nil or be empty', though the variable is defined.
there is comments_controller
class CommentsController < ApplicationController
def new
end
def create
#comment = current_user.comments.build(comment_params)
if #comment.save
redirect_to root_url
else
render 'static_pages/home'
end
end
private
def comment_params
params.require(:comment).permit(:text)
end
end
new.html.erb
<%= form_for(#comment) do |f| %>
<%= f.text_field :text %><br><br>
<% end %>
how fix?
sorry for my bad English
Fix :-
class CommentsController < ApplicationController
def new
#comment = Comment.new
end
# ....
end
I have three models: Client, Car, and ParkingRate. Client has many cars, and car has many parking_rates. I have a form on the client page that creates a car associated with that client. What I don't know how to do is to add a field for parking_rate to that form, so that when a car is created for that client, a parking rate is also created for that car.
My code looks like:
client.rb
class Client < ActiveRecord::Base
has_many :cars, dependent: destroy
end
car.rb
class Car < ActiveRecord::Base
belongs_to :client
has_many :parking_rates
end
parking_rate.rb
class ParkingRate < ActiveRecord::Base
belongs_to :car
end
On the client page (client/:id), I have a form to create a car associated with that client, like this:
views/clients/show.html.erb:
<h1>Client information</h1>
... client info ...
<%= render 'cars/form' %>
views/cars/_form.html.erb:
<%= form_for([#client, #client.cars.build]) do |f| %>
<p>
<%= f.label :vehicle_id_number %><br>
<%= f.text_field :vehicle_id_number %>
</p>
<p>
<%= f.label :enter_date %><br>
<%= f.text_field :enter_date %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
The Clients and Cars controllers look like this:
clients_controller.rb:
class ClientsController < ApplicationController
def new
#client = Client.new
end
def create
#client = Client.new(client_params)
if #client.save
redirect_to #client
else
render 'new'
end
end
def show
#client = Client.find(params[:id])
end
def index
#clients = Client.all
end
def edit
#client = Client.find(params[:id])
end
def update
#client = Client.find(params[:id])
if #client.update(client_params)
redirect_to #client
else
render 'edit'
end
end
def destroy
#client = Client.find(params[:id])
#client.destroy
redirect_to clients_path
end
private
def client_params
params.require(:client).permit(:first_name, :last_name)
end
end
cars_controller.rb:
class CarsController < ApplicationController
def create
#client = Client.find(params[:client_id])
#car = #client.cars.create(car_params)
#parking_rate = #car.parking_rates.create(rate_params)
redirect_to client_path(#client)
end
def show
#client = Client.find(params[:client_id])
#car = Car.find(params[:id])
end
def edit
#client = Client.find(params[:client_id])
#car = Car.find(params[:id])
end
def update
#client = Client.find(params[:client_id])
#car = Car.find(params[:id])
#car.update(car_params)
redirect_to client_path(#client)
end
def destroy
#client = Client.find(params[:client_id])
#car = #client.cars.find(params[:id])
#car.destroy
redirect_to client_path(#client)
end
private
def car_params
params.require(:car).permit(:vehicle_id_number, :enter_date, :rate)
end
def rate_params
params.require(:parking_rate).permit(:rate)
end
end
With this I am able to add cars to a given client, but I would also like to add a parking_rate to a car on the same form. So right when I create a car using this form, I want to create an associated parking rate. The form_for helper uses a [#client, #client.comments.build] as the model object, so I am not sure how to reference the parking_rate model in the same form. I think the solution is to use a fields_for helper, what would be the model reference for that, and what would I need to add to the cars and client controllers?
In client.rb, add the line
accepts_nested_attributes_for :cars