Rails/RoR - NoMethodError (undefined method `destroy' for nil:NilClass) - ruby-on-rails

I have a TranslationsUser table and a FavoriteTranslation table. I want a TranslationsUser to only have one favorite translation, however I do not want to use validations because I want my controller to replace a favorite translation if one already exists. Instead, I created a validate_uniqueness function.
When I try to replace a TranslationsUser with a new favorite translation, I get the following error in my terminal:
NoMethodError (undefined method `destroy' for nil:NilClass):
I think the problem may be the before action :set_favorite_translation since it defines #favorite_translation
If so, how can I delete a specific FavoriteTranslation record: transUser.favorite_translations.first
If not, please help me figure out what the issue is! Many thanks.
before_action :set_favorite_translation, only: [:show, :edit, :update, :destroy]
def create
transUser = TranslationsUser.find(favorite_translation_params[:translations_user_id])
#favorite_translation = FavoriteTranslation.new(favorite_translation_params)
#favorite_translation.user_id = #current_user.id
if validate_uniqueness(transUser) == false
transUser.favorite_translations.first.destroy
end
respond_to do |format|
if #favorite_translation.save
#format.html { redirect_to #favorite_translation, notice: 'Translations users comment was successfully created.' }
format.json { head :no_content }
else
format.html { render :new }
format.json { render json: #favorite_translation.errors, status: :unprocessable_entity }
end
end
end
def validate_uniqueness(transUser)
if FavoriteTranslation.joins(:translations_user).where('lang_id = ?', transUser.lang_id).where('favorite_translations.user_id = ?', #current_user.id).where('translations_users.translation_id = ?', transUser.translation_id).exists?
return false
else
return true
end
end
def destroy
#favorite_translation.destroy
respond_to do |format|
format.html { redirect_to favorite_translations_url, notice: 'Translation was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_favorite_translation
#favorite_translation = FavoriteTranslation.find(params[:id])
end

I guess you are almost there. Just add the following inside the destroy method.
def destroy
if #favorite_translation
#favorite_translation.destroy
end
respond_to do |format|
format.html { redirect_to favorite_translations_url, notice: 'Translation was successfully destroyed.' }
format.json { head :no_content }
end
end
This basically checks if the favorite_translation is present, else the translationUser don't have a favorite_translation and so will allow the new record to be created.

If you don't want validations, no worries, writing proper associations will help you and DRY up your code as well.
Firstly, use has_one :favorite_translation and belongs_to :translations_user associations, then in you create action..
def create
transUser = TranslationsUser.find(favorite_translation_params[:translations_user_id])
#favTrans = transUser.favorite_translation || transUser.build_favorite_translation
#favTrans.assign_attributes(favorite_translation_params)
respond_to do |format|
if #favTrans.save
format.html { redirect_to #favTrans, notice: 'Translations users comment was successfully created.' }
format.json { head :no_content }
else
format.html { render :new }
format.json { render json: #favTrans.errors, status: :unprocessable_entity }
end
end
end
Now you don't need to destroy records and use has_many relations, create and update are kinda merged here.

I tried the given solutions, but I found that the following worked. Thanks for all the help!!!!
def create
transUser = TranslationsUser.find(favorite_translation_params[:translations_user_id])
if validate_uniqueness(transUser) == true
#favorite_translation = FavoriteTranslation.new(favorite_translation_params)
#favorite_translation.user_id = #current_user.id
else
update
end
respond_to do |format|
if #favorite_translation.save
format.json { head :no_content }
else
format.html { render :new }
format.json { render json: #favTrans.errors, status: :unprocessable_entity }
end
end
end
def update
transUser = TranslationsUser.find(favorite_translation_params[:translations_user_id])
#favorite_translation = FavoriteTranslation.joins(:translations_user).where('lang_id = ?', transUser.lang_id).where('favorite_translations.user_id = ?', #current_user.id).where('translations_users.translation_id = ?', transUser.translation_id).first
#favorite_translation.translations_user_id = favorite_translation_params[:translations_user_id]
#favorite_translation.save
respond_to do |format|
if #favorite_translation.update(favorite_translation_params)
'Translations users comment was successfully updated.' }
format.json { head :no_content }
else
format.html { render :edit }
format.json { render json: #favorite_translation.errors, status: :unprocessable_entity }
end
end
end

I removed this line
config.action_view.javascript_expansions[:defaults] = %w(jquery.min jquery_ujs)
from application.rb to resolve the issue.

Related

Rails, update the product right after create one

I have the web app on RoR, but the issue is once the user upload the image, the product_id is not associated with the product_attachments. Not until I proceed to next form.
Following were my controller
ProductAttachmentsController:
class ProductAttachmentsController < ApplicationController
before_action :set_product_attachment, only: [:show, :edit, :update, :destroy]
def index
#product_attachments = ProductAttachment.all
end
def show
end
def new
#product_attachment = ProductAttachment.new
end
def create
#product_attachment = ProductAttachment.new(product_attachment_params)
respond_to do |format|
if #product_attachment.save
format.html { redirect_to #product_attachment, notice: 'Product attachment was successfully created.' }
format.json {render :json => #product_attachment}
else
format.html { render :new }
format.json { render json: #product_attachment.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #product_attachment.update(product_attachment_params)
format.html { redirect_to #product_attachment.product, notice: 'Product attachment was successfully updated.' }
format.json { render :show, status: :ok, location: #product_attachment }
else
format.html { render :edit }
format.json { render json: #product_attachment.errors, status: :unprocessable_entity }
end
end
end
def destroy
#product_attachment.destroy
respond_to do |format|
format.html { redirect_to product_attachments_url, notice: 'Product attachment was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product_attachment
#product_attachment = ProductAttachment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_attachment_params
params.require(:product_attachment).permit(:product_id, :attachment)
end
end
How can I trick the create method, so it will create a product_id when I create product_attachment? Currently I need to proceed next step and it trigger update method to insert product_id in product_attachments table. Thanks!!
You can store the product attachment id in a session variable
if #product_attachment.save
session[:product_attachment] = #product_attachment.id ### HERE!
format.html { redirect_to #product_attachment, notice: 'Product attachment was successfully created.' }
format.json {render :json => #product_attachment}
else
format.html { render :new }
format.json { render json: #product_attachment.errors, status: :unprocessable_entity }
end
When you create the product (in the ProductsController ) recall the attachment and update the product_id
if #product.save
if session[:product_attachment]
ProductAttachment.find(session[:product_attachment]).update_attribute(:product_id, #product.id)
session[:product_attachment] = nil
end
...
end

Fetching JSON Data from Facebook Graph URL in Rails

i have a ruby on rails 3.2.13 app, and i want to fetch data from my facebook page and show it one of my views...
What steps should i follow to do this?
What has to go in my controller and model and also in my view?
Please Help! ive been investigating on how to do this for like a week now, and i cannot find a good tutorial on how to get this done.
I have made a Data scaffold with the stuff i want to read from facebook.
This is my controller
class DatosController < ApplicationController
# GET /datos
# GET /datos.json
def index
#datos = JSON.parse("http://graph.facebook.com/iscopeapp")
respond_to do |format|
format.html # index.html.erb
format.json { render json: #datos }
end
end
# GET /datos/1
# GET /datos/1.json
def show
#dato = Dato.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #dato }
end
end
# GET /datos/new
# GET /datos/new.json
def new
#dato = Dato.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #dato }
end
end
# GET /datos/1/edit
def edit
#dato = Dato.find(params[:id])
end
# POST /datos
# POST /datos.json
def create
#dato = Dato.new(params[:dato])
respond_to do |format|
if #dato.save
format.html { redirect_to #dato, notice: 'Dato was successfully created.' }
format.json { render json: #dato, status: :created, location: #dato }
else
format.html { render action: "new" }
format.json { render json: #dato.errors, status: :unprocessable_entity }
end
end
end
# PUT /datos/1
# PUT /datos/1.json
def update
#dato = Dato.find(params[:id])
respond_to do |format|
if #dato.update_attributes(params[:dato])
format.html { redirect_to #dato, notice: 'Dato was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #dato.errors, status: :unprocessable_entity }
end
end
end
# DELETE /datos/1
# DELETE /datos/1.json
def destroy
#dato = Dato.find(params[:id])
#dato.destroy
respond_to do |format|
format.html { redirect_to datos_url }
format.json { head :no_content }
end
end
end
This is my Model
class Dato < ActiveRecord::Base
attr_accessible :likes, :name, :talking_about_count
end
this is the facebook json link i want to parse and show some fields of it in my view.
When i access the index of this controller im getting an error : "Unexpected Token at:http://graph.facebook.com/iscopeapp"
http://graph.facebook.com/iscopeapp
Please help!
Thank you in advance!
You could use Koala:
Koala is a Facebook library for Ruby, supporting the Graph API (including the batch requests and photo uploads), the REST API, realtime updates, test users, and OAuth validation

How to remove respond_to block from scaffold_controller template

how to customize scaffold generator #was following this link
class IdeasController < ApplicationController
before_action :set_idea, only: [:show, :edit, :update, :destroy]
# GET /ideas
# GET /ideas.json
def index
#ideas = Idea.all
end
# GET /ideas/1
# GET /ideas/1.json
def show
end
# GET /ideas/new
def new
#idea = Idea.new
end
# GET /ideas/1/edit
def edit
end
# POST /ideas
# POST /ideas.json
def create
#idea = Idea.new(idea_params)
respond_to do |format|
if #idea.save
format.html { redirect_to #idea, notice: 'Idea was successfully created.' }
format.json { render action: 'show', status: :created, location: #idea }
else
format.html { render action: 'new' }
format.json { render json: #idea.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /ideas/1
# PATCH/PUT /ideas/1.json
def update
respond_to do |format|
if #idea.update(idea_params)
format.html { redirect_to #idea, notice: 'Idea was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #idea.errors, status: :unprocessable_entity }
end
end
end
# DELETE /ideas/1
# DELETE /ideas/1.json
def destroy
#idea.destroy
respond_to do |format|
format.html { redirect_to ideas_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_idea
#idea = Idea.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def idea_params
params.require(:idea).permit(:name, :description, :picture)
end
end
How to remove all the respond_to code ?
Use respond_with to make your controllers cleaner. This apidoc and
this screencast will answer all your related questions.
Your controller methods will be as clean as this:
def update
#idea.update(idea_params)
respond_with #idea, notice: 'Idea was successfully updated.'
end
To apply that to default scaffold controller template, just copy the template content from github and put it into RAILS_ROOT/lib/templates/rails/scaffold_controller/controller.rb. Then apply the respond_with approach there.
Just do so like this.
For e.g.
respond_to do |format|
if #idea.save
format.html { redirect_to #idea, notice: 'Idea was successfully created.' }
format.json { render action: 'show', status: :created, location: #idea }
else
format.html { render action: 'new' }
format.json { render json: #idea.errors, status: :unprocessable_entity }
end
end
can be replaced with
if #idea.save
redirect_to #idea, notice: 'Idea was successfully created.'
else
render 'new
end

Undefined constant Rails 4

by copying and trying to modify a scaffold manually in Rails 4, I got an error when I want to delete an article: uninitialized constant Article::Tag.
Another error when I want to edit an Article: "undefined local variable or method `article_params'".
I don't know from where it can comes from, the highlited error which are displayed are #article.destroy and if #article.update(article_params). I don't understand at all considering I think having copied perfectely the scaffold...
def destroy
#article.destroy
respond_to do |format|
format.html { redirect_to articles_url }
format.json { head :no_content }
end
end
def update
respond_to do |format|
if #article.update(article_params)
format.html { redirect_to #article, notice: 'Article was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
Thansk you for your help

Rails before_filter doesn't hit database

In my application, I want to only allow user with admin privilege to access this model. So I set up and before_filter to check if the user is an Admin. The problem with this approach is that, after the admin user passes the filter, s/he won't be able to get redirect to the action. Instead, only the views are rendered, which leads to the undefined method each' for nil:NilClass error. What am I doing wrong here?
class TidbitsController < ApplicationController
before_filter :is_admin?
layout "tidbits"
# GET /tidbits
# GET /tidbits.json
protected
def is_admin?
unless current_user.admin?
flash[:error] = "You are not authorized!"
redirect_to "/" and return
end
end
def index
#tidbits = Tidbit.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #tidbits }
end
end
# GET /tidbits/1
# GET /tidbits/1.json
def show
#tidbit = Tidbit.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #tidbit }
end
end
# GET /tidbits/new
# GET /tidbits/new.json
def new
#tidbit = Tidbit.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #tidbit }
end
end
# GET /tidbits/1/edit
def edit
#tidbit = Tidbit.find(params[:id])
end
# POST /tidbits
# POST /tidbits.json
def create
#tidbit = Tidbit.new(params[:tidbit])
respond_to do |format|
if #tidbit.save
format.html { redirect_to #tidbit, notice: 'Tidbit was successfully created.' }
format.json { render json: #tidbit, status: :created, location: #tidbit }
else
format.html { render action: "new" }
format.json { render json: #tidbit.errors, status: :unprocessable_entity }
end
end
end
# PUT /tidbits/1
# PUT /tidbits/1.json
def update
#tidbit = Tidbit.find(params[:id])
respond_to do |format|
if #tidbit.update_attributes(params[:tidbit])
format.html { redirect_to #tidbit, notice: 'Tidbit was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #tidbit.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tidbits/1
# DELETE /tidbits/1.json
def destroy
#tidbit = Tidbit.find(params[:id])
#tidbit.destroy
respond_to do |format|
format.html { redirect_to tidbits_url }
format.json { head :no_content }
end
end
end
in your example all your action methods are protected so maybe that's the problem?
I think you forgot to add the devise required callback filter
before_filter :authenticate_user!
before_filter :is_admin?

Resources