Undefined method error when I add method to model in Rails - ruby-on-rails

I have the error
undefined method events_and_repeats' for #<Class:0x429c840>
app/controllers/events_controller.rb:11:in `index'
my app/models/event.rb is
class Event < ActiveRecord::Base
belongs_to :user
validates :title, :presence => true,
:length => { :minimum => 5 }
validates :shedule, :presence => true
require 'ice_cube'
include IceCube
def events_and_repeats(date)
#events = self.where(shedule:date.beginning_of_month..date.end_of_month)
return #events
end
end
app/controllers/events_controller.rb
def index
#date = params[:month] ? Date.parse(params[:month]) : Date.today
#repeats = Event.events_and_repeats(#date)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #events }
end
end
What is wrong?

Like Swards said, you called a instance method on a class. Rename it:
def self.events_and_repeats(date)
I am only writting this in an answer because it's too long for a comment,
checkout the ice-cube github page, it strictly says:
Include IceCube inside and at the top of your ActiveRecord model file to use the IceCube classes easily.
Also i think it you don't need the require in your model.

You can do it both ways:
class Event < ActiveRecord::Base
...
class << self
def events_and_repeats(date)
where(shedule:date.beginning_of_month..date.end_of_month)
end
end
end
or
class Event < ActiveRecord::Base
...
def self.events_and_repeats(date)
where(shedule:date.beginning_of_month..date.end_of_month)
end
end

Just for more clarity:
class Foo
def self.bar
puts 'class method'
end
def baz
puts 'instance method'
end
end
Foo.bar # => "class method"
Foo.baz # => NoMethodError: undefined method ‘baz’ for Foo:Class
Foo.new.baz # => instance method
Foo.new.bar # => NoMethodError: undefined method ‘bar’ for #<Foo:0x1e820>
Class method and Instance method

Related

Ruby on Rails to_json function add parameter to methods for render in favorites or not?

How do I add parameters to methods for rendering the current place in favorites?
I tried this:
class Place < ActiveRecord::Base
has_and_belongs_to_many :users
def in_fav(user)
if user.places.include?Place.find(id)
return true
else
return false
end
end
end
class User < ActiveRecord::Base
has_and_belongs_to_many :places
end
class PlacesController < ApplicationController
places = Place.all
user = User.first
render json: {desc:true, status:1; data: places}.to_json(:methods => :in_fav(user))
end
I find same problem here
attr_accessor :current_user
def is_favorited_by_user?(user=nil)
user ||= current_user
end
#drops.current_user = current_user
render :json => #drops.to_json(:methods => :is_favorited_by_user?)
I don't understand current_user - it's assocciations? and how to use method current_user for collection #drops

Define Custom Object Lifecycle Hooks In Ruby

So I have a object and I want to define a lifecycle hook such as before_create, after_create, etc.
I want to call this after_retire and have it setup so I can do the following:
class User < ActiveRecord::Base
include Active
after_retire :method
def method
#do stuff
end
end
So far I have a module setup like so but I keep getting a method undefined after_retire error on my User model.
module Active
extend ActiveSupport::Concern
included do
define_callbacks :retire
set_callback :retire, :after, :after_retire
default_scope { where(:retired => false) }
scope :retired, where(:retired => true)
end
def retire!
run_callbacks :retire do
update_attribute :retired, true
update_attribute :retired_at, Time.now.to_datetime
end
end
end
How should I be setting this up?
The before/after_callback syntax is handled in ActiveModel::Callbacks through #define_model_callbacks. The raw ActiveSupport::Callbacks will require you to use #set_callback without any syntactic sugar:
module Active
extend ActiveSupport::Concern
included do
define_callbacks :retire
default_scope { where(:retired => false) }
scope :retired, where(:retired => true)
end
def retire!
run_callbacks :retire do
update_attribute :retired, true
update_attribute :retired_at, Time.now.to_datetime
end
end
end
class User < ActiveRecord::Base
include Active
set_callback :retire, :after, :method
def method
#do stuff
end
end
If you want to have the after/before syntax, since you are working with an ActiveRecord (and thus ActiveModel) class, you can use:
module Active
extend ActiveSupport::Concern
included do
define_model_callbacks :retire
default_scope { where(:retired => false) }
scope :retired, where(:retired => true)
end
def retire!
run_callbacks :retire do
update_attribute :retired, true
update_attribute :retired_at, Time.now.to_datetime
end
end
end
class User < ActiveRecord::Base
include Active
after_retire :method
def method
#do stuff
end
end

Rails setting macros in module

I am trying to setup belongs_to, validates, and default scopes in a module.
module MultiTenancy
class TenantNotSetError < StandardError ; end
def self.included(model)
class << model
belongs_to :tenant
validates :tenant_id, presence: true
default_scope -> {
raise TenantNotSetError.new unless Tenant.current_tenant
where(tenant_id: Tenant.current_tenant.id)
}
def multi_tenanted?
true
end
end
end
end
I keep getting a
NoMethodError: undefined method `belongs_to' for #<Class:User>
error.
What am I doing wrong?
This should work:
def self.included(base)
base.class_eval do
# your code goes here
end
end
The reason it doesn't work is you try to call belongs_to on metaclass of User, not on User.

