json rendering issue in rails - ruby-on-rails

I have added following code in user.rb.
def as_json(options={})
h = super(:only => [:id, :content, :created_at, :updated_at])
h
end
But in another api I have to get username and address as well. But producing these four fields when rendering json. How can I get both outputs. Thanks in advance

Let the two API be
this API should return username and address too
def api1
User.first.as_json(user_info: true)
end
this does not need to return username and address
def api2
User.first.as_json(user_info: false)
end
let the user.rb be
class User < ApplicationRecord
def as_json(options = {})
if options[:user_info] == true
user = super(:only => [:id, :content, :created_at, :updated_at, :username, :address])
else
user = super(:only => [:id, :content, :created_at, :updated_at])
end
user
end
end

I don't have any better idea but I think you can use except like:
def as_json(options={})
h = super(:only => [:id, :content, :created_at, :updated_at, :username, :address])
h
end
Then when rendering you can use #yourVariable.as_json(except: [:username, :address]) when you don't need those or you can use only instead of except

Related

Persist nested data to database in one transaction

I have 3 models:
class Address < ApplicationRecord
has_one :company_address
end
class CompanyAddress < ApplicationRecord
belongs_to :address, dependent: :destroy
belongs_to :address_type
end
class Company < ApplicationRecord
has_many :company_addresses
end
I am getting JSON data from another application.
The data consists of attributes of a company and one/none or many company_address which consists of only one address each
I want to be able to insert and update the data automatically and if anything fails I want to role the migration back
When I set require on strong_params I don't receive the array of company_addresses, however when I only use permit it works fine
This doesn't work:
params.require(:company)
.permit([
:short, :name, :company_legal_form_id,
:company_role_id, :parent_id, :email,
:fax, :phone, :description,
:comment, :changed_by,
company_addresses: [
:company_id, :address_type_id, :addition,
:comment, :changed_by,
address: [
:street, :zip, :city,
:country_id, :other1, :other2,
:other3, :comment, :changed_by
]
]
])
This works:
params.permit([
:short, :name, :company_legal_form_id,
:company_role_id, :parent_id, :email,
:fax, :phone, :description,
:comment, :changed_by,
company_addresses: [
:company_id, :address_type_id, :addition,
:comment, :changed_by,
address: [
:street, :zip, :city,
:country_id, :other1, :other2,
:other3, :comment, :changed_by
]
]
])
So I created a Form-Object called CompanyForm with these methods.
class CompanyForm
include ActiveModel::Model
attr_accessor(
:company_attributes
)
def save
#company_id = company_attributes.delete('id')
company_addresses_attributes = company_attributes.delete('company_addresses')
company_attributes[:changed_by] = 'user'
company.update!(p company_attributes)
#company_id = company.id
if company_addresses_attributes.empty?
company.company_addresses.destroy_all
end
company_addresses_attributes.each do |company_address_attributes|
#company_address_id = find_company_address_id(company_address_attributes)
address_attributes = company_address_attributes.delete('address')
#address_id = find_address_id(address_attributes)
address_attributes[:changed_by] = 'user'
address.assign_attributes(p address_attributes)
#address_id = address.id
company_address[:changed_by] = 'user'
company_address.build_address(#address.attributes)
company_address.assign_attributes(p company_address_attributes)
company.company_addresses.update!(p company_address.attributes)
end
end
private
def company
#company ||= Company.find_by(id: #company_id) || Company.new()
end
def address
#address ||= Address.find_by(id: #address_id) || Address.new()
end
def company_address
#company_address ||= CompanyAddress.find_by(id: #company_address_id) || CompanyAddress.new()
end
def find_company_id(params)
params.dig(:id)
end
def find_company_address_id(params)
params.dig(:id)
end
def find_address_id(params)
params.dig(:id)
end
end
The first question is: why can't I get company_address as well when I set require on :company?
The second question is, how could I get my code to work without problems? I know that the code is really ugly, however I am new to Rails and Ruby in general.
It looks like an issue with the JSON itself - it would help if you provided actual example of JSON sent in that request. The structure could be different than you expect (eg 'company' nested inside of another key).
Try using binding.pry at the first line of the controller which handles that request and investigate what are returns from params and params.require(:company) it might lead you to the answer.

Rails nested attributes type mispatch error

I am creating a rails api using rails_api gem, I have a model name User and another model named Identity.
The issue I am facing is that whenever I tries to create user from params with nested_attributes it gives me ActiveRecord::AssociationTypeMismatch error
Models
User.rb
class User < ActiveRecord::Base
enum gender: [:male , :female]
has_many :identities ,dependent: :destroy
accepts_nested_attributes_for :identities
has_secure_password
end
Identity.rb
class Identity < ActiveRecord::Base
belongs_to :user
validates_associated :user
end
Controllers
users_controller.rb
class UsersController < ApplicationController
def create
#user = User.new user_params
##user.build.identities(user_params[:identities])
if #user.save
render json: #user , status: :created
else
render json: #user.errors, status: :unprocessable_entity
end
end
private
def user_params
json_params = ActionController::Parameters.new( JSON.parse(request.body.read) )
json_params.require(:user).permit(:first_name, :last_name, :email, :password, :image, :location, :gender,{identities: [:provider, :uid, :url, :token, :expires_at]})
end
end
I am sending the data as json object:
This is the error in server console:
Kindly help me fix this issue. I have tried all the possible solutions. Thanks in advance
Your strong param should be like this:
json_params.require(:user).permit(:first_name, :last_name, :email, :password, :image, :location, :gender,identities_attributes: [:provider, :uid, :url, :token, :expires_at])
json_params.require(:user).permit(:first_name, :last_name, :email, :password, :image, :location, :gender, :identities => [:provider, :uid, :url, :token, :expires_at])
this will resolve your issue as in current way.

How to get only nested params in strong parameter in ruby on rails

How can I get the only need_attributes from this?
def needy_params
params.require(:needy).permit(:user_name, :user_email, :needs_attributes: [:name, :description, :amount_required, :country_id, :city_id])
end
Is it possible that I get only needs_attributes from this or write new method like this?
def need_param
params.require(:needy.needs_attributes).permit(:name, :description, :amount_required, :country_id, :city_id)
end
This would work for you:
def needs_attributes_param
params.require(:needy).require(:needs_attributes).permit(
:name, :description, :amount_required, :country_id, :city_id
)
end

Rails Update method doesn't work

I want to update a prediction_config, but something is going wrong. Here are the relevant methods in my controller:
def edit
#prediction_config = PredictionConfigs.find(params[:id])
end
def update
#prediction_config = PredictionConfigs.find(params[:id])
if #prediction_config.update_attributes(params[:prediction_config])
redirect_to #prediction_config
else
render 'edit'
end
end
Here is my Model:
class PredictionConfigs < ActiveRecord::Base
attr_accessible :name, :value
validates :name, presence: true
validates :value, :inclusion => {:in => [0,100]},
presence: true
end
What could be the problem? Any help is appreciated!
EDIT: It is simply not updating the value, but everything loads properly.

Rails validation from controller

There is a contact page, which offers to enter name, telephone, email and message, after that it sends to an administrator's email. There is no reason to store message in DB.
Question. How to:
Use Rails validations in controller, not using model at all, OR
Use validations in model, but without any DB relations
UPD:
Model:
class ContactPageMessage
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :telephone, :email, :message
validates :name, :telephone, :email, :message, presence: true
validates :email, email_format: { :message => "Неверный формат E-mail адреса"}
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
controller:
def sendmessage
cpm = ContactPageMessage.new()
if cpm.valid?
#settings = Setting.first
if !#settings
redirect_to contacts_path, :alert => "Fail"
end
if ContactPageMessage.received(params).deliver
redirect_to contacts_path, :notice => "Success"
else
redirect_to contacts_path, :alert => "Fail"
end
else
redirect_to contacts_path, :alert => "Fail"
end
end
end
you should use model without inheriting from ActiveRecord::Base class.
class ContactPageMessage
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :whatever
validates :whatever, :presence => true
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
Through this you will able to initialize new object and able to call validations on that object.
I think you have a different class name with same name, in your controller code, I can see this :
if ContactPageMessage.received(params).deliver
redirect_to contacts_path, :notice => "Success"
else
if this is your mailer class change its name to ContactPageMessageMailer. you will no loger get that error.
Hope it will help. Thanks
I would still advice you to use model, rails models doesn't have to inherit from ActiveRecord::Base.
For example:
class Contact
include ActiveModel::Validations
attr_accessor :name, :telephone, :email, :message
validates_presence_of :name, :telephone, :email, :message
validates_format_of :email, with: EMAIL_REGEXP
end
and you can use it in your controller with:
contact = Contact.new
# ...
if contact.valid?
# do something
else
# do something else
end
In your model you can add the below which will just set getter and setter method for message and you can have validation on message without having a column in the db
attr_accessor :message
validates :message, presence: true

Resources