Display child element along with Parent in Rabl - json

I created rails-api application with rabl as json builder template. My models are below
class Course < ActiveRecord::Base
belongs_to :department
end
class Department < ActiveRecord::Base
has_many :courses
end
I am return courses as json. My Course has Title and Credits and DepartmentId. My existing rabl is
collection #courses => :courses
attributes :id, :Title, :Credits
But i need to include department name which is in the Department table. So my json is
{
courses:
{
course: {
id: 1045
Title: "Calculus"
Credits: 4
}-
}-
{
course: {
id: 1050
Title: "Chemistry"
Credits: 3
}-
}
}
}
I need as add department as next object after Credits. Is normal rails app, i can put course.department.Name in the html. but how in rabl? Please guidee me

I will suggest to add delegate in Course model
delegate :name, to: :department
then add
collection #courses => :courses
attributes :id, :Title, :Credits , :department_name

Related

How to save selected values from one table column to another table column

I am new to Rails, and trying to learn. In my simple form I have created a drop down select with generated data from a table called professions. This part is working fine, and I can select multiple values. I'm using a mysql database.
When I click the submit button, I need it to save the chosen values to a column called my_professions in another table called users. I can’t figure out how to do this.
I get this error
My form
<%= simple_form_for #user, url: wizard_path, method: :put do |f| %>
<%= collection_select(:f, :professions_id, Profession.where.not(name: nil), :id, :name, {:multiple => true}, {:class=>'js-example-basic-multiple', :id=>'jsmultipleddd'}) %>
<%= f.submit "Save", :class => 'btn blue' %>
<% end %>
I have tried to add this to the user model
user.rb
class User < ApplicationRecord
has_many :professions
accepts_nested_attributes_for :professions
serialize :my_professions, Array
end
And this to the profession model
profession.rb
class Profession < ApplicationRecord
belongs_to :user
end
my params look like this
registration_steps_controller.rb
def user_params
params.require(:user).permit(:gender,:practitioner_website, :public_health_insurance, clinic_images: [], professions: [])
end
application_controller.rb
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:gender, :practitioner_website, :public_health_insurance, clinic_images: [], professions: []])
devise_parameter_sanitizer.permit(:account_update, keys: [:gender, :practitioner_website, :public_health_insurance, clinic_images: [], professions: []])
end
Start by getting rid of accepts_nested_attributes_for :professions. You don't need nested attributes for this.
Then get rid of serialize :my_professions, Array. Serialize is a legacy hack to store complex data in string columns. You don't need or want this (ever), since associations should be stored in join tables in ActiveRecord - not array columns. That's how AR was designed to work and that's how relational databases where designed to work.
Instead what you want is a join model. Which you can generate with:
rails g model user_profession user:belongs_to profession:belongs_to
Run the migration. You then setup the associations between users and professions:
class User < ApplicationRecord
# ...
has_many :user_professions
has_many :professions, through: :user_professions
end
class Profession < ApplicationRecord
# ...
has_many :user_professions
has_many :users, through: :user_professions
end
Now this lets us associate users with professions by passing profession_ids.
In a normal Rails form you would create the input with:
<%= f.collection_select :profession_ids, Profession.all, :id, :name, multiple: true ... %>
In SimpleForm use the association helper:
<%= f.association :professions, ... %>
Then whitelist the correct param:
def user_params
# don't jam this into one super long unreadable line
params.require(:user)
.permit(
:gender, :practitioner_website, :public_health_insurance,
clinic_images: [], profession_ids: []
)
end

Render :json with includes does not render table data with different model name

I have following model structure
class SetBenchmark < ApplicationRecord
self.table_name = 'benchmarks'
has_many :my_question_sets
end
class MyQuestionSet < ApplicationRecord
belongs_to :set_benchmark, class_name: 'SetBenchmark',
end
class MyAdmin < ApplicationRecord
has_many :my_question_sets
end
Following is controller render method
render json: my_admin, include: { my_question_sets: [ 'benchmark.*'] }
I am not getting benchmark data in response. Is it because it has different class name than table name?
I think you should use association names, not table names in json specification.
render json: my_admin, include: { my_question_sets: :set_benchmark }
https://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json

storing values into a integer variable

I have a question about storing a value into a integer variable. Is it possible to store different id into the same variable ?
This is my problem, I would like to use a collection_select to save many id's.
My code is actually working for one variable, like this :
My code :
User model :
has_many :pins
scope :artist, -> { where(artist: true) }
Pin model :
belongs_to :user
Pin controller:
def new
#pin = Pin.new
#users = User.all.artist
end
def create
#pin = current_user.pins.build(pin_params)
if #pin.save
redirect_to #pin, notice: "successfully created!"
else
render 'new'
end
end
Pin/new(views):
<div class="form-group">
<%= f.collection_select(:pin_maker, #users, :id, :pseudo) %>
</div>
I would like something like that for my new views :
<div class="form-group">
<%= f.collection_select(:pin_maker, #users, :id, :pseudo, { }, {:multiple => true}) %>
</div>
But the variables are not saving in my sql table.
So my question is : That's possible to store many id in the same variable (:pin_maker) which is an integer ? Or should I create a new table for that ?
pin_maker is user ? if so:
(IMO): you need a n-to-n associations and a table users_pins.
Logic:
One user has many pins
One pin may be made by many users
On Rails:
Model User:
has_many pins, :through => :users_pins
Model Pin:
has_many users, :through => :users_pins
Try has_many :users to involve your associations

Rails JSON using RABL, showing parent attribute?

I have the following RABL file in my Rails 3.2 application:
collection #results.limit(5)
attributes :date, :client_id
child :client do
attributes :Surname
end
child :animal do
attributes :AnimalName
end
I would like to add the name of the user that the result belongs to. Everything I have read in the RABL documentation seem to suggest that only child and node are available.
How could I get a parents attribute within the above code? Just doing the following returns NULL, obviously!
child :animal do
attributes :AnimalName
end
Is this possible?
Current JSON output:
{
date: "2013-06-25T19:36:11+01:00",
client_id: 88172,
client: {
Surname: "Strange"
},
animal: {
AnimalName: "Ria"
}
},
Desired output:
{
date: "2013-06-25T19:36:11+01:00",
client_id: 882372,
client: {
Surname: "Summer"
},
animal: {
AnimalName: "Ria"
},
user: {
UserName: "Danny"
}
},
You can add a custom node that adds in the user data:
collection #results.limit(5)
attributes :date, :client_id
node :user do |report|
partial('users/show', :object => report.user)
end
This is assuming that you want the whole user/show template.
If you just want the name key/value:
node :user do |report|
{ :name => report.user.name }
end

Datamapper Many-To-Many relation

Article has many authors, editors, translaters, etc. All of class Person.
Is it possible to generate join model? Or, in this case, solution is to create each join models manually.
class Article
include DataMapper::Resource
property :id, Serial
property :published_date, Date
property :status, Enum[ :pending, :accepted, :declined, :modified, :new ], :default => :new
property :visible, Boolean, :default => false
timestamps :at
has n, :authors, 'Person', :through => Resource
end
class Person
include DataMapper::Resource
property :id, Serial
property :name, String
property :about, Text
property :gender, Enum[ :male, :female ]
property :birthday, Date
timestamps :at
has n, :articles, :through => Resource
end
looks like it impossible. Only manual model creation.