How to set ActiveModel::Base.include_root_in_json to false? - ruby-on-rails

I'm using Rails 3 w/ Mongoid, (so no ActiveRecord). Mongoid uses ActiveModel's "to_json" method, and by default that method includes the root object in the JSON (which I don't want).
I've tried putting this in an initializer:
ActiveModel::Base.include_root_in_json = false
But get the error
uninitialized constant ActiveModel::Base
Any ideas how I can change this? I changed the default directly in the source-code and it worked fine, but obviously I'd like to do it properly.
The variable is defined at the top of this file:
Github - activemodel/lib/active_model/serializers/json.rb
From the docs:
"The option ActiveModel::Base.include_root_in_json controls the top-level behavior of to_json. It is true by default."

I know this is old, but another way you can do this is by placing this within your application class in application.rb:
# When JSON-encoding a record, don't wrap the attributes in a hash where the
# key is named after the model
config.active_record.include_root_in_json = false

You should simply set it on the class that includes the ActiveModel modules:
class Person
include ActiveModel::Validations
include ActiveModel::Serializers::JSON
self.include_root_in_json = false
...
end

ActiveModel::Base.include_root_in_json = false
in an initializer??

If you prefer initializers, it's ActiveRecord::Base, not ActiveModel::Base in Rails versions 2.* and 3.1, possibly 3.0. Looked through the source, and in 3.0 beta it was switched to ActiveModel, but back again to ActiveRecord at some point.
ActiveRecord::Base.include_root_in_json = false
Also, in case you're actually trying to use this functionality, in Rails 3.1 the params wrapper is relevant:
ActionController::ParamsWrapper
Wraps the parameters hash into a nested hash. This will allow clients to submit POST requests without having to specify any root elements.
http://edgeapi.rubyonrails.org/classes/ActionController/ParamsWrapper.html

Related

Why do methods defined in an initializer intermittently raise a 'not defined' error which is resolved by restarting the server?

I'm using PaperTrail 4.1 with Rails 4.2.
I have defined several custom methods in an initializer (see: How to add a method to the versions model of Paper_trail?)
#config/initializers/paper_trail.rb
PaperTrail::Rails::Engine.eager_load!
module PaperTrail
class Version < ActiveRecord::Base
scope :scoped, lambda { #selects some records }
def custom_method
#does some stuff
end
end
end
Every so often in development environment I get a method not defined error for methods/ scopes defined in this initializer.
Restarting the server fixes the problem.
Why are these methods being 'lost' to Rails?
Is this an issue that will also present itself in production or other environments?
What steps can I take to find the cause of this issue?
For anyone else arriving here, apparently this is a known issue with PaperTrail
From https://github.com/airblade/paper_trail/pull/492
Now the paper_trail source get's reloaded in the development
environment when saving a file which means the class gets discarded
from the cache and rebuild from the paper_trail sources. The
initializer is not interpreted again since they are one time only, no
module_eval, no abstract class -> exceptions.
And a fix has been included in the latest version of the gem: https://github.com/airblade/paper_trail/pull/557
In essence, it is no longer advised to use an initializer to add custom methods to PaperTrail, and instead to use a model that inherits from PaperTrail (which is a much better fit with AR).
# app/models/paper_trail/version.rb
module PaperTrail
class Version < ActiveRecord::Base
include PaperTrail::VersionConcern
# my custom methods
end
end

Adding to Rails.application.config before initializers run

I want to inject a custom property (hash map) into my Rails.application.config. It seems that the way to do it is simply to assign a new variable in environment.rb:
Rails.application.config.feature_map = { :email => true }
I need to access this map through various places in my application, like the user model, controllers, and rake tasks.
Other gems, like devise, also need access to this. The problem is that adding it to environment.rb seems to be too early in the application life-cycle.
I have code in initializers/devise.rb like this:
if Rails.application.config.feature_map[:email] = true
The server complains that this field doesn't exist.
I also use it to add additional validation in my user model:
if Rails.application.config.feature_map.enabled?(:username)
validates_length_of :username, :in => 3..50
I also get a runtime error here about undefined feature Rails.application.config.feature_map
Where can I move this so that I can access it as early as in initializers and in my model class? I tried moving it into a new initializers/feature_map.rb file, but that didn't work either.
Put it in config/application.rb:
module MyRailsApp
class Application < Rails::Application
config.feature_map = ActiveSupport::OrderedOptions.new
config.feature_map.email = true
end
end
Anything you set in there will be default for all environments, but can be overridden per environment in config/environments/*.rb.
Gems like Figaro and .env will help you load up your config even before the loading of initializer.rb
Unless there is a strong reason that you wouldn't wanna use environment variables, I would recommend using either of those gems since they are the recommended way of adding your custom configs.
Edit: See Jimmy Cuadra's answer above, which I ended up going with.
I found an alternative solution: this answer to manipulate the order of initializers.
I can rename my initializer to 00_feature_map.rb and it loads first.

Uninitialized content when trying to include ActionController::UrlWriter in model

I'm using Rails 3 beta 4 and trying to include ActionController::UrlWriter in my model, which is the correct way to go about it as far as i can tell, but i get "Uninitialized Constant ActionController::UrlWriter".
Any idea why that would be? Did it move in rails 3?
First I agree with zed. This shouldn't be done in a model. Your models should be unaware of any http url.
I do the same in a resque job. Here's what I do :
include ActionDispatch::Routing::UrlFor
include ActionController::PolymorphicRoutes
include Rails.application.routes.url_helpers
default_url_options[:host] = 'example.com'
Then you can call any usual url generator.
url_for(object)
page_url(object)
It'll create the link on the host defined as default_url_options[:host]
Answers to Can Rails Routing Helpers (i.e. mymodel_path(model)) be Used in Models? are pretty good
or see
http://api.rubyonrails.org/classes/ActionDispatch/Routing/UrlFor.html
http://siddharth-ravichandran.com/2010/11/26/including-url-helpers-in-models/
Basically, you can do something like this in a model:
def url
Rails.application.routes.url_helpers.download_attachment_path(self)
end
It is worth considering whether this is the right layer, though. In my case it's for file attachments and I want to do attachment.url instead of writing out a helper a lot.

Backward compatibility issues with json libraries in rails 2.3.4

to_json method in rails 2.0.2 for objects(say user model object with id and name)used to give simple output in the form
{"id":"xyz","name":"hello"}
But while upgrading the rails to 2.3.4 it gives the output as
{"user":{"id":"xyz","name":"hello"}}
This is breaking my most of the frontend code.
Is there way to get the results in the same fashion as in 2.0.2 ???
Looking for a speedy answer from you guys!!
You need to edit the file config/initializers/new_rails_defaults.rb and change ActiveRecord::Base.include_root_in_json = true to false. That should do it. See the to_json documentation.
If for some reason you don't have that file, this is what it should look like in a default Rails 2.3.x app.
# Be sure to restart your server when you modify this file.
# These settings change the behavior of Rails 2 apps and will be defaults
# for Rails 3. You can remove this initializer when Rails 3 is released.
if defined?(ActiveRecord)
# Include Active Record class name as root for JSON serialized output.
ActiveRecord::Base.include_root_in_json = true
# Store the full class name (including module namespace) in STI type column.
ActiveRecord::Base.store_full_sti_class = true
end
# Use ISO 8601 format for JSON serialized times and dates.
ActiveSupport.use_standard_json_time_format = true
# Don't escape HTML entities in JSON, leave that for the #json_escape helper.
# if you're including raw json in an HTML page.
ActiveSupport.escape_html_entities_in_json = false

Specifying model in controller?

I came across a controller in an older set of code (Rails 1.2.3) that had the following in a controller:
class GenericController > ApplicationController
# filters and such
model :some_model
Although the name of the model does not match the name of the model, is there any reason to specify this? Or is this something that has disappeared from later versions of Rails?
This had to do with dependency injection. I don't recall the details.
By now it's just a glorified require, which you don't need because rails auto-requires files for missing constants.
Yes, that is something that has disappeared in later versions of Rails. There is no need to specify it.

Resources