Overriding the embed_key in Active Model Serializer - ruby-on-rails-4

I have a serializer with some has_many associations where I've modified the embed_key.
I'm trying to have the IDs for my model be like path-name rather than 12. The code below is making that happen:
class SymbolSerializer < ActiveModel::Serializer
attributes :id,
:name,
:parent_id,
:rails_id
embed :ids, include: true
has_many :ancestors, embed_key: :symbol_path, serializer: SimplifiedSymbolSerializer
has_many :children, embed_key: :symbol_path, serializer: SimplifiedSymbolSerializer
has_one :parent, embed_key: :symbol_path, serializer: SimplifiedSymbolSerializer
has_many :siblings, embed_key: :symbol_path, serializer: SimplifiedSymbolSerializer
def id
object.symbol_path
end
def parent_id
object.id
end
def rails_id
object.id
end
end
The problem is that I'd like to still have the actual id of the parent object (Which I've tried to do in my parent_id method ^^).
Right now the overridden method still returns the :symbol_path key rather than the id.
Anyone know how to address this?

The simplest way for me to address this was to just use a different naming convention for the key I wanted to pass.
So all I had to do was add this method/attribute in there too:
def parent_rails_id
object.parent.id
end

Related

Access rails model attributes through a has one association

My User has one Driver:
class User < ActiveRecord::Base
has_one :driver, :dependent => :destroy
end
class Driver < ActiveRecord::Base
belongs_to :user
end
User attributes include, user_first_name, user_last_name, user_email and user_phone number.
I want to be able to access these User attributes when working with the driver class.
For example:
#drivers = Driver.where( :user_first_name => "David )
Obviously the above code won't work, since user_first_name is not a Driver attribute, but is there a way to do this without looping through each user record?
I'm still new to Rails but hopefully this is helpful!
If you create a foreign key index to associate your model's tables within the database, then you should be able to access the data like so...
#user = User.find(params[:id])
#drivers = Driver.where( #user.user_first_name => "David" )
Also, not sure if it was a typo here, but you forgot to close the quotes with "David.

ActiveRecord - Display columns from multiple associations

I have a user, user_profile and profile_type models. A user has_many user_profiles, a user_profile belongs_to a user and belongs_to a profile_type and a profile_type has_many user_profiles.
I have been reading on how to get this work but I am having problems figuring this out and any help would be much appreciated.
I know I could do this with SQL with a statement like this (freehand SQL, excuse mistakes), but I want to use ActiveRecord.
Select up.id, u.user_id, pt.connection_type
from user u
join user_profile up
on u.user_id = up.user_id
join profile_type pt
on pt.profile_type_id = up.profile_type_id
where u.username = "test"
I want to return nested user_profile objects for an associated user but I want the user_profile object to contain the profile_type.connection_type instead of the profile_type.profile_id.
Currently, if I do this,
user.user_profiles.all
add then iterate through the nested user_profiles that are returned, this is my output:
{
:id
:user_id
:profile_type_id
}
What I want is:
{
:id
:user_id
:profile_type.connection_type (instead of profile_type.profile_type_id)
}
User Model
class User < ActiveRecord::Base
has_many :user_profiles, autosave: true
has_many :account_settings, autosave: true
end
User_Profile Model
class UserProfile < ActiveRecord::Base
belongs_to :user
belongs_to :profile_type
end
User Profile Type Model
class ProfileType < ActiveRecord::Base
has_many :user_profiles
end
Try this:
user.account_settings.select("profile_type.*, profile_type.connection_type").all
I was able to figure out how to do this using Grape.
Since the association was already created, I can use Grape entities to expose what I needed out of the associations. It works seamlessly and I hope this helps anyone else who is having a similar problem.
To get what I was looking for, I needed to gather all user_profiles
userprofiles = user.user_profiles.all
Then, I presented this using Grape
present :user_profile_settings, userprofiles, with: API::V1::Entities::UserProfile
And, here is what my entities looked like:
class UserProfile < Grape::Entity
expose :profile_type, using: ProfileTypeEntity
end
class ProfileTypeEntity < Grape::Entity
expose :connection_type
end

Rails collection_select passing id

I've read a bunch of questions but none of them are helping me with this problem. I am trying to create a form to make new forums but cannot get them to use the right category id.
<%= f.collection_select :category_id, Category.all, :id, :name %>
This creates a new forum but the id is not the category id from the drop down list. Here is the forums model
def new
#forum = Forum.new
end
def create
#forum = Forum.new(forum_params)
if #forum.save
redirect_to root_url
else
render 'new'
end
end
private
def forum_params
params.require(:forum).permit(:category_id, :name, :description )
end
end
Not quite sure what I am doing wrong here. Is it something to do with the foreign key? Any help would really be appreciated.
UPDATE
Forum Model
class Forum < ActiveRecord::Base
belongs_to :category
has_many :topics, dependent: :destroy
end
Category Model
class Category < ActiveRecord::Base
has_many :forums, dependent: :destroy
end
There is basically no category_id in the Forum model.
Here is a couple of things you can do to troubleshoot this. Run:
rails dbconsole
.schema
Check to see if you have category_id or not. If not, create a new migration for this.
Your initial code is correct. For some reason, I misread that your collection_select was already bound to the model.