undefined method `include?' for nil:NilClass with partial validation of wizard gem

I am trying to follow the guide for partial validation on object using the wizard gem, but I keep getting the error undefined method `include?' for nil:NilClass, cant understand what is wrong, have tried to follow the step by step instructions.
The error in the log shows.
NoMethodError - undefined method `include?' for nil:NilClass:
app/models/property.rb:22:in `active_or_tenants?'
Here is my steps controller.
class Properties::BuildController < ApplicationController
include Wicked::Wizard
steps :tenant, :confirmed
def show
#property = Property.find(params[:property_id])
#tenants = #property.tenants.new(params[:tenant_id])
render_wizard
end
def update
#property = Property.find(params[:property_id])
params[:property][:status] = step.to_s
params[:property][:status] = 'active' if step == steps.last
#property.update_attributes(params[:property])
render_wizard #property
end
def create
#property = current_user.properties.build(params[:property])
logger.info #property.attributes
if #property.save
flash[:success] = "Tenant Added"
redirect_to wizard_path(steps.second, :property_id => #property.id)
else
render 'edit'
end
end
end
Property.rb
class Property < ActiveRecord::Base
attr_accessible :name, :address_attributes, :tenants_attributes, :property_id, :status
belongs_to :user
has_one :address, :as => :addressable
accepts_nested_attributes_for :address, :allow_destroy => true
has_many :tenants
accepts_nested_attributes_for :tenants, :allow_destroy => true
validates :name, :presence => true
validates :address, :presence => true
validates :tenants, :presence => true, :if => :active_or_tenants?
def active?
status == 'active'
end
def active_or_tenants?
status.include?('tenants') || active?
end
end
Let me know if you need any other parts added to the question. Thanks in advance.
From my comments:
The status is an attribute of your Property model. It can be nil which raises an error in certain cases:
undefined method include?' for nil:NilClass
It is actually trying to compare nil to 'tenants' (String).
To fix that, you can use an empty string to be compared if status is nil,
# an example (you can try in your IRB console):
nil || "No value"
# => returns "No value"
in your case:
def active_or_tenants?
status.to_s.include?('tenants') || active?
end
nil.to_s return an empty string. Which solves your problem ;)
Actually, the methods to_s, to_i, to_f etc. are often used to remove the possible nil:
# in ruby console:
2.3.3 :018 > nil.to_i
# => 0
2.3.3 :019 > nil.to_f
# => 0.0
2.3.3 :020 > nil.to_s
# => ""
2.3.3 :021 > nil.to_a
# => []
In Ruby 2.3 you can use the safe navigation operator, which will simply return nil when your object is nil and it won't throw an error.
def active_or_tenants?
status&.include?('tenants') || active?
end
There is another solution to this, you might want to set a default state upon object creation, preferable in the migration.
class AddStatusToProperties < ActiveRecord::Migration
def change
create_table :projects do |t|
t.string :status, default: 'new'
end
end
end
Following this you'll never have nil for your state

undefined method `model_name' for ActiveModel::Errors:Class

I have the following mongoid model class:
class Exercise
include Mongoid::Document
field :name, :type => String
field :description, :type => String
belongs_to :group
validates_presence_of :name, :description, :group
end
And I have the following controller:
class ExercisesController < ApplicationController
respond_to :json
def create
#exercise = Exercise.create(params[:exercise])
if #exercise.save
respond_with #exercise
else
respond_with(#exercise.errors, :status => :unprocessable_entity)
end
end
end
The model saves fine when valid but when the following line is ran:
respond_with(#exercise.errors, :status => :unprocessable_entity)
I get the following error
undefined method `model_name' for ActiveModel::Errors:Class
The errors collection is populated so I think my respond_with syntax is wrong.
The rails respond_with helper expects to receive a rails model objects as the 1st parameter. So in this case you'd just want respond_with #exercise, status: :unprocessable_entity And then in your response view you would need to properly format the error data, I'm assuming you are doing this via ajax and responding with json, etc. Hope that helps.

Resources