undefined method `each' for nil:NilClass - But why? - ruby-on-rails

I want to create a ruby app to check if a server status is up or down.
Later I will find a way to adapt my json path to find a way in the diverse syntax. But for now, I'm stuck with a dirty "undefined method `each' for nil:NilClass"
Ping controller:
def index
#pings = Ping.all
end
def new
#service = Ping.new
end
def create
#ping = Ping.new(ping_params)
#ping.service = #service
#ping.up = test_ping
#ping.save
end
def test_ping
require 'json'
require 'open-uri'
url = 'https://www.facebook.com/platform/api-status/'
fb_status_serialized = open(url).read
fb_status = JSON.parse(fb_status_serialized)
if fb_status['current']['health'] == 1
test_ping = true
else
test_ping = false
end
end
private
def ping_params
params.require(:ping).permit(:service_id, :up)
end
def set_ping
#ping = Ping.find(params[:ping_id])
end
end
Service controller:
(here are my setup for the services I want to add)
class ServiceController < ApplicationController
before_action :set_service, only: [:edit, :show, :destroy]
def index
#services = Service.all
end
def new
#service = Service.new
end
def edit
end
def show
end
def create
#service = Service.new(service_params)
#service.save
if #service.save
redirect_to service_path(#service)
else
render :new
end
end
def destroy
#service.destroy
#service.destroy
redirect_to services_path
end
private
def set_service
#service = Service.find(params[:id])
end
def service_params
params.require(:service).permit(:name, :web_api, :json_path)
end
end
View (service index):
<%= #services.each do | s | %>
<p><%= s.name %></p>
<p><%= s.web_api %></p>
<p><%= s.json_path %></p>
<p><%= s.id %></p>
<%= #pings.each do | p | %>
<%# if p.service_id == s.id %>
<!-- undefined -->
<% end %>
<p>|||</p> <%= Ping.new(up: true, service: s ) %> <p>|||</p>
<% end %>

You're trying to iterate over #pings that are inside the #services iteration, but this hasn't been defined, you've defined only services, and the iteration in pings won't work if the object in which each is being applied has a nil value.
Whatever is the controller you're using to render the view, you need to define both instance variables, try with:
def index
#services = Service.all
#pings = Ping.all
end

Related

Rails Unable To Access an Object In the Controller using Roo to import Excel/CSV and PGSQL DB

I'm using a words_import class/controller to allow me to validate my words as I import them from a csv file or excel spreadsheet. Unfortunately I'm receiving an error:
undefined method 'fetch_value' for nil:NilClass
When I attempt to load the words_import#new page. Please help if you can!
importer/app/controllers/word_imports_controller.rb
class WordImportsController < ApplicationController
def new
#word_import = WordImport.new
end
def create
#word_import = WordImport.new(params[:word_import])
if #word_import.save
redirect_to root_url, notice: "Imported words successfully."
else
render :new
end
end
end
importer/app/models/word_import.rb
class WordImport < ApplicationRecord
attr_accessor :file
def initialize(attributes = {})
attributes.each { |name, value| send("#{name}=", value) }
end
def persisted?
false
end
def save
if imported_words.map(&:valid?).all?
imported_words.each(&:save!)
true
else
imported_words.each_with_index do |word, index|
word.errors.full_messages.each do |message|
errors.add :base, "Row #{index+2}: #{message}"
end
end
false
end
end
def imported_words
#imported_words ||= load_imported_words
end
def load_imported_words
spreadsheet = Roo::Spreadsheet.open(file.path)
header = spreadsheet.row(1)
(2..spreadsheet.last_row).each do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
word = Word.find_by(abbreviation: row["abbreviation"]) || Word.new
word.attributes = row.to_hash
word
end
end
end
importer/app/views/product_imports/new.html.erb
<div class="container-fluid">
<div class="jumbotron">
<h1>Import Words</h1>
<p>A CSV or Excel file can be used to import records. The first row should be the column name. The following columns are allowed.</p>
<ul>
<% Word.columns.each do |column| %>
<% if column.name.in? ["id", "name", "released_on", "price"] %>
<li>
<strong><%= column.name %></strong>
<%= column.type.to_s.titleize %> type
</li>
<% end %>
<% end %>
</ul>
<%= form_for #word_import do |f| %>
<% if #word_import.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#word_import.errors.count, "error") %> prohibited this import from completing:</h2>
<ul>
<% #word_import.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.file_field :file %>
</div>
<div class="buttons"><%= f.submit "Import" %></div>
<% end %>
</div>
</div>
importer/config/routes.rb
Rails.application.routes.draw do
root 'words#home'
resources :words, except: [:show] do
collection do
post :import
end
end
get 'results' => 'words#results'
resources :session, only: [:create, :new, :destroy]
resources :word_imports, only: [:create, :new]
end
importer/app/controllers/words_controller
class WordsController < ApplicationController
include ApplicationHelper
before_action :authorize, except: [:index, :home, :results]
def index
#words = Word.order(:abbreviation)
respond_to do |format|
format.html
format.csv { send_data #words.to_csv }
format.xls
end
render :index
end
def create
#word = Word.new(abbreviation: params[:word][:abbreviation], full_word: params[:word][:full_word], definition: params[:word][:definition])
if #word.save
redirect_to results_path
else
#errors = #word.errors.full_messages
render :new
end
end
def new
#word = Word.new(params[:word])
render :new
end
def edit
#word = Word.find(params[:id])
render :edit
end
def update
#word = Word.find(params[:id])
#word.update(abbreviation: params[:word][:abbreviation], full_word: params[:word][:full_word], definition: params[:word][:definition])
if #word.save
redirect_to root_path
else
#errors = #word.errors.full_messages
render :edit
end
end
def destroy
#word = Word.find(params[:id])
#word.destroy
redirect_to root_path
end
def home
render :home
end
def results
#words = Word.search(params[:term])
render :results
end
def import
Word.import(params[:file])
redirect_to root_url, notice: 'Words successfully added.'
end
private
def word_params
params.require(:word).permit(:abbreviation, :full_word, :definition, :term)
end
end
importer/app/models/word
require 'csv'
class Word < ApplicationRecord
include ApplicationHelper
validates :abbreviation, presence: true, length: {maximum: 5}
validates :full_word, presence: true, uniqueness: true
validates :definition, presence: true
def self.search(term)
if term
where('abbreviation iLIKE ?', "%#{term}%").order('full_word DESC')
else
all
end
end
def self.to_csv(options = {})
desired_columns = ["abbreviation", "full_word", "definition"]
CSV.generate(options) do |csv|
csv << desired_columns
all.each do |word|
csv << word.attributes.values_at(*desired_columns)
end
end
end
def self.import(file)
spreadsheet = Roo::Spreadsheet.open(file.path)
header = spreadsheet.row(1)
(2..spreadsheet.last_row).each do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
word = find_by(id: row["id"]) || new
word.attributes = row.to_hash
word.save!
end
end
end
require 'roo' in the file containing your class

undefined method `fetch_value' for nil:NilClass

I'm using a words_import class/controller to allow me to validate my words as I import them from a csv file or excel spreadsheet. Unfortunately I'm receiving an error:
undefined method 'fetch_value' for nil:NilClass
When I attempt to load the words_import#new page. Please help if you can!
importer/app/controllers/word_imports_controller.rb
class WordImportsController < ApplicationController
def new
#word_import = WordImport.new
end
def create
#word_import = WordImport.new(params[:word_import])
if #word_import.save
redirect_to root_url, notice: "Imported words successfully."
else
render :new
end
end
end
importer/app/models/word_import.rb
class WordImport < ApplicationRecord
attr_accessor :file
def initialize(attributes = {})
attributes.each { |name, value| send("#{name}=", value) }
end
def persisted?
false
end
def save
if imported_words.map(&:valid?).all?
imported_words.each(&:save!)
true
else
imported_words.each_with_index do |word, index|
word.errors.full_messages.each do |message|
errors.add :base, "Row #{index+2}: #{message}"
end
end
false
end
end
def imported_words
#imported_words ||= load_imported_words
end
def load_imported_words
spreadsheet = Roo::Spreadsheet.open(file.path)
header = spreadsheet.row(1)
(2..spreadsheet.last_row).each do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
word = Word.find_by(abbreviation: row["abbreviation"]) || Word.new
word.attributes = row.to_hash
word
end
end
end
importer/app/views/product_imports/new.html.erb
<div class="container-fluid">
<div class="jumbotron">
<h1>Import Words</h1>
<p>A CSV or Excel file can be used to import records. The first row should be the column name. The following columns are allowed.</p>
<ul>
<% Word.columns.each do |column| %>
<% if column.name.in? ["id", "name", "released_on", "price"] %>
<li>
<strong><%= column.name %></strong>
<%= column.type.to_s.titleize %> type
</li>
<% end %>
<% end %>
</ul>
<%= form_for #word_import do |f| %>
<% if #word_import.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#word_import.errors.count, "error") %> prohibited this import from completing:</h2>
<ul>
<% #word_import.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.file_field :file %>
</div>
<div class="buttons"><%= f.submit "Import" %></div>
<% end %>
</div>
</div>
importer/config/routes.rb
Rails.application.routes.draw do
root 'words#home'
resources :words, except: [:show] do
collection do
post :import
end
end
get 'results' => 'words#results'
resources :session, only: [:create, :new, :destroy]
resources :word_imports, only: [:create, :new]
end
importer/app/controllers/words_controller
class WordsController < ApplicationController
include ApplicationHelper
before_action :authorize, except: [:index, :home, :results]
def index
#words = Word.order(:abbreviation)
respond_to do |format|
format.html
format.csv { send_data #words.to_csv }
format.xls
end
render :index
end
def create
#word = Word.new(abbreviation: params[:word][:abbreviation], full_word: params[:word][:full_word], definition: params[:word][:definition])
if #word.save
redirect_to results_path
else
#errors = #word.errors.full_messages
render :new
end
end
def new
#word = Word.new(params[:word])
render :new
end
def edit
#word = Word.find(params[:id])
render :edit
end
def update
#word = Word.find(params[:id])
#word.update(abbreviation: params[:word][:abbreviation], full_word: params[:word][:full_word], definition: params[:word][:definition])
if #word.save
redirect_to root_path
else
#errors = #word.errors.full_messages
render :edit
end
end
def destroy
#word = Word.find(params[:id])
#word.destroy
redirect_to root_path
end
def home
render :home
end
def results
#words = Word.search(params[:term])
render :results
end
def import
Word.import(params[:file])
redirect_to root_url, notice: 'Words successfully added.'
end
private
def word_params
params.require(:word).permit(:abbreviation, :full_word, :definition, :term)
end
end
importer/app/models/word
require 'csv'
class Word < ApplicationRecord
include ApplicationHelper
validates :abbreviation, presence: true, length: {maximum: 5}
validates :full_word, presence: true, uniqueness: true
validates :definition, presence: true
def self.search(term)
if term
where('abbreviation iLIKE ?', "%#{term}%").order('full_word DESC')
else
all
end
end
def self.to_csv(options = {})
desired_columns = ["abbreviation", "full_word", "definition"]
CSV.generate(options) do |csv|
csv << desired_columns
all.each do |word|
csv << word.attributes.values_at(*desired_columns)
end
end
end
def self.import(file)
spreadsheet = Roo::Spreadsheet.open(file.path)
header = spreadsheet.row(1)
(2..spreadsheet.last_row).each do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
word = find_by(id: row["id"]) || new
word.attributes = row.to_hash
word.save!
end
end
end
GitHub Repo:
https://github.com/bburnett86/cpf_dictionary

Rails Form to update Attribute from a different controller

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.

No route matches {:action=>"index", :controller=>"features", :grounddetail_id=>nil} missing required keys: [:grounddetail_id]

I wanna fetch feature index page without going through grounddetail id. When i try to create a link in homepage i always get this error:
No route matches {:action=>"index", :controller=>"features", :grounddetail_id=>nil} missing required keys: [:grounddetail_id]
<%= link_to "Account Setting", edit_admin_registration_path %> |
<%= link_to "Log Out", destroy_admin_session_path, method: :delete %> |
<%= link_to "Featured Ground", grounddetail_features_path(#grounddetail) %> # Feature Link Where I get error
grounddetail controller looks :
class GrounddetailsController < ApplicationController
before_action :find_ground, only: [:show, :edit, :destroy, :update]
def index
#grounddetails = Grounddetail.all.order('created_at DESC')
#grounddetail = Grounddetail.first # With this code it run but with grounddetail id.
end
def new
#grounddetail = Grounddetail.new
end
def edit
end
def show
end
def create
#grounddetail = Grounddetail.new(ground_params)
if #grounddetail.save
redirect_to #grounddetail
else
render 'new'
end
end
def update
if #grounddetail.update(ground_params)
redirect_to #grounddetail
else
render 'edit'
end
end
def destroy
#grounddetail.destroy
redirect_to root_path
end
private
def find_ground
#grounddetail = Grounddetail.find(params[:id])
end
def ground_params
params.require(:grounddetail).permit(:name, :working_hours, :end_time, :address, :contact_no, :email, :number_of_grounds, :description, :featured_ground)
end
end
feature controller looks like :
class FeaturesController < ApplicationController
before_action :set_ground
def index
#grounddetails = Grounddetail.where(featured_ground: true).order("created_at DESC")
#features = Feature.includes(:grounddetail).where(grounddetail_id: #grounddetail.id)
end
def new
#feature = Feature.new
end
def show
#feature = Feature.find(params[:id])
end
def edit
#feature = Feature.find(params[:id])
end
def create
#feature = Feature.create(feature_params)
#feature.grounddetail_id = #grounddetail.id
if #feature.save
redirect_to grounddetail_features_path(#grounddetail)
else
render 'new'
end
end
def update
#feature = Feature.find(params[:id])
if #feature.update(feature_params)
redirect_to grounddetail_features_path(#grounddetail)
else
render 'edit'
end
end
def destroy
#feature = Feature.find(params[:id])
#feature.destroy
redirect_to grounddetail_features_path(#grounddetail)
end
private
def set_ground
#grounddetail = Grounddetail.find(params[:grounddetail_id])
end
def feature_params
params.require(:feature).permit(:featuring_start_time, :featuring_end_at)
end
end
Models:
grounddetail model:
has_many :features
feature model:
belongs_to :grounddetail
index.html.erb #feature index page
<h2>Featured Ground</h2>
<% #grounddetails.each do |grounddetail| %>
Name: <%= link_to grounddetail.name, grounddetail %><br>
Address: <%= grounddetail.address %><br>
Opening Hours: From<%= grounddetail.working_hours.strftime("%l:%M %P") %> To <%= grounddetail.end_time.strftime("%l:%M %P") %><br>
Featured : <%= check_box "Grounddetail", "Featured Ground", {checked: grounddetail.featured_ground, disabled: true} %><br>
<% if (grounddetail.featured_ground = true) && (grounddetail_id = #grounddetail.id) %>
<% #features.each do |feature| %>
Featuring Start Time : <%= feature.featuring_start_time.strftime('%e %b %Y %l:%M %P') %><br>
<%# feature.start_date_cannot_be_in_the_past %>
Featuring End At : <%= feature.featuring_end_at.strftime('%e %b %Y %l:%M %P') %><br>
<% end %>
<% end %>
<%= link_to "Add Featuring Time", new_grounddetail_feature_path(#grounddetail) %><br><br>
<% end %>
routes.rb
resources :grounddetails do
resources :features
end
Sorry for the mess up..

ActionController::ParameterMissing param is missing or the value is empty

I can't solve this problem.
When I try to use "Chatroom#new" method, I I got this error, ActionController::ParameterMissing param is missing or the value is empty .
below codes are the ChatroomController.
class ChatroomsController < ApplicationController
before_action :find_room_owner,only:[:index]
before_action :objects_for_index,only:[:index]
def index
#/users/:user_id/cart/items/chatroom
sign_in #user if signed_in?
if #seller && #buyer
flash[:success] = "U are owners of the chatroom"
#messages = Message.all #Messageのmodelを作成
else
flash[:error] = "U cant enter the chatroom."
redirect_to user_cart_items_url(#user,#cart,#items) ##user,#cart,#itemsをgetしろ
end
end
def new
#user = User.find(params[:user_id])
#cart = Cart.find(params[:user_id])
#item = Item.find(params[:item_id])
#message = Message.new(message_params)
end
def create
#user = User.find(params[:user_id])
#message = #user.messages.build
if #message.save
#message.update_attributes(user_id:#user.id)
redirect_to user_cart_chatroom_path(#user,#cart,#items)
else
flash[:error] = "could not create any message."
render 'new'
end
end
private
def message_params
params.require(:messages).permit(:id,:user_id,:messages)
#params{:message => :id,:user_id,:messages}
end
#before_aciton
def find_room_owner
#item = Item.find(params[:item_id])
#buyer = User.find(params[:user_id])
#seller = Product.find_by(user_id:#item.user_id)
end
def objects_for_index
#user = User.find(params[:user_id])
#items = Item.all
end
end
Below codes are the view of Message#new.
<h1>Chatroom#new</h1>
<p>Find me in app/views/chatroom/new.html.erb</p>
<%= form_for #message,url:new_user_cart_item_chatroom_path(#user,#cart,#item) do |f| %>
<%= f.label :messages %>
<%= f.text_field :messages %>
<%= f.submit "new message", class:"btn btn-default" %>
<% end %>
Below codes are the migration of Message.
class CreateMessages < ActiveRecord::Migration
def change
create_table :messages do |t|
t.integer :user_id
t.string :messages
t.timestamps
end
end
end
Below codes are the model of message.
class Message < ActiveRecord::Base
validates :messages,presence:true,length:{maximum:200}
belongs_to :user
end
Below codes are the routes.
KaguShop::Application.routes.draw do
resources :users,only:[:show,:new,:create,:edit,:update,:destroy] do
collection do
get 'get_images',as:'get_images'
end
resources :products,only:[:show,:index,:new,:create,:edit,:update,:destroy] do
collection do
post 'add_item', as:'add_item'
get 'get_image',as:'get_image'
get 'get_images',as:'get_images'
end
end
end
resources :users,only:[:show,:new,:create,:edit,:update,:destroy] do
resource :cart,except:[:new,:show,:edit,:destroy,:update,:create] do
collection do
post 'purchase', as:'purchase'
#get 'show' , as: 'show'
post 'create' , as: 'create'
#多分routeにas的な感じでtemplateを提供するのが一番いい気がする
delete 'destroy',as:'destroy'
delete 'remove_item',as:'remove_item'
end
resources :items,only:[:show,:index] do
collection do
get 'get_images',as:'get_images'
end
resources :chatrooms,only:[:index,:create,:new] do
end
end
end
end
resources :sessions,only:[:new,:create,:destroy]
root 'products#index'
match '/signup', to:'users#new',via:'get'
match '/signin', to:'sessions#new', via:'get'
match '/signout', to:'sessions#destroy', via:'delete'
match '/contact', to:'nomal_pages#contact', via:'get'
end
You should call Message.new without params because message_params nil in this request and this raise ActionController::ParameterMissing:
class ChatroomsController < ApplicationController
#.........
def new
#user = User.find(params[:user_id])
#cart = Cart.find(params[:user_id])
#item = Item.find(params[:item_id])
#message = Message.new
end
#........
private
def message_params
params.require(:messages).permit(:id,:user_id,:messages)
end
#.......
end

Resources