Best way to update Has_many Joined Table

right now I have a jobs table with
has_many :applicants
has_many:users, through: :applicants
and a applicant table with
belongs_to :job
belongs_to :user
and a user table with
has_many :applicants
has_many:jobs, through: :applicants
So Users are connected through applicant table to Jobs table and vise versa.
I'm not sure I'm updating the model correctly. Right now it looks like this:
def addapply
#job = Job.find(params[:id])
applicant = Applicant.find_or_initialize_by(job_id: #job.id)
applicant.update(user_id: current_user.id)
redirect_to #job
end
But I got to thinking - would not this replace whatever association was there before?
I started looking around and found this in someone else's code:
def update
unless params[:user_relationships][:user_category_ids]
# Set default user category if not selected.
#user.user_category_relationships.build(
:category_id => '1',
:created_by_user_id => #current_user.id,
:name_id => #name.id
)
else
params[:user_relationships][:user_category_ids].each { |user_category_id|
#user.user_category_relationships.build(
:category_id => user_category_id,
:created_by_user_id => #current_user.id,
:name_id => #name.id
)
}
end
end
I'm not sure how that all works but perhaps I do need to iterate through them with a .each before I update.
I don't want to replace what is already there, I just want to add to it.
In Short what is the best way to update (or rather add to) a has_many :through joined table association?
Why not?
def addapply
#job = Job.find(params[:id])
applicant = Applicant.where(job_id: #job.id, user_id: current_user.id).first_or_create
redirect_to #job
end

How to fill the related model on a many 2 many association?

Using ember-data, I have this two models:
App.Post = DS.Model.extend
title: DS.attr "string"
body: DS.attr "string"
categories: DS.hasMany "App.Category"
App.Category = DS.Model.extend
name: DS.attr "string"
posts: DS.hasMany 'App.Post'
and this serialization:
class PostSerializer < ActiveModel::Serializer
attributes :id, :title, :body
has_many :categories
embed :ids, include: true
end
class CategorySerializer < ActiveModel::Serializer
attributes :id, :name
end
When I ask for posts, I get the expected JSON and I can access a post's categories without problem, but if I request the categories (that I think that they are cached) I get the categories without any relation to posts. It doesn't even try to make a get request (that wouldn't work either).
So, shouldn't categories have their posts relations filled up?
Not sure if I miss something in ember or AMS (which I think that the category serializer should know that has many posts)
Well, after struggling with some guys at IRC I ended with this solution, which I hope it will be helpful for others and maybe improved.
The problem was that the categories doesn't had any post reference, So if you ask for Posts, you get the posts with categories, but the categories themselves knows nothing about posts.
If I try to do something like:
class CategorySerializer < ActiveModel::Serializer
attributes :id, :name
has_many :posts
embed :ids, include: true
end
it will explode because they are referencing each other and you get a "Too deep level" or something like that.
You can do something like:
class CategorySerializer < ActiveModel::Serializer
attributes :id, :name
has_many :posts, embed: :objects
end
and it will work, but the result JSON will be huge because when you request posts, you get every post + every comment and inside them, every post that have that category... No love
So what's the idea? Having something like:
class PostSerializer < ActiveModel::Serializer
attributes :id, :title, :body
has_many :categories
embed :ids, include: true
end
class CategorySerializer < ActiveModel::Serializer
attributes :id, :name
has_many :posts, embed: :ids
end
For every post you get the categories_ids and for every category you reference, you only get its attributes and the ids (not the entire objects) of the posts that belongs to that category.
But what happens when you go to '/#/categories' and you didn't loaded the posts yet? Well, since your CategorySerializer doesn't serialize any post, you won't get anything.
So since you can't do cross references between serializers, I ended with 4 serializers. 2 for posts and their categories and 2 for categories and their posts (so, doesn't matter if you load the posts first or the categories):
class PostSerializer < ActiveModel::Serializer
attributes :id, :title, :body
has_many :categories, serializer: CategoriesForPostSerializer
embed :ids, include: true
end
class CategoriesForPostSerializer < ActiveModel::Serializer
attributes :id, :name
has_many :posts, embed: :ids
end
class CategorySerializer < ActiveModel::Serializer
attributes :id, :name
has_many :posts, serializer: PostsForCategorySerializer
embed :ids, include: true
end
class PostsForCategorySerializer < ActiveModel::Serializer
attributes :id, :title, :body
has_many :categories, embed: :ids
end
This does the trick. But since I'm new with Ember and I'm not a crack of JSON design. If someones knows a simple way or maybe doing some embedded (always or load in the adapter, which I don't understand yet), please comment :)