Rails Active Model serializers not setting root - activemodel

I have a class that is not an ActiveRecord object and im trying to create a AM serializer for it. I can return the proper json, but its not including a root
in have this in my controller
format.json { render json: #current_user, root: "current_user" }
and my class looks like this
class CurrentUser
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :first_name, :last_name, :user_type, :user_id
end
Ive also tried adding this in the controller
def default_serializer_options
{root: true}
end
But still my json object does not have the root which I need for Ember Model
return object
{"first_name":"Luke","last_name":"Skywalker","user_type":"Padawan","user_id":12}
and I need
{current_user: {"first_name":"Luke","last_name":"Skywalker","user_type":"Padawan","user_id":12} }

For anyone in the future who may come across this same problem,
when using ActiveModelSerializers 0.10.x, just add to an existing initializer or create a new one and add this to include the root node in your responses:
config/initializers/serializer.rb:
ActiveModel::Serializer.config.adapter = :json
AMS documentation states that this is not backwards compatible for versions 0.9.x and 0.8.x.

If using default_serializer_options inside your controller doesn't work, maybe you should have a look into config/initializers/wrap_parameters.rb for include_root_in_json option.
If you are curious, concerned source code for that option can be found here.

Related

CakePHP static name of controller

I'm probably missing something really obvious here, but is there a function in CakePHP (I'm on 3.8) that returns the name of a controller without creating an instance of the class?
An instanced controller can call this function:
echo $this->name;
But what I'd like to be able to do, is avoid typing the controller name as a string in, say, an HTML->link(); ie a static call something like:
echo $this->Html->link(
'Dashboard',
['controller' => DashboardsController::name, 'action' => 'index']
);
The reason is that I'm refactoring a couple of controllers and am having to find and replace all of those strings by hand. I come from a .Net background and CakePHP is pretty new to me, so if there's a better (more cakeish) way to carry out the refactoring than the question I'm asking, then I'd be really glad to hear it.
Nothing in the documents is leaping out at me, but I've a feeling there should be a simple answer.
The namespace of a class can be retrieved using ::class property. Checkout the following example:
DashboardsController::class // Cake/Controllers/DashboardController
The name without the namespace can be retrieved with ReflectionClass:
$function = new \ReflectionClass(DashboardsController::class);
var_dump($function->inNamespace());
var_dump($function->getShortName());
Shortname can be used to get the class without namespace:
namespace App;
class Test {
public static function name(){
$function = new \ReflectionClass(self::class);
return $function->getShortName();
}
}
var_dump(Test::name());
Checkout the docs: https://www.php.net/manual/en/language.oop5.constants.php#example-186
Reflection: https://www.php.net/manual/en/reflectionclass.getname.php

Meaning of Yii::$app->user->identity->role->role_name;

In a book called Yii2 for Beginners, which is mainly about the advanced template, I have encountered the following unexplained code, which seems relevant to RBAC:
$userHasRoleName = Yii::$app->user->identity->role->role_name;
What exactly does this mean? For example, I guess that this:
Yii::$app->user
refers to this file:
vendor\yiisoft\yii2\web\User.php
Is this correct?
In any case, what does the rest of the code refer to? Specifically:
->identity->role->role_name
In the above User.php file, I have not been able to find anything like "function identity()", so it can't be that. I have found numerous $identity variables, but I don't know which one the code might be referring to. And there is no $role variable at all.
What is this code referring to:
Yii::$app->user->identity->role->role_name;
Yii described magic methods like __get, __set and so on, to get access for inaccessible properties. Oftenly such methods begins from get or set (in Yii implementation it is). To get access to ->identity, \yii\web\User has method getIdentity. This method return identity wich you described in config with identityClass property for user component. Oftenly identityClass is a AR model which implements IdentityInterface.
'components' => [
'user' => [
'identityClass' => 'common\models\User',
]
]
To get access to ->role for example you must to create a new method
namespace common\models;
class User extends ActiveRecord implements IdentityInterface {
public function getRole(){
// if user can have only one role
return current( \Yii::$app->authManager->getRolesByUser( $this->id ) );
}
}
Btw implementation of ->role->role_name may be very different.

