As i'm trying to show a specific data from has_many relation on a iteration
Why Rails shows undefined method for Null:String and how do I fix it?
NoMethodError (undefined method `rated' for "shop_date is not
null":String)
# controller Cast
def cast
#products = Product.all
#rating = Product.joins(:shops).where(:shops => ('shop_date is not null').rated.average(:b_rating) || 0 )
end
# Model Shop
belongs_to :product
attr_accessible :b_rating,:product_id
scope :by_participant, -> { where('shop_date is not null').order('shop_date desc') }
scope :rated, -> { where('b_rating is not null') }
def self.average_rating
by_participant.rated.average(:b_rating) || 0
end
# Model Product
Has_many :shops
I suppose, simplest way is to user group by query:
# controller
#products = Product.all
products_ids = #products.collect(&:id)
#ratings =
Shop.where(product_id: products_ids).
where('shop_date is not null').rated.
group(:product_id).
average(:b_rating)
# view
<% #products.each do |product| %>
Rating: <%= #ratings[product.id] || 0 %>
<% end %>
Related
I am trying to pass stored_products from shopify into a Rails app but keep getting a home controller error at https://f588240c.ngrok.io/ i have made updates, with no luck and restarted the server a number of times with no luck.
Any help would be welcomed. Heres the code
class Api::V1::HomeController < ShopifyApp::AuthenticatedController
def index
#products = ShopifyAPI::Product.find(:all, params: { limit: 10 })
#products.each do |product|
StoredProduct.where(shopify_id: product.id)
.first_or_create do |stored_product|
stored_product.shopify_id = product.id
stored_product.shopify_title = product.title
stored_product.shopify_handle = product.handle
stored_product.shopify_image_url = product.image.src
stored_product.shop_id = #shop.id
stored_product.save
product.images.each do |image|
ProductImage.where(shopify_id: image.id)
.first_or_create do |product_image|
product_image.image_url = image.src
product_image.stored_product_id = stored_product_id
product_image.shopify_id = image.id
end
end
end
end
#stored_products = StoredProduct.belongs_to_shop(#shop.id)
end
end
From the authenticated controller
private
def set_shop
#shop = Shop.find_by(id: session[:shopify])
set_locale
end
from the store_products.rb file
class StoredProduct < ApplicationRecord
belongs_to :shop
has_many :product_images
scope :belongs_to_shop, -> shop_id { where(shop_id: shop_id) }
end
For this specific issue/code tutorial, the private set_shop method should be set like follows:
def set_shop
#shop = Shop.find_by(id: session[:shop_id])
set_locale
end
The other answer has params instead of session
The problem is that #shop is nil. The error message says it cannot call the method .id on NilClass.
In the image I can see that you have a shop_id in the params so you might just need to change your code here:
def set_shop
#shop = Shop.find_by(id: params[:shop_id])
set_locale
end
But that depends on your code, so please double check.
wrong number of arguments (given 2, expected 1)
SportsController
class SportsController < ApplicationController
def index
#sport = Sport.all
#events, #errors = Bapi::Inplay.all(query)
end
private
def query
params[:query, {}]
end
end
Sport index.html.erb
<% #sports.each do |sport| %>
<% #events(:sport_id => sport.id).each_slice(2) do |events| %>
I want send each sport.id to #enevts instance variable
Edited :
When send query as hash in SportsController its work!!
class SportsController < ApplicationController
def index
#sport = Sport.all
query = {:sport_id => 1}
#events, #errors = Bapi::Inplay.all(query)
end
private
def query
params[:query, {}]
end
end
Index.html.erb
<% #sports.each do |sport| %>
<% #events.each_slice(2) do |events| %>
params is a hash and method :[] can accept only 1 argument.
def query
params[:query] || {} # Will return :query part or empty Hash if it has nothing
end
I get this error and for the life of me I can't figure out why. Help would be appreciated. :
error 3: error displayed after changes
error 4: after User.all.each do |user|
Error: Undefined method 'each' for nil: nilClass
my ruby/haml code is as follows
viewer code:
-# This file is app/views/projects/index.html.haml
%h1 All Project Tasks
= form_tag projects_path, :method => :get do
Include:
- #all_users.each do |user|
= user
= check_box_tag "users[#{user}]", 1, ("checked" if #filtered_users.find_index(user))
= submit_tag 'Refresh', :id => "users_submit"
%table#projects
%thead
%tr
%th{:class => ("hilite" if params[:sort] == "title")}= link_to "Title", {:controller => "projects", :sort => "title", :filter => #filtered_users.to_s}, :id => "title_header"
%th Task Details
%th Assigned Usertimot
%th{:class => ("hilite" if params[:sort] == "due_date")}= link_to "Due Date", {:controller => "projects", :sort => "due_date", :filter => #filtered_users.to_s}, :id => "due_date_header"
%tbody
- #projects.each do |project|
%tr
%td= project.title
%td= link_to "More about #{project.title}", project_path(project)
%td= project.user
%td= project.due_date.to_formatted_s(:long)
= link_to 'Add new project task', new_project_path
controller code:
class ProjectsController < ApplicationController
def show
id = params[:id] # retrieve project task ID from URI route
#project = Project.find(id) # look up project task by unique ID
# will render app/views/projects/show.<extension> by default
def index
#projects_users = Project.all_users
# remembered settings
if (params[:filter] == nil and params[:users] == nil and params[:sort] == nil and
(session[:filter] != nil or session[:users] != nil or session[:sort] != nil))
if (params[:filter] == nil and session[:filter] != nil)
params[:filter] = session[:filter]
end
if (params[:sort] == nil and session[:sort] != nil)
params[:sort] = session[:sort]
end
redirect_to projects_path(:filter => params[:filter], :sort => params[:sort], :users => params[:users])
else
if (params[:filter] != nil and params[:filter] != "[]")
#filtered_users = params[:filter].scan(/[\w-]+/)
session[:filter] = params[:filter]
else
#filtered_users = params[:users] ? params[:users].keys : []
session[:filter] = params[:users] ? params[:users].keys.to_s : nil
end
end
session[:sort] = params[:sort]
session[:users] = params[:users]
if (params[:sort] == "title")
if ( params[:users]or params[:filter] )
#projects = Project.find(:all, :order => "title")
end
end
if (params[:sort] == "due_date")
if ( params[:users]or params[:filter] )
#projects = Project.find(:all, :order => "due_date")
end
if (params[:sort] == nill)
if(params[:users] or params[:filter])
#projects = Project.all
end
end
end
end
def new
# default: render 'new' template
end
def create
#project = Project.create!(project_params)
flash[:notice] = "#{#project.title} was successfully created."
redirect_to projects_path
end
def edit
#project = Project.find params[:id]
end
def update
#project = Project.find params[:id]
#project.update_attributes!(project_params)
flash[:notice] = "#{#project.title} was successfully updated."
redirect_to project_path(#project)
end
def destroy
#project = Project.find(params[:id])
#project.destroy
flash[:notice] = "Project '#{#project.title}' deleted."
redirect_to projects_path
end
private
def project_params
params.require(:project).permit(:title, :description, :extended_description, :user, :due_date)
end
end
end
i understand that the spacing for haml may be a little off, just the nature of trying to format the code block thanks in advance!
viewer code:
class Project < ActiveRecord::Base
def self.all_users
allUsers = []
Project.all.each do |project|
if (allUsers.find_index(project.user) == nil)
allUsers.push(project.user)
end
end
return allUsers
end
end
You are probably getting the error on this line in your view:
#all_users.each do |user|
The reason for the error as I see it is that you don't have #all_users instantiated anywhere in your controller's index action method.
First switch #all_users to #projects_users. Also it appears that your all_users method in project.rb is overly complex and is returning nil. Try modifying project.rb to the following:
class Project < ActiveRecord::Base
def self.all_users
all.includes(:user).map(&:user).uniq
end
end
Undefined method 'each' for nil: nilClass
This error basically means you don't have any data in your variable.
In other languages, it would mean you've not delcared the variable. Because Ruby is object orientated, it will populate the variable with the nilClass class.
Many new Ruby devs are thrown by the "undefined method" exception message; it's the nilClass you have to look out for.
--
To explain the error properly, because Ruby is object orientated, every variable is actually a data object, represented by a class. In Rails, you can define these classes as models (User.find etc).
Unlike other languages, Ruby treats these objects as is -- it uses methods on them. Other languages fit data into functions, E.G PHP's each function:
#PHP
<$ each($people) $>
#Ruby
<% #people.each do |person| %>
Thus, the "no method" error basically means that Ruby cannot find the method you're calling on the nilClass. It throws developers because they think that "I have the x method on the User class", not realizing that the variable has been populated by the nilClass instead.
The short of it is that you have to either make your calls conditional, or populate the variable properly.
The error appears to be here:
#app/views/project/index.html.haml
#all_users.each do |user|
#app/controllers/projects_controller.rb
class ProjectsController < ApplicationController
def index
#projects_users = Project.all_users
end
end
You're not assigning #all_users at all
You're using an inefficient way to get "all users"
Here's what I'd do:
#app/controllers/projects_controller.rb
class ProjectsController < ApplicationController
def index
#users = Project.all_users
end
end
#app/models/project.rb
class Project < ActiveRecord::Base
scope :all_users, -> { joins(:users) } #-> this needs to be tested
end
#app/views/projects/index.haml
- #users.each do |user|
= user.name
I am pretty inexperienced with pure SQL, you'll be best referring to the joins documentation for a clearer perspective.
I have a controller action that is doing product listing, pagination and some filters, like category(from a dropdown), title(from a text-field), stock(from a checkbox)
This is my controller:
class ProductsController < ApplicationController
def index
#products = Product.where(active:1).where("title LIKE ?","%#{params[:title]}%")
if params[:stock]
#products=#products.where("stock = 0")
end
if params[:category]
#products=#products.where("category_id LIKE ?","#{params[:category]}")
end
#products= #products.paginate(:page => params[:page])
#categories= Category.all
end
And my model is:
class Product < ActiveRecord::Base
belongs_to :category
...some validations...
end
What could I change in order that my controller would become thinner? Thanks
Model
class Product < ActiveRecord:::Base
scope :active, where(active: 1)
def self.with_stock(stock=nil)
return where(stock: 0) if stock
self
end
def self.categorized(category=nil)
return self.where(category: category) if category
self
end
def self.titled(title=nil)
return self.where("title LIKE ?", 'title') if title
self
end
def self.list(params)
title = params[:title]
category = params[:category]
page = params[:page]
self.titled(title).with_stock(stock).categorized(category)
.paginate(page).active
end
end
Controller
def index
#products = Product.list(params)
end
Do not ship Category in controller. Do it in template/partial. ONE instance variable from controller only.
I propose the specific refactoring style:
controller
class ProductsController < ApplicationController
def index
#products = Product.titled params[:title]
#products = #products.in_stock if params[:stock]
#products = #products.category params[:category] if params[:category]
#products = #products.paginate :page => params[:page]
#categories = Category.all
end
end
model
class Product < ActiveRecord::Base
belongs_to :category
...
scope :titled, proc {| title | where(active:1).where("title LIKE ?","%#{title}%")
scope :in_stock, proc { where("stock = 0") }
scope :category, proc {| category | where("category_id LIKE ?","#{category}") }
end
If your intent is just to the controller become thinner, you could move the logic to the model.
ProductController.rb
#products = Product.some_method(params)
Product.rb
def self.some_method(params)
if params[:stock]
where("stock = 0 AND active = 1 AND title LIKE ?","%#{params[:title]}%")
end
if params[:category]
where("active = 1 AND category_id LIKE ? AND title LIKE ?", "#{params[:category]}", "%#{params[:title]}%")
end
Using thin controller, fat model principle.
controller:
class ProductsController < ApplicationController
def index
#products = Product.active(params).paginate(page: params[:page])
#categories = Category.all
end
end
model:
class Product < ActiveRecord::Base
belongs_to :category
def self.active(params)
products = where(active:1).where("title LIKE ?","%#{params[:title]}%")
if params[:stock]
products = products.where("stock = 0")
end
if params[:category]
products = products.where("category_id LIKE ?","#{params[:category]}")
end
end
end
My models are;
class region
has_many :cities
end
class event
belongs_to :city
end
class city
has_many :events
belongs_to :region
end
Eventcontroller
def index
#region = Region.find(params[:region_id])
#cities = #region.cities
#city = City.find(params[:city_id])
#events = #city.events
#events_by_date = #events.group_by(&:start_on)
end
Page:
region/x/cities/x/events
Shows all the events from the city.
Question: how can i show all events from all the cities on my /region/events page? I created a resources
resources :regions do
resources :events do
collection do
get 'all_events'
end
end
But how I define the "all_event" action in the eventcontroller?
I cannot do this in my eventcontroller #events = #cities.events because event belongs_to :city. Is there a solution for this?
I tried this:
controller:
#region = Region.find(1)
#events = Event.includes(:city)
#events_by_date = #events.group_by(&:published_on)
View:
%ul.property_list
- #events_by_date[date].each do |event|
%li.restaurant
%span.icon
%h5
= link_to event.title, polymorphic_path([#region, event.city.name, event])
error : undefined method `region_Assisi_event_path'
If I am understanding this correctly all you would need to do:
In your controller
def all_events
#events = Event.includes(:city)
end
Then in your view, use a block to access all the instances
#events.each do |event|
event.name
event.city.name #not sure if you have a name attribute