While rendering xml for an object, I am getting the error
NoMethodError (undefined method `model_name' for OrderResponse:Class):
OrderResponse.rb
class OrderResponse
include ActiveModel::Serialization
attr_accessor :payload
end
In controller
def create
#order_response = OrderResponse.new
#order_response.payload = 12345
respond_to do |format|
format.xml { render :xml => #order_response }
end
end
I found other questions with similar titles while searching, according to that i modified 'respond_to' with 'respond_with' which inturns throws an error
undefinedMethod 'model_name' in OrderResponse
How to solve this?
I found an answer to this somewhere on stackoverflow and wish I could credit the source... This is my interpretation of it.
In Rails 3, if you have a resource listed in your routes which has a model .rb file but no active record table behind it, then you'll see this kind of error. This appeared for me as a form_for trying to reference a :controller and :action in this model. Perhaps it is related to Rails attempting to process associations for the model or something similar. Either way, this is new for me since I upgraded an application from Rails 2.3.8.
For me, the appears as:
undefined method `model_name' for SomeModel:Class
To fix it, at the top of the affected class add:
extend ActiveModel::Naming
include ActiveModel::Conversion
def persisted?
false
end
This has worked for me on two models like this.
You could try defining a class method by that name, which returns the name of the class:
def self.model_name; 'OrderResponse'; end
try including ActiveSupport::CoreExtensions::Module where model_name is defined ActiveSupport::CoreExtensions::Module
Related
I want to infer a decorator in a controller, so I generate a decorator the normal way (rails g decorator) and infer it in the controller. However, when I test with Postman, I get the error:
Could not infer a decorator for Employers::Job.
The error message shows that my syntax in the controller is incorrect (where .decorate is used), I don't know where I am going wrong.
I have tried changing the way of writing and specifying the decorator explicitly ( #job = Employers::JobDecorator.find(params[:id]).decorate), but again this gives a NoMethodError (undefined method `find' for Employers::JobDecorator:Class).
This is part of the controller:
def show
#job = #employer.jobs.find(params[:id])
render json: #job
end
end
This is the decorator at the beginning:
def attributes
#somethings
end
UPDATE 2
Thanks to the suggestion in the comments, things changed after I used Employers::JobDecorator.decorate(#job) in the controller, but I got a new error. The message says undefined method 'attributes' for nil:NilClass, the source is a line of code from the following file:
#app/decorators/employer/job_decorator.rb
def attributes
super.merge(
{
id: nil,
emp: nil,
}).delete_if { |k, v|
['class_name'].include?(k)
}
end
What is the reason for this?
UPDATE 3
Following the advice of the comments, I got back to the previous error after changing some of the decorators to the following.
def attrs
model.attributes.merge(
{
The error is "NoMethodError in Employers::JobController#show", and the file pointed to is one of the lines in "config/initializer/active_model/serialization.rb" (last line extracted below):
module ActiveModel
module Serialization
def serializable_hash(options = nil)
options ||= {}
attribute_names = attributes.keys
UPDATE 4
If I change the way decorator is written, the result is still similar to "undefined method `id' for #Employers::JobDecorator:0x00007ff3cdd3f748"
class Employers::JobDecorator < Draper::Decorator
delegate_all
def attributes
{
id: nil,
name: nil,
slug: nil
}
end
end
UPDATE 5
I suspect the reason is that #job is nil, so I added something to the controller, finally solved the problem. I got it in the wrong direction.
Draper infers the decorator from the object that is decorated and in your scenario is Employers::Job.
Because the decorator you want to be used has a totally different name, Api::V2::Employers::JobDecorator, you need to explicitly specify it.
So, Api::V2::Employers::JobDecorator.decorate(#job) is what you need.
More information, here
I am using Rails 5.2.2 There are many empty(nil) fields in my DB and created a custom method to use distance_of_time_in_words in my model without errors.
def my_distance_of_time_in_words
if self.accounts.blank?
"No Record Avaliable"
else
distance_of_time_in_words(self.accounts.first.updated_at,Time.now).titleize
end
end
And i am passing my object from view using :
<%= #customer.my_distance_of_time_in_words %>
It was working well and i restarted my PC and it says :
undefined method `distance_of_time_in_words' for #<Customer:0x00007f43b98601d8>
This is odd because as i said it was working as i expected.But it's not working now.
The date helpers are not available in your model by default, so you need to explicitly include them.
class Customer < ApplicationRecord
include ActionView::Helpers::DateHelper
def my_distance_of_time_in_words
if self.accounts.blank?
"No Record Avaliable"
else
distance_of_time_in_words(self.accounts.first.updated_at,Time.now).titleize
end
end
end
However a better approach would be to use a helper method to accomplish what you need, this way you won't need to explicitly include ActionView::Helpers::DateHelper since it is already available to you there:
module CustomersHelper
def my_distance_of_time_in_words(customer)
if customer.accounts.blank?
"No Record Avaliable"
else
distance_of_time_in_words(customer.accounts.first.updated_at,Time.now).titleize
end
end
end
I keep getting this error when I try to load the index page:
NoMethodError in MessageController#new_message
undefined method `action' for MessageController:Class
The error goes away if I replace BaseController with ApplicationController, but that also breaks a lot of other things and the tutorial(http://websocket-rails.github.io/) for rails-websocket has it as BaseController.
class MessageController < WebsocketRails::BaseController
def initialize_session
# perform application setup here
controller_store[:message_count] = 0
end
def new_message
new_message = {:message => 'this is a message'}
send_message :new_message, new_message
end
def index
end
end
Does anyone know what the problem is here?
--
edit
using rails version 4.0.2
if that matters at all
Seems like this has been reported as an issue on the project's issue tracker in the past, but has been closed (with non-fix).
The comment explaining the situation:
You don't want to mix ApplicationController methods with ones from WebsocketRails::BaseController. In fact, WebsocketRails::BaseController is designed after ApplicationController and implements some of the same methods, namely process_action.
The solution I used (and which they also suggest), is to use 2 controllers. One inheriting from WebsocketRails::BaseController and another from ActionController::Base (Rails). Put your logic in a separate class and use it from both.
I'm trying to call sanitize within a controller. Here's what I tried:
class FooController < ApplicationController
include ActionView::Helpers::SanitizeHelper
# ...
end
However, I'm getting this error:
undefined method `white_list_sanitizer' for FooController:Class
I searched around and people recommended switching the include line to include ActionView::Helpers, but that results in this error:
undefined method `url_for' for nil:NilClass
What's the correct way to call sanitize? I'm using Rails 2.3.5.
you can use this ActionController::Base.helpers inside action method:
class SiteController < ApplicationController
def index
render :text => ActionController::Base.helpers.sanitize('<b>bold</b>')
end
end
Hope this helps
Rails 6:
To strip links (for example) from a text, just call:
...
Rails::Html::LinkSanitizer.new.sanitize("links here will be stripped")
...
see https://github.com/rails/rails-html-sanitizer
I'm not sure what you're trying to do here but I'm almost 100% certain it doesn't belong in the controller.
If you want to sanitize an attribute before you save it to the DB, do so in the model with a before save callback.
Otherwise, sanitize in the view template or view helper.
I'm returning to RoR after not using it for a few years and I'm trying to use ActiveModel to serialise a plain object to XML.
I'm doing the following, as per the comments in activemodel/lib/activemodel/serialization.rb:
class XmlError
include ActiveModel::Serializers::Xml
attr_accessor :code
attr_accessor :description
def attributes
#attributes ||= {'code' => 'nil', 'description' => 'nil'}
end
def initialize(error_code)
#code = error_code
#description = "blah"
self
end
end
I use this in a controller as:
render :xml => XmlError.new("invalid_login")
and I get the following stacktrace:
NoMethodError (undefined method `model_name' for XmlError:Class):
app/controllers/users_controller.rb:19:in `login'
app/controllers/users_controller.rb:5:in `login'
If create a model_name class method, I then get the following stacktrace:
NoMethodError (undefined method `element' for "XmlError":String):
app/controllers/users_controller.rb:19:in `login'
app/controllers/users_controller.rb:5:in `login'
It feels like I'm chasing my tail here. Have I just missed something simple in my class? I followed the example closely.
extend ActiveModel::Naming
is what you are looking for.
http://rdoc.info/github/lifo/docrails/master/ActiveModel/Naming
Why not sub-class ActiveModel::Base?