Enum Values return as json in Rails

I have model called location with one enum location _type. My model implemented like below
class Location < ActiveRecord::Base
enum location_type: [:Offshore, :Onsite]
end
This work correctly for mapping insertion and display. But now i want an action to give the enum as json for binding to the drop down in the client side. Please help me to do this
Edit:
Now i read this articles expected like this only. But i just copt and created Enum class and LocationType class in the lib directory (with out any module nmae). But how i do this in controller action. I got NameError. My controller is
class Api::V1::LocationsController < Api::V1::BaseController
def get_location_types
Rails.logger.warn(LocationType.values)
#respond_with Location.location_types.to_json
end

TYPO3. Passing objects as arguments in FLUID View Helpers

In the following code booksis a list of book object containing certain properties. And by clicking on the title, it goes to an action display
Fluid template is
<f:for each="books" as="book">
<f:link.action action="display" arguments="{book: book}"> {book.title} </f:link.action>
</f:for>
In controller
public function displayAction(){
print_r($this->request->getArguments());
}
The value of book here is not being set. [book] => null. I try printing the class of it, it still gives me null.
It works fine when I send the arguments as book.title instead of the entire object
What am I missing here? Is this the right way to pass objects as arguments ?
EDIT:
Initially I tried this way.
public function displayAction(\TYPO3\MyExt\Domain\Model\Book $book) {}
But this gives me
Exception while property mapping at property path "":No converter found which can be used to convert from "string" to "TYPO3\MyExt\Domain\Model\Book"
The class Book is something which I created manually and is not registered under extension builder.
You could try it with a parameter for the action:
public function myAction(Tx_MyExt_Domain_Model_Book $book) {
$this->view->assignMultiple(array(
'title' => $book->getTitle(),
'label' => $book->getLabel(),
'content' => $book->getContent()
));
}
EDIT: I updated the example.
Update:
It works with book.title because it's just a string. When you want a complete book object it needs to be found in some storage. A database e.g.. Hence that means you need a model and a repository. Also an entry in the tca and the tables files. Better create your Models with the extension builder, it's much easier and safer for the beginning.

Check if object is an sqlalchemy model instance

I want to know how to know, given an object, if it is an instance of an sqlalchemy mapped model.
Normally, I would use isinstance(obj, DeclarativeBase). However, in this scenario, I do not have the DeclarativeBase class used available (since it is in a dependency project).
I would like to know what is the best practice in this case.
class Person(DeclarativeBase):
__tablename__ = "Persons"
p = Person()
print isinstance(p, DeclarativeBase)
#prints True
#However in my scenario, I do not have the DeclarativeBase available
#since the DeclarativeBase will be constructed in the depending web app
#while my code will act as a library that will be imported into the web app
#what are my alternatives?
You can use class_mapper() and catch the exception.
Or you could use _is_mapped_class, but ideally you should not as it is not a public method.
from sqlalchemy.orm.util import class_mapper
def _is_sa_mapped(cls):
try:
class_mapper(cls)
return True
except:
return False
print _is_sa_mapped(MyClass)
# #note: use this at your own risk as might be removed/renamed in the future
from sqlalchemy.orm.util import _is_mapped_class
print bool(_is_mapped_class(MyClass))
for instances there is the object_mapper(), so:
from sqlalchemy.orm.base import object_mapper
def is_mapped(obj):
try:
object_mapper(obj)
except UnmappedInstanceError:
return False
return True
the complete mapper utilities are documented here: http://docs.sqlalchemy.org/en/rel_1_0/orm/mapping_api.html
Just a consideration: since specific errors are raised by SQLAlchemy (UnmappedClassError for calsses and UnmappedInstanceError for instances) why not catch them rather than a generic exception? ;)