RoR - undefined method `draft?' for nil:NilClass - ruby-on-rails

Actually I am trying to use enum attribute in my rails 5 blog app.The problem is that when I try to toggle the status from draft to published or vice versa, I get the error stating "NoMethodError in BlogsController#toggle_status"
blogs_controller.rb
class BlogsController < InheritedResources::Base
def toggle_status
if #blog.draft?
#blog.published!
elsif #blog.published?
#blog.draft!
end
redirect_to blogs_url, notice: "Blog status has been updated"
end
private
def blog_params
params.require(:blog).permit(:title, :body)
end
end
index.html.slim
h1 Listing blogs
table
thead
tr
th Title
th Body
th
th
th
th
tbody
- #blogs.each do |blog|
tr
td = blog.title
td = blog.body
td = link_to blog.status,toggle_status_blog_path(blog)
td = link_to 'Show', blog
td = link_to 'Edit', edit_blog_path(blog)
td = link_to 'Destroy', blog, data: { confirm: 'Are you sure?' }, method: :delete
br
= link_to 'New Blog', new_blog_path
blog.rb
class Blog < ApplicationRecord
enum status: { draft: 0, published: 1 }
end
routes.rb
Rails.application.routes.draw do
resources :blogs do
member do
get :toggle_status
end
end
end
schema.rb
create_table "blogs", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "status", default: 0
end
I don't know where I may be going wrong, I tried at my best but unable to figure it out.
Any suggestions are most welcome.
Thank you in advance.

You'll need to set your #blog instance variable.
def toggle_status
#blog = Blog.find(params[:id])
...

Related

Getting all notes to display on the front-end

I built out a recipe book for my wife and her family and I seem to be having issues with getting the notes that people add to display, mainly when someone posts a note it replaces the previous note with the new one instead of displaying all of the notes. I tried adding a notes table and controller and all of that and it kept throwing errors and just wouldn't work. So I have tried to make a model method to just show all of the notes but it gives me an error in my update action. This is my first real project out of my Bootcamp so I am still fairly green at all of this but I want to show my controller and model with the method that I thought that would work. I don't know if I was going down the right track with the model and controller and just didn't quite get all of the syntax right or if the model method is the correct path.
Model:
class Recipe < ApplicationRecord
validates :name, presence: true
def ingredients_list
ingredients.split(", ")
end
def directions_list
directions.split(". ")
end
def recipe_notes
recipe_notes = notes.all
end
end
Controller:
class RecipesController < ApplicationController
def index
recipes = Recipe.all
render json: recipes
end
def show
recipe = Recipe.find_by(id: params[:id])
render json: recipe
end
def create
recipe = Recipe.new(
name: params["name"],
contributor: params["contributor"],
ingredients: params["ingredients"],
directions: params["directions"],
category: params["category"]
)
if recipe.save
render json: recipe
else
render json: {errors: recipe.errors.full_messages},
status: 422
end
end
def update
recipe_id = params["id"]
recipe = Recipe.find_by(id: recipe_id)
recipe.name = params["name"] || recipe.name
recipe.contributor = params["contributor"] || recipe.contributor
recipe.ingredients = params["ingredients"] || recipe.ingredients
recipe.directions = params["directions"] || recipe.directions
recipe.category = params["category"] || recipe.category
recipe.notes = params["notes"] || recipe.notes
if recipe.save
render json: recipe
else
render json: {errors: recipe.errors.full_messages},
status: 422
end
end
def destroy
recipe_id = params["id"]
recipe = Recipe.find_by(id: recipe_id)
recipe.destroy
render json: {message: "Recipe Deleted"}
end
end
This was my schema before I removed all of the notes stuff:
create_table "notes", force: :cascade do |t|
t.integer "recipe_id"
t.string "note"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "recipes", force: :cascade do |t|
t.string "name"
t.string "ingredients"
t.string "directions"
t.string "category"
t.string "contributor"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "notes"
end
This was the model before I tried to move to a model method:
class Recipe < ApplicationRecord
validates :name, presence: true
has_many :notes
def ingredients_list
ingredients.split(", ")
end
def directions_list
directions.split(". ")
end
end
class Note < ApplicationRecord
belongs_to :recipe
end
This was the controller that I set up for the notes before I removed it:
class NotesController < ApplicationController
def show
note = Note.find_by(id: params[:id])
render json: note
end
end
I also had the route set up for a show action too

Rails create does not save params from checkbox

I am creating a website where a user (interviewer) can create a position (a job opening).
Even if the params are sent, my create action does not save them except for the current_user.
This is what I send:
positions_controller.rb
def new
#position = Position.new
end
def create
#position = Position.new(position_params)
#position.interviewer = current_interviewer
if #position.save
redirect_to position_path(#position)
flash[:success] = "You created a new position/opening"
else
render :new
end
raise
end
private
def set_position
#position = Position.find(params[:id])
end
def position_params
params.require(:position).permit(:title, :skills, :interviewer)
end
end
_form.html.erb
<%= simple_form_for [#interviewer, #position] do |f| %>
<%= f.input :title, required:true %>
<%= f.input :skills, as: :check_boxes, collection:[
['Python', "python"],
['Java', "java"],
['JavaScript', "javascript"],
['Ruby', "ruby"],
['C++', "c++"],
['Node.js', "node"],
['React', "react"],
['Django', "django"],
['Rails', "rails"],
['SQL', "sql"],
['Doker', "doker"],
['AWS', "aws"],
['Vue.js', "vue"],
['Marketing', "Marketing"],
['HR', "hr"],
['Finance', "finance"],
['IT', "it"],
], input_html: { multiple: true } %>
<%= f.submit "Submit position", class: "btn btn-primary" %>
<% end %>
position.rb
class Position < ApplicationRecord
validates :title, presence: true
belongs_to :interviewer
end
schema
create_table "positions", force: :cascade do |t|
t.string "title"
t.bigint "interviewer_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "candidate_id"
t.string "candidatures", default: [], array: true
t.string "skills"
t.index ["candidate_id"], name: "index_positions_on_candidate_id"
t.index ["interviewer_id"], name: "index_positions_on_interviewer_id"
end
My alternative was to replace the create code with:
#position = current_interviewer.positions.new(position_params)
but it still does not work.
Since you have a input_html: { multiple: true } for the params skills, you need to add the following in positions_controller.rb:
def position_params
params.require(:position).permit(:title, :interviewer, :candidate, skills:[])
end
Basically, your skills will be saved as an array if you allow input_html: { multiple: true } for a collection
In addition, you are not passing any params for candidate
In your table, you have interviewer_id but in your permitted params you have interviewer.
Change your params to permit interviewer_id instead.
Also, in your form you have <%= f.input :title, required:true %> Presence is required by default (at least with simple_form). You don't need to declare it in the form, but you should still keep it in your Model.

Rails NameError in controller / undefined local variable

I am trying to add items to a cart. I keep getting
Undefined local variable or method document_id' for #<Cart:0x8fc0130>
Rails.root: C:/Users/cmendla/RubymineProjects/technical_library
app/models/cart.rb:22:inadd_item'
app/controllers/carts_controller.rb:7:in `add_to_cart' Request
Parameters:
{"_method"=>"post",
cart.rb
has_many :items
def add_item(product_id)
$test1 = 'add item 2'
item = items.where('document_id = ?', document_id).first
if item
increase the quantity of product in cart
item.quantity + 1
save
else
product does not exist in cart
product = Product.find(product_id)
items << product
document = Document.find(document_id)
items << document
cart.items << Item.new(document_id: document_id)
end
save
end
Application controller:
application_controller.rb
def current_cart
if session[:cart_id]
#current_cart ||= Cart.find(session[:cart_id])
end
if session[:cart_id].nil?
#current_cart = Cart.create!
session[:cart_id] = #current_cart.id
end
#current_cart
end
.
class Item < ActiveRecord::Base
belongs_to :cart
end
carts controller:
def add_to_cart
# #cart = current_cart
current_cart.add_item(params[:document_id])
redirect_to carts_path(current_cart.id)
# redirect to shopping cart or whereever
end
Routes.rb
post '/add_to_cart/:doc_id' => 'carts#add_to_cart', :as => 'add_to_cart'
Schema:
create_table "items", force: :cascade do |t|
t.integer "document_id"
t.string "user"
t.integer "cart_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "items", ["cart_id"], name: "index_items_on_cart_id"
create_table "carts", force: :cascade do |t|
t.string "user"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
I am calling the add action with the following link in my documents.index
<td><%= link_to "add", add_to_cart_path(document.id), :method => :post %></td>
item = items.where('document_id = ?', document_id).first
On that line document_id is not defined. should that actually be product_id?

Append a string to an array through strong parameters using << or Find_By_Sql in Rails

I am trying to append a string value to two array columns ("good_product" & "bad_product") of a Postgresql model ("product.rb") using strong parameters with user input from form_for text fields. I have found two ways (<< & find_by_sql) to achieve this goal but can't get either to work.
For example, "Product 3" submitted through form_for input should be added to {"Product 1", "Product 2", _______ } (if other products exist in the array) OR an empty array (if no product added yet).
Model: product.rb
class Product < ActiveRecord::Base
serialize :good_product, Array
serialize :bad_product, Array
end
Controller: products.controller.rb
def new
#product = Product.new
end
def create
#product = Product.new(product_params)
#product.good_product ||= []
#product.bad_product ||= []
#product.good_product << :good_product
#product.bad_product << :bad_product
redirect_to '/products'
end
private
def product_params
params.require(:product).permit(:good_product => [], :bad_product => [])
end
end
View: new.html.erb
<%= form_for #product, url: products_path do |f| %>
<%= f.label :good_product, "Good Product" %>
<%= f.text_field :good_product %>
<%= f.label :bad_product, "Bad Product" %>
<%= f.text_field :bad_product %>
<%= f.submit 'Submit' %>
<% end %>
Schema: schema.rb
create_table "products", force: :cascade do |t|
t.string "good_product", default: [], array: true
t.string "bad_product", default: [], array: true
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "products", ["user_id"], name: "index_products_on_user_id", using: :btree
Alternatively, instead of "<<", I tried this in the Controller:
def create
#product = Product.new(product_params)
Product.find_by_sql(["UPDATE products SET good_product = array_append(good_product, '?') WHERE user_id = ?", #product.good_product, current_user]);
Product.find_by_sql(["UPDATE products SET bad_product = array_append(bad_product, '?') WHERE user_id = ?", #product.bad_product, current_user]);
redirect_to '/products'
end
Thank you all for your help!

Rails slim form_for error "First argument in form cannot contain nil or be empty"

I'm trying to create many absents at once (for different students) and I'm pretty new to rails. I keep getting an error that "First argument in form cannot contain nil or be empty".
I'm also wondering whether I need a new method at all.
Here is my form
= form_for #absent, url: absent_path, method: :post do |f|
table.table
thead
tr
th Name
th Absent
tbody
- #students.each do |student|
tr
td = student.full_name
td = f.check_box :student_ids, student.id, #absent.students.include?(student), name: "absent[student_ids][]", id: "student_id_#{student.id}"
= f.submit 'Save'
Here is my controller
def new
#absent = Absent.new
end
def create
absent_params[:student_ids].each do |student_id|
#absent = Absent.new(student_id: student_id)
if #absent.save
redirect_to absent_path
else
render :index
end
end
end
private
def absent_params
params.require(:absent).permit(
:student_ids
)
end
Here is my schema:
create_table "absents", force: true do |t|
t.integer "student_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "absents", ["student_id"], name: "index_absents_on_student_id", using: :btree
create_table "students", force: true do |t|
t.string "full_name"
t.datetime "created_at"
t.datetime "updated_at"
end
Here are my models:
class Student < ActiveRecord::Base
has_many :absents, foreign_key: :student_id
end
class Absent < ActiveRecord::Base
belongs_to :student, foreign_key: :student_id
end

Resources