On my site users can both take and retake a quiz, meaning I will use the quiz code in a partial view that will be used both by the the edit and new views.
To render my partials I have in my new view:
<%= render partial: "quiz", locals: { url: quiz_bs_path } %>
and in my edit view:
<%= render partial: "quiz", locals: { url: edit_quiz_b_path } %>
The link_to locations are from my rake routes results:
quiz_bs GET /quiz_bs(.:format) quiz_bs#index
POST /quiz_bs(.:format) quiz_bs#create
new_quiz_b GET /quiz_bs/new(.:format) quiz_bs#new
edit_quiz_b GET /quiz_bs/:id/edit(.:format) quiz_bs#edit
quiz_b GET /quiz_bs/:id(.:format) quiz_bs#show
PATCH /quiz_bs/:id(.:format) quiz_bs#update
PUT /quiz_bs/:id(.:format) quiz_bs#update
DELETE /quiz_bs/:id(.:format) quiz_bs#destroy
I am getting an Argument Error in my edit view saying First argument in form cannot contain nil or be empty. The line on which the error is being called is in my partial:
<%= form_for #quiz_bs, url: url, method: :post do |f| %>
My controller code is:
class QuizBsController < ApplicationController
before_action :require_sign_in
def show
#quiz_bs = QuizBs.find(params[:id])
end
def new
#quiz_bs = current_user.quiz_bs || current_user.build_quiz_bs
end
def create
#quiz_bs = QuizBs.new
#quiz_bs.bs01 = params[:quiz_bs][:bs01]
#quiz_bs.bs02 = params[:quiz_bs][:bs02]
#quiz_bs.bs03 = params[:quiz_bs][:bs03]
#quiz_bs.bs04 = params[:quiz_bs][:bs04]
#quiz_bs.bs05 = params[:quiz_bs][:bs05]
#quiz_bs.bs06 = params[:quiz_bs][:bs06]
#quiz_bs.user = current_user
if #quiz_bs.save
flash[:notice] = "Quiz results saved successfully."
redirect_to user_path(current_user)
else
flash[:alert] = "Sorry, your quiz results failed to save."
redirect_to welcome_index_path
end
end
def update
#quiz_bs = QuizBs.find(params[:quiz_bs])
#quiz_bs.assign_attributes(quiz_bs_params)
if #quiz_bs.save
flash[:notice] = "Post was updated successfully."
redirect_to user_path(current_user)
else
flash.now[:alert] = "There was an error saving the post. Please try again."
redirect_to welcome_index_path
end
end
private
def quiz_bs_params
params.require(:quiz_bs).permit(:bs01, :bs02, :bs03, :bs04, :bs05, :bs06)
end
end
The model is:
class QuizBs < ActiveRecord::Base
before_save :set_bscode
def set_bscode
self.bscode = "#{self.bs01}#{self.bs02}#{self.bs03}-#{self.bs04}#{self.bs05}#{self.bs06}"
end
belongs_to :user
validates :user, presence: true
end
Any ideas where I am going wrong?
Keep it more simple, if you want to assign to current_user, create method will do for you.
Partial:
#new.html.erb
<%= render partial: "quiz", locals: {quiz: #quiz_bs, url: :quiz_bs } %>
#edit.html.erb
<%= render partial: "quiz", locals: {quiz: #quiz_bs, url: :quiz_b } %>
Form:
#_form.html.erb
<%= form_for quiz, url: url do |f| %>
Controller:
def new
#quiz_bs = QuisBs.new
end
You do not have edit action in controller, so rails assumes it being empty. Thus #quiz_bs is really nil
Add something like
def edit
#quiz_bs = QuizBs.find(params[:id])
end
also in your update action params[:quiz_bs] is most likely nil too and should be changed to params[:id]
It is not necessary to create RESTfull methods in controller but if you are using it as I can see #quiz_bs then you will have to initialize it first then you can use it, In your new view you initialize the #quiz_bs by
#quiz_bs = current_user.quiz_bs || current_user.build_quiz_bs
then you are using it.
and also routes which is generated for edit is needed an id i.e.
edit_quiz_b GET /quiz_bs/:id/edit(.:format) quiz_bs#edit
so you will have to pass #quiz_bs like
edit_quiz_b_path(#quiz_bs)
GOT it?
Some updates to your controller:
before_action :assign_quiz_bs, only: [:show, :edit, :update, :destroy]
#...
def update
#quiz_bs.update(quiz_bs_params)
# .... rendering ...
end
private
def assign_quiz_bs
#quiz_bs = Quiz.find(params[:id])
end
def quiz_bs_params
params.require(:quiz_bs).permit(:bs01, :bs02, :bs03, :bs04, :bs05, :bs06)
end
Related
I have an App with Demos and Ratings. The basic idea is that each user can rate demos, and they can update the ratings. However, I'm having a lot of errors with several things:
Updating the rating for the demo
Creating a form to update the rating
Demo Controller
def show
#demo = Demo.find(params[:id])
#user = User.find(#demo.user_id)
#topic = Subject.find(#demo.subject_id)
if repeat_reviewer?(current_user)
#rating = Rating.create(reviewer: current_user, reviewed: #demo)
else
#rating = Rating.where(reviewer: current_user, reviewed: #demo)
end
end
....
def repeat_reviewer?(user)
#demo = Demo.find(params[:id])
return false unless user == User.where(reviewed: #demo)
end
def update_average_rating
#value = 0
self.ratings.each do |r|
#rating += #rating.value
end
#total = self.ratings.size
update_attributes(rating_average: #value.to_f / #total.to_f)
end
Ratings Controller
before_action :require_user, only: [:create, :update]
after_action :update_demo_rating
def create
#rating = Rating.create(rating_params)
if #rating.save
redirect_back_or
end
end
def update
#rating = Rating.where(reviewer: current_user)
if #rating.update_attributes(rating_params)
redirect_back_or
end
end
private
def rating_params
params.require(:rating).permit(:value, :reviewer_id, :reviewed_id)
end
def update_demo_rating
#rating = Rating.find(params[:id])
#demo = #rating.reviewed
#demo.update_average_rating
end
Demos Show View
<%= form_for #rating, url: ratings_path(#rating), method: :put do |f| %>
<%= options_for_select([[5,5],[3,3],[1,1]], 1) %>
<%= f.submit %>
I have errors with generating the form, with updating the correct attributes, and also find the rating associated with the demo and user.
I'm having trouble with editing an object from the admin panel on my app. (It's a political related app, hence the references to Liberal and Conservative, etc).
When I edit a category it creates a new category (with the same name) instead of updating it. I can't figure out why.
I can see from the log that when I edit the category Rails appears to go to the POST route (POST /admin/categories(.:format) admin/categories#create) instead of the PUT or PATCH route (PATCH /admin/categories/:id(.:format) admin/categories#update)
Apologies if I am using incorrect terminology, I'm not well versed in Rails.
categories_controller.rb:
class Admin::CategoriesController < Admin::DashboardController
before_action :find_category, only: [ :edit, :update, :destroy ]
def index
#categories = Category.all
end
def new
#category = Category.new
end
def create
#category = Category.new(category_params)
if #category.save
flash[:notice] = 'Category created'
redirect_to admin_categories_path
else
flash[:error] = 'Something was wrong'
render :new
end
end
def edit
end
def update
#category.update(category_params)
if #article.save
flash[:notice] = 'Category saved'
redirect_to admin_categories_path
else
flash[:error] = 'Something was wrong'
render :edit
end
end
def destroy
#category.destroy
redirect_to admin_categories_path
end
private
def find_category
#category = Category.find(params[:id])
end
def category_params
params.require(:category).permit(:name, :liberal_image, :conservative_image)
end
end
edit.html.slim inside the admin view (using slim):
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
= javascript_include_tag 'application', 'data-turbolinks-track' => true
.container
= link_to 'Manage Categories', admin_categories_path
h1 = "Edit Category - #{#category.name}"
= render partial: 'form', locals: { category: #category }
= simple_form_for #category, url: admin_category_path, method: 'delete' do |f|
= f.submit 'Delete category', class: 'btn btn-danger btn-lg'
I'm presuming it's something wrong in one of these files but let me know if there's something else I need to copy up there. Thanks !
_form.html.slim
= simple_form_for #category, url: admin_categories_path, method: 'post' do |f|
div.form-group.required
= f.input :name, label: 'Category Name'
div.form-group.required
= f.input :liberal_image, as: :file, label: 'Liberal Image'
div.target
div.form-group.required
= f.input :conservative_image, as: :file, label: 'Conservative Image'
div.target
div.form-actions
= f.submit 'Save', class: 'btn'
javascript:
$(document).ready(function() {
$('input[type="file"]').on('change', function(event) {
var files = event.target.files;
var image = files[0]
var reader = new FileReader();
reader.onload = function(file) {
var img = new Image();
img.src = file.target.result;
$(event.target).parent().parent().find('.target').html(img);
}
reader.readAsDataURL(image);
console.log(files);
});
});
We'd need to see your form partial to be clear, but from first glance, you have an issue with your update action:
def update
if #category.update(category_params)
redirect_to admin_categories_path, notice: "Category saved"
else
render :edit, error: "Something was wrong"
end
end
You had #article.update - I don't know why, because you haven't even set #article at all.
--
Update
It seems that your form is the cause of the issue:
= simple_form_for #category, url: admin_categories_path, method: 'post' do |f|
Here, you're sending each request to the create action.
You need to use the following:
= simple_form_for [:admin, #category] do |f|
As someone noticed, you are using #article variable that seems to be undeclared. This should cause an ApplicionError, so I think this maybe a simple bug, that your "edit" link actually leads to the "new" action. Does the name field actually contains a category name, or is it empty?
UPDATE: Actually, using #article will not cause an error. But check your links to be sure anyway.
I am making a form in my rails application where people have the option of adding images and I am using 'carrierwave' but I am getting an undefined method error on the edit page. Here is the code for the form:
<%= title "Add Item to #{#todo_list.title}" %>
<%= form_for [#todo_list, #todo_item], builder: FoundationFormBuilder do |form| %>
<%= render partial: 'form', locals: { form: form } %>
<%= form.file_field :picture %>
<% end %>
Here I can see the upload button and it is working fine but on the edit page I get the above stated error. Code for my edit page:
<%= title "Editing Todo Item" %>
<%= form_for [#todo_list, #todo_item], builder: FoundationFormBuilder do |form| %>
<%= render partial: 'form', locals: { form: form } %>
<% end %>
<div class="row">
<div class="small-12 columns">
<%= link_to "Delete", todo_list_todo_item_path(#todo_list, #todo_item), method: :delete, data: { confirm: "Are you sure?" }, class: "button radius expand alert" %>
</div>
<%= #todo_item.picture %>
</div>
Why is this showing an undefined method error. I tried creating a method in my todo_item model but its still showing the above error.
Controller for todo_item:
class TodoItemsController < ApplicationController
before_action :require_user
before_action :find_todo_list
before_action :set_back_link, except: [:index]
def index
go_back_link_to todo_lists_path
end
def new
#todo_item = #todo_list.todo_items.new
end
def create
#todo_item = #todo_list.todo_items.new(todo_item_params)
if #todo_item.save
flash[:success] = "Added todo list item."
redirect_to todo_list_todo_items_path
else
flash[:error] = "There was a problem adding that todo list item."
render action: :new
end
end
def edit
#todo_item = #todo_list.todo_items.find(params[:id])
end
def update
#todo_item = #todo_list.todo_items.find(params[:id])
if #todo_item.update_attributes(todo_item_params)
flash[:success] = "Saved todo list item."
redirect_to todo_list_todo_items_path
else
flash[:error] = "That todo item could not be saved."
render action: :edit
end
end
def destroy
#todo_item = #todo_list.todo_items.find(params[:id])
if #todo_item.destroy
flash[:success] = "Todo list item was deleted."
else
flash[:error] = "Todo list item could not be deleted."
end
redirect_to todo_list_todo_items_path
end
def complete
#todo_item = #todo_list.todo_items.find(params[:id])
#todo_item.toggle_completion!
redirect_to todo_list_todo_items_path, notice: "Todo item updated."
end
def url_options
{ todo_list_id: params[:todo_list_id] }.merge(super)
end
private
def set_back_link
go_back_link_to todo_list_todo_items_path(#todo_list)
end
def find_todo_list
#todo_list = current_user.todo_lists.find(params[:todo_list_id])
end
def todo_item_params
params[:todo_item].permit(:content)
end
end
To display your image you should change
<%= #todo_item.picture %>
to
<%= image_tag(#todo_item.picture_url) %>
I trying write params to Company model. But I have error undefined method `model_name' for NilClass:Class in this point = simple_form_for #company, url: update_settings_company_path do |f|. Where I must set #company?
Controller
def change_settings
#vacation_days = current_company.vacation_days
#illnes_days = current_company.illnes_days
end
def update_settings
if #company.update(company_params)
redirect_to account_company_path, notice: t('company.settings_changed')
else
render action: 'change_settings'
end
end
private
def company_params
params.require(:company).permit(:vacation_days, :illnes_days)
end
View
.company_settings
= simple_form_for #company, url: update_settings_company_path do |f|
= f.error_notification
= f.input :vacation_days
= f.input :illnes_days
%br
= f.submit t('common.save'), class: 'btn'
= link_to t('common.back'), account_company_path, class: 'btn'
routes
resource :company, only: :all do
get :change_settings
post :update_settings
patch :update_settings
end
What's wrong? Help me please
You don't set #company instance variable in both your actions. You can do it using before_filter, like this:
before_filter :find_company
def change_settings
#vacation_days = current_company.vacation_days
#illnes_days = current_company.illnes_days
end
def update_settings
if #company.update(company_params)
redirect_to account_company_path, notice: t('company.settings_changed')
else
render action: 'change_settings'
end
end
private
def company_params
params.require(:company).permit(:vacation_days, :illnes_days)
end
def find_company
#company = current_company
end
Try this instead, You need to set the instance variable before you use it. By default the instance variable is set to nil.
def update_settings
#company = current_company
if #company.update(company_params)
redirect_to account_company_path, notice: t('company.settings_changed')
else
render action: 'change_settings'
end
end
I have this setup in the routes.rb:
resources :users do
resources :images do
resources :comments
end
end
When I load the show action from the ImagesController, this is what is in the template file:
...
= render 'comments/form', :#comment => #image.comments.new
...
and in the comments/form file is following:
= form_for [#comment.commentable, #comment] do |f|
.field
= f.text_field :body
.actions
= f.submit 'Comment'
And the show action:
def show
#user = User.find(params[:user_id])
#image = #user.images.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #image }
end
end
But when I load this page in the browser, I get this error:
undefined method `image_comments_path' for #<#<Class:0x007feb48488128>:0x007feb48399668>
Why Rails returns this error message?
Open your terminal and type rake routes to see the right routes available in your app
In your show method,
def show
#user = User.find(params[:user_id])
#image = #user.images.find(params[:id])
## Add this line:
#comment = #image.comments.build
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #image }
end
end
In your template, if you are rendering a template,
= render "comments/form", :locals => { :comment => #comment } %>
In your comments/form write like this:
= form_for comment do |f|
.field
= f.text_field :body
.actions
= f.submit 'Comment'
It should work. Thanks