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
Related
This is my controller
class SchoolsController < ApplicationController
def teacher
#teacher = Teacher.new
end
def form_create
#teacher = Teacher.new(teacher_params)
if teacher.save
redirect_to schools_teacher_path
else
flash[:notice] = "error"
end
end
private
def teacher_params
params.require(:teacher).permit(:name)
end
end
This is my views/schools/teacher.html.erb
<%= form_for :teacher do |f| %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
I am new to Ruby on Rails, and not sure how to proceed.
You should move this to a TeachersController let me show you how:
First you need to create the controller, you can get this done by typing this on the terminal at the project root directory:
$ rails g controller teachers new
Then into your route file (config/routes.rb):
resources :teachers, only: [:new, :create]
After that go to the teachers_controller.rb file and add the following:
class TeachersController < ApplicationController
def new
#teacher = Teacher.new
end
def reate
#teacher = Teacher.new(teacher_params)
if #teacher.save
redirect_to schools_teacher_path
else
redirect_to schools_teacher_path, notice: "error"
end
end
private
def teacher_params
params.require(:teacher).permit(:name)
end
end
Then you can have the form at views/teachers/new.html.erb:
<%= form_for :teacher do |f| %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
Please let me know how it goes!
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)
I am trying to render a form to upload a song.
I have a playlist model and a song model, song being a nested resource of playlist.
With simple form, when I try and render the new song partial, I get undefined method songs_path for #<#<Class:0x007fdc51980870>
In routes, the new song path is new_playlist_song but it doesn't seem that simple form knows this.
Songs controller:
class SongsController < ApplicationController
def new
#song = Song.new
end
def create
#song = Song.new(song_params)
if #song.save
flash[:info] = "Song uploaded sensually"
redirect_to user_path(current_user)
else
render 'new'
end
end
def index
#song = Song.all
end
private
def song_params
params.require(:song).permit(:audio)
end
end
Playlists controller:
class PlaylistsController < ApplicationController
before_action :find_playlist, only: [:edit, :update, :destroy]
def index
#playlists = Playlist.all
end
def new
if user_signed_in?
#playlist = current_user.playlists.new
else
redirect_to(root_url)
flash[:danger] = "You have to register to purchase gigs"
end
end
def create
#playlist = current_user.playlists.new
#playlist.user_id = current_user.id
if #playlist.save
redirect_to new_playlist_path
else
render 'new'
end
end
def destroy
#playlist = Playlist.find(params[:id])
if #playlist.present?
#playlist.destroy
redirect_to playlists_path
end
end
private
def find_playlist
#playlist = Playlist.find(params[:id])
end
end
Song model:
class Song < ActiveRecord::Base
belongs_to :playlist
has_attached_file :audio
validates_attachment_presence :audio
validates_attachment_content_type :audio, :content_type => [ 'audio/mp3','audio/mpeg']
end
Playlist model :
class Playlist < ActiveRecord::Base
belongs_to :user
has_many :songs
end
Routes:
resources :playlists do
resources :songs
end
User profile link to create new song:
<p> <%= #user.playlist.user_id %> </p>
<p> <%= #user.playlist.created_at %> </p>
<% if #user == current_user %>
<p> <%= link_to "Uploaad track", new_playlist_song_path(#user) %>
<% end %>
I have tried a few variants for the simple_form form.
New song partial 1:
<%= simple_form_for ([#playlist, #song]) do |f| %>
<%= f.file_field :audio %>
<%= f.button :submit %>
<% end %>
another try :
<%= simple_form_for ([#playlist, current_user.playlist.songs.build]) do |f| %>
I just can't get the form to show and I can't figure out why not. Any ideas would be appreciated, thanks.
As pointed out in the comments songs_path is not referenced in your code, and shouldn't even exist as it's a sub-resource of playlist.
If you want to list all the available routes just run a rake routes and make sure the code references an existing path.
I didn't define the playlist that the song belongs to.
Adding to the controller
def create
#song = current_user.playlist.songs.new song_params
#song.playlist_id = #playlist.id
if #song.save
and
def find_playlist
#playlist = Playlist.find(params[:id])
end
then to simple form
<%= simple_form_for ([#playlist, #playlist.songs.build]) do |f| %>
It works.
I am trying to set up a 5 star rating system so users can rate other users. At the moment everything is working, (create, delete, update etc...) but only the logged in user can rate himself. I cannot rate other users. I get no errors, it just redirects to the user profile page as it should but without added a rating to that user.
user.rb
class User < ActiveRecord::Base
has_many :reviews
review.rb
class Review < ActiveRecord::Base
belongs_to :user
end
reviews_controller.rb
class ReviewsController < ApplicationController
before_action :find_user
before_action :find_review, only: [:edit, :update, :destroy]
def new
#review = Review.new
end
def create
#review = Review.new(review_params)
#review.user_id = current_user.id
if #review.save
redirect_to user_path(#user)
else
render 'new'
end
end
def edit
end
def update
if #review.update(review_params)
redirect_to user_path(#user)
else
render 'edit'
end
end
def destroy
#review.destroy
redirect_to user_path(#user)
end
private
def review_params
params.require(:review).permit(:rating, :comment)
end
def find_user
#user = User.find(params[:user_id])
end
def find_review
#review = Review.find(params[:id])
end
end
_form which then gets rendered on show page:
<%= simple_form_for([#user, #user.reviews.build]) do |f| %>
<div id="rating-form">
<label>Rating</label>
</div>
<%= f.input :comment %>
<%= f.button :submit %>
<% end %>
<script>
$('#rating-form').raty({
path: '/assets/',
scoreName: 'review[rating]'
});
</script>
Any help getting this to work would be greatly appreciated!!
Do this:
#config/routes.rb
resources :users do
resources :reviews, only: [:new, :create]
end
#app/models/review.rb
class Review < ActiveRecord::Base
belongs_to :user
belongs_to :reviewed, class_name: "User", foreign_key: :reviewed_id
end
#app/controllers/reviews_controller.rb
class ReviewsController < ApplicationController
def new
#review = current_user.reviews.new
end
def create
#review = current_user.reviews.new review_params
#review.save
end
private
def review_params
params.require(:review).permit(:rating, :comment).merge(reviewed_id: params[:user_id])
end
end
#app/views/reviews/new.html.erb
<%= form_for #review do |f| %>
<%= f.number_field :rating %>
<%= f.text_field :comment %>
<%= f.submit %>
<% end %>
This would mean you'll have to include a reviewed_id column in your reviews table.
You'll be able to access it using: url.com/users/:user_id/reviews/new
The application will automatically fill the user_id and reviewed_id fields, so the rest of your code should work with the upgrade.
The big problem you have is that you're basically recording the user_id (presumably of who created the review)... but have no way of stipulating who the review is about.
The above code fixes that for you.
I am trying to create a new teacher for a specific school in my project and I got this error:
No route matches [POST] "/schools/3/teachers/new"
Here is my teachers_controller.rb:
class TeachersController < ApplicationController
def new
#teacher = Teacher.new
end
def create
#teacher = Teacher.new(teacher_params)
#teacher.save
redirect_to school_path(school)
end
private
def teacher_params
params.require(:teacher).permit(:firstName, :lastName, :middleName)
end
end
schools_controller.rb:
class SchoolsController < ApplicationController
def show
#school = School.find(params[:id])
end
def new
#school = School.new
end
def edit
#school = School.find(params[:id])
end
def update
#school = School.find(params[:id])
if #school.update(school_params)
redirect_to #school
else
render 'edit'
end
end
def index
#schools = School.all
end
def create
#school = School.new(school_params)
if #school.save
redirect_to schools_path
else
render 'new'
end
end
def destroy
#school = School.find(params[:id])
#school.destroy
redirect_to schools_path
end
private
def school_params
params.require(:school).permit(:name)
end
end
routes.rb:
Rails.application.routes.draw do
resources :schools do
resources :teachers
end
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
root 'welcome#index'
And teachers/new.html.erb:
<%= form_for :teacher, url: school_teachers_path(school) do |f| %>
<p>
<%= f.label :firstName %><br>
<%= f.text_field :firstName %>
</p>
<p>
<%= f.label :lastName %><br>
<%= f.text_field :lastName %>
</p>
<p>
<%= f.label :middleName %><br>
<%= f.text_field :middleName %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
As your teacher resource is nested under the school resource, so you need to pass the school when you try to create a teacher.
Try changing your new and create actions in teachers_controller.rb to something like this:
def new
#school = School.find(params[:school_id])
#teacher = #school.teachers.build
end
def create
#school = School.find(params[:school_id])
#teacher = #school.teachers.build(params[:teacher])
#teacher.save
redirect_to school_path(#school)
end
And, then change your form to this:
<%= form_for([#school, #teacher]) do %>
. . .
. . .
<% end %>
Try this in your form:
<%= form_for [school, Teacher.new] do |f| %>
The path you are posting to is for the index of teachers at a school:
school_teachers GET /schools/:school_id/teachers(.:format) teachers#index
I believe that it's a has_many belongs_to association. So you need to first change your teacher controller create action and new action.
class TeachersController < ApplicationController
def new
get_school
#teacher = #school.teachers.build
end
def create
get_school
#teacher = #school.teachers.build(teacher_params)
If #teacher.save
redirect_to school_path(school)
else
render 'new'
end
private
def teacher_params
params.require(:teacher).permit(:firstName, :lastName, :middleName)
end
def get_school
#school = School.find (params [:school_id])
end
end
Then in your form you 'll do :
<%= form_for([#school,#teacher]) do |f| %>
Hope this will help