I am using Rails scaffold to create a simple model called Movies that contains the movie's name, director, synopsis and poster.
I am using the Carrierwave gem to upload the poster image. When I first boot up the rails server, I get the following message:
NameError in MoviesController#new
uninitialized constant Movie::PosterUploader
The extracted source the error screen displays is my models/movie.rb file:
class Movie < ApplicationRecord
mount_uploader :poster, PosterUploader
end
Here is my movies controller:
class MoviesController < ApplicationController
before_action :set_movie, only: [:show, :edit, :update, :destroy]
# GET /movies
# GET /movies.json
def index
#movies = Movie.all
end
# GET /movies/1
# GET /movies/1.json
def show
end
# GET /movies/new
def new
#movie = Movie.new
end
# GET /movies/1/edit
def edit
end
# POST /movies
# POST /movies.json
def create
#movie = Movie.new(movie_params)
respond_to do |format|
if #movie.save
format.html { redirect_to #movie, notice: 'Movie was successfully
created.' }
format.json { render :show, status: :created, location: #movie }
else
format.html { render :new }
format.json { render json: #movie.errors, status:
:unprocessable_entity }
end
end
end
# PATCH/PUT /movies/1
# PATCH/PUT /movies/1.json
def update
respond_to do |format|
if #movie.update(movie_params)
format.html { redirect_to #movie, notice: 'Movie was successfully
updated.' }
format.json { render :show, status: :ok, location: #movie }
else
format.html { render :edit }
format.json { render json: #movie.errors, status:
:unprocessable_entity }
end
end
end
# DELETE /movies/1
# DELETE /movies/1.json
def destroy
#movie.destroy
respond_to do |format|
format.html { redirect_to movies_url, notice: 'Movie was successfully
destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_movie
#movie = Movie.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white
list through.
def movie_params
params.require(:movie).permit(:title, :director, :synopsis, :poster)
end
end
When I created the model using Rails scaffold I made the poster a string, but changed that to file in this section of Movies form partial:
<div class="field">
<%= form.label :poster %>
<%= form.file_field :poster, id: :movie_poster %>
</div>
Here is my routes file just in case I have made an error there:
Rails.application.routes.draw do
resources :movies
root 'movies#index'
# For details on the DSL available within this file, see
http://guides.rubyonrails.org/routing.html
end
Any help would be greatly appreciated.
uninitialized constant Movie::PosterUploader
You should generate the uploader. Do
rails generate uploader Poster
which should generate the file
app/uploaders/poster_uploader.rb
Related
I'm trying to understand why my upload application in Ruby on Rails is returning this error unknown attribute 'file' for Document
I'm trying to build an upload app for csv documents only.
The app it is using an external Gem for doing the upload:
Gem
My controller where the error occurs:
class DocumentsController < ApplicationController
before_action :set_document, only: [:show, :edit, :update, :destroy]
# GET /documents
# GET /documents.json
def index
#documents = Document.all
end
# GET /documents/1
# GET /documents/1.json
def show
send_data(#document.file_contents,
type: #document.content_type,
filename: #document.filename)
end
# GET /documents/new
def new
#document = Document.new
end
# GET /documents/1/edit
def edit
end
# POST /documents
# POST /documents.json
def create
#document = Document.new(document_params)
respond_to do |format|
if #document.save
format.html { redirect_to documents_path, notice: 'Document was successfully created.' }
format.json { render :show, status: :created, location: #document }
else
format.html { render :new }
format.json { render json: #document.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /documents/1
# PATCH/PUT /documents/1.json
def update
respond_to do |format|
if #document.update(document_params)
format.html { redirect_to #document, notice: 'Document was successfully updated.' }
format.json { render :show, status: :ok, location: #document }
else
format.html { render :edit }
format.json { render json: #document.errors, status: :unprocessable_entity }
end
end
end
# DELETE /documents/1
# DELETE /documents/1.json
def destroy
#document.destroy
respond_to do |format|
format.html { redirect_to documents_url, notice: 'Document was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_document
#document = Document.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def document_params
params.require(:document).permit(:file)
end
end
The controller should hold the creat upload functionality and upload using as a reference the external Gem for make the file upload.
The model where I' calling some functionality from the Gem:
class Document < ActiveRecord::Base
include CsvUploaderWidget
validate :file_size_under_one_mb, :csv_file_format
before_save :upload_local
end
I am new to rails I created post model and posts_controller which has Name:string, EMail:string, Message:text, topic_id:integer columns using scaffold.
I also created a topic model and topics_controller which has Topic_Name:string in it.
I provided the relationship among the models as follows:
class Topic < ActiveRecord::Base
has_many :posts, foreign_key: 'topic_id'
end
class Post < ActiveRecord::Base
belongs_to :topic
end
In routes.db I created the nested resources as:
resources :topics do
resources :posts
end
topics_controller.rb code:
class TopicsController < ApplicationController
before_action :set_topic, only: [:show, :edit, :update, :destroy]
# GET /topics
# GET /topics.json
def index
#topics = Topic.all
end
# GET /topics/1
# GET /topics/1.json
def show
end
# GET /topics/new
def new
#topic = Topic.new
end
# GET /topics/1/edit
def edit
end
# POST /topics
# POST /topics.json
def create
#topic = Topic.new(topic_params)
respond_to do |format|
if #topic.save
format.html { redirect_to #topic, notice: 'Topic was successfully created.' }
format.json { render :show, status: :created, location: #topic }
else
format.html { render :new }
format.json { render json: #topic.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /topics/1
# PATCH/PUT /topics/1.json
def update
respond_to do |format|
if #topic.update(topic_params)
format.html { redirect_to #topic, notice: 'Topic was successfully updated.' }
format.json { render :show, status: :ok, location: #topic }
else
format.html { render :edit }
format.json { render json: #topic.errors, status: :unprocessable_entity }
end
end
end
# DELETE /topics/1
# DELETE /topics/1.json
def destroy
#topic.destroy
respond_to do |format|
format.html { redirect_to topics_url, notice: 'Topic was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_topic
#topic = Topic.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def topic_params
params.require(:topic).permit(:Name)
end
end
posts_controller code:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:Name, :Email, :Message, :topic_id)
end
end
I need to group posts using the topic. i.e., On clicking show on a particular topic it should go to the URL /topics/<topic_id>/posts where it should lists all posts related to that topic and I can create/delete posts belongs to that topic.
Can anyone help doing this..
Thank you..
Your question should be more direct, there's a lot of information that aren't related to the problem (the attributes names, for example), and your goal isn't clear enough.
It seems that you just want to setup the routes, right? You already have all posts related to that topic though the association: topic.posts. You just need to setup nested resource routes for posts:
resources :topics do
resources :posts
end
Also, you don't need the foreign_key option since you're using the naming conventions. It seems as well that you named some attributes in upper case, they should be name, email and message.
UPDATE:
In the index action, since you want posts belonging to one topic, you need to scope the #posts instance variable. Since you're using nested resources, you have the parameter params[:topic_id], so just fetch the topic with #topic = Topic.find(params[:topic_id]), then scope the association with #posts = #topic.posts. You'll need to do the same for every other action. I recommend that you read a little about associations in Rails, you'll probably need to use methods like #topic.posts.build and #topic.posts.find(params[:id]).
I found the solution for this problem in this link: Nested resources
Download the source code and find the solution...
I've been searching all over and can't find the answer to this anywhere.
I'm taking the intro to RoR course on udemy, and I've been able to solve all the problems I've had in the first 80% of the course, but now I'm at a roadblock and can't find this. We're building an app like Etsy, and I'm at the point where I need to restrict users from editing/deleting listings that don't belong to them.
I'm running Ruby 1.9.3 on Rails 3.2.21
I tried following the instructions for adding the check user filter, but when I checked back on local host, I received this error:
NoMethodError in ListingsController#edit
undefined method `user' for nil:NilClass
app/controllers/listings_controller.rb:98:in `check_user'
Parameters:
{"id"=>"8"}
My code matches the instructor's code exactly, but I think this error is because I'm using Rails 3, and he's using 4.
Here's my listings_controller.rb
class ListingsController < ApplicationController
# GET /listings
# GET /listings.json
before_filter :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]
before_filter :check_user, only: [:edit, :update, :destroy]
def index
#listings = Listing.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #listings }
end
end
# GET /listings/1
# GET /listings/1.json
def show
#listing = Listing.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #listing }
end
end
# GET /listings/new
# GET /listings/new.json
def new
#listing = Listing.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #listing }
end
end
# GET /listings/1/edit
def edit
#listing = Listing.find(params[:id])
end
# POST /listings
# POST /listings.json
def create
#listing = Listing.new(params[:listing])
#listing.user_id = current_user.id
respond_to do |format|
if #listing.save
format.html { redirect_to #listing, notice: 'Listing was successfully created.' }
format.json { render json: #listing, status: :created, location: #listing }
else
format.html { render action: "new" }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# PUT /listings/1
# PUT /listings/1.json
def update
#listing = Listing.find(params[:id])
respond_to do |format|
if #listing.update_attributes(params[:listing])
format.html { redirect_to #listing, notice: 'Listing was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# DELETE /listings/1
# DELETE /listings/1.json
def destroy
#listing = Listing.find(params[:id])
#listing.destroy
respond_to do |format|
format.html { redirect_to listings_url }
format.json { head :no_content }
end
end
private
def set_listing
#listing = Listing.find(params[:id])
end
def listing_params
params.require(:listing).permit(:name, :description, :price, :image)
end
def check_user
if current_user != #listing.user
redirect_to root_url, alert: "Sorry, this listing belongs to someone else."
end
end
end
The code that we had to add for this is the second before_filter and the def check_user
If any other information is needed to help answer this, please let me know.
It's not a Rails 3 vs 4 issue, your code never calls set_listing and so #listing is never being set. You should probably have a:
before_filter :set_listing, only: [:show, :edit, :update, :destroy]
at the top of your file, before the before_filter :check_user, ...
I would like users to be able to create/update my "Person" resource, including overwriting each other. Currently I'm able to capture the user who created the initial "Person" but i can't figure out how to capture and display the user that updated the resource.
For example if user 1 creates an item, then user 2 updates this item, I would like to display that this item was most recently edited by user 2.
Here's my controller, any help would be much appreciated thanks!
class PeopleController < ApplicationController
before_action :set_person, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
# GET /people
# GET /people.json
def index
#people = Person.all
end
# GET /people/1
# GET /people/1.json
def show
end
# GET /people/new
def new
#person = current_user.person.build
end
# GET /people/1/edit
def edit
end
# POST /people
# POST /people.json
def create
#person = current_user.person.build(person_params)
respond_to do |format|
if #person.save
format.html { redirect_to #person, notice: 'Person was successfully created.' }
format.json { render action: 'show', status: :created, location: #person }
else
format.html { render action: 'new' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /people/1
# PATCH/PUT /people/1.json
def update
respond_to do |format|
if #person.update(person_params)
format.html { redirect_to #person, notice: 'Person was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
# DELETE /people/1
# DELETE /people/1.json
def destroy
#person.destroy
respond_to do |format|
format.html { redirect_to people_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_person
#person = Person.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def person_params
params.require(:person).permit(:name, :twitter, :facebook, :instagram, :vine)
end
end
Simple way for doing it is to maintain the a column called updated_by and store the current user when its updated as #Andrey mentioned in previous comment.
But if your looking for a more extensive for tracking you can use auditable gem
You can check this out :
https://github.com/harley/auditable
Create updated_by column in posts table, and each time user updates the post, update the column updated_by by the value of current_user.
Disclaimer: I'm very new to Ruby on Rails.
Here is the error I am getting when attempting to generate a feed:
undefined method `title' for nil:NilClass
Extracted source (around line #2):
atom_feed do |feed|
feed.title "Who bought #{#product.title}"
feed.updated #latest_order.try(:updated_at)
Application trace:
app/views/products/who_bought.atom.builder:2:in `block in _app_views_products_who_bought_atom_builder__3166274680323093135_70240865825480'
app/views/products/who_bought.atom.builder:1:in `_app_views_products_who_bought_atom_builder__3166274680323093135_70240865825480'
This is my first time working with atom_feed - so I am really not sure what to look for here. What I have appears to be straight from the book "Agile Web Development with Rails 4" Am I missing something?
Should be:
CODING :
before_action :
set_product, only: [:show, :edit, :update, :destroy, :who_bought]
The problem was in a script I did not list - inside the products controller:
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.all
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
#product = Product.new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render action: 'show', status: :created, location: #product }
else
format.html { render action: 'new' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url }
format.json { head :no_content }
end
end
def who_bought
#product = Product.find(params[:id])
#latest_order = #product.orders.order(:updated_at).last
if stale?(#latest_order)
respond_to do |format|
format.atom
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:title, :description, :image_url, :price)
end
end
The who_bought method, was listed under the private methods and I had also forgotten the '#' symbol in #latest_order
Your #product variable is nil. Did you defined it? Does the particular product exist?
Try to output it into console: logger.info #product.inspect