What is wrong with my RABL file? - ruby-on-rails

Rabl is not generating the main object but it is generating it for its children nodes.
I have a Rails-Angularjs project. I want to use RABL to generate the json file. I have read the RABL's documentation and created the Rabl file for the action show, which is not working properly, as explained:
object #ticket => :ticket do
attributes :id, :name, :subname, :description, :width, :height, :qty, :single, :double, :project_id, :material_id, :equipment_id, :location_id, :created_at, :updated_at
end
child :project do
attributes :name, :nickname, :project_number
end
child :job_state do
attributes :color, :name
end
child :location do
attributes :name
end
child :local_equipment do
attributes :name
end
child :local_material do
attributes :name
end
IF I remove 'do' and 'end' on the object #ticket, It throws the error: 'wrong number of arguments (1 for 0)'.
If I leave them, it doesn't show any ticket's field name. As shown below:
{"ticket":{"project":{"name":"Information Security Conference 2017","nickname":"infosecon17","project_number":1000},"job_state":{"color":"red","name":"printed"},"location":{"name":"Grand prairie graphics"},"local_equipment":null,"local_material":null}}
Any help will be appreciated.

If the issue is not with your Angular, from rails side, this is the structure that works for me. Check that your Tickets#show file is here and named: app\views\tickets\show.json.rabl and contains only
object #ticket
attributes :id, :name, :subname, :description, :width, :height, :qty, :single, :double, :project_id, :material_id, :equipment_id, :location_id, :created_at, :updated_at
for the children you would have separate files like this:
app\views\tickets\projects.json.rabl which will contain
collection #projects
extends "projects/show"
but also confirm that attributes match your schema anyway.

I think you're on the right track. I would make one small change. You don't need to wrap the #ticket attributes in a block. You can just specify object #ticket and go from there.
object #ticket
attributes :id, :name, :subname, :description, :width, :height, :qty, :single, :double, :project_id, :material_id, :equipment_id, :location_id, :created_at, :updated_at
child :project do
attributes :name, :nickname, :project_number
end
child :job_state do
attributes :color, :name
end
child :location do
attributes :name
end
child :local_equipment do
attributes :name
end
child :local_material do
attributes :name
end

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 - Object attributes accessible individually but not by inspect method

Sorry I'm new to rails but can't wrap my head around this one.
I have an Order object with various attributes - no references
In my controller I can print out the attributes individually via their attr_accessor and see them in the console via puts.
But when I call .inspect they are all nil! any suggestions?
class Order < ApplicationRecord
attr_accessor :name, :email, :phone, :date, :dessert_type, :size, :quantity, :dessert, :comments, :total
validates :name, :date, :quantity, presence: true
validates :quantity, numericality: { only_integer: true, greater_than: 0}
validate :contact_provided?
private
def contact_provided?
if :email.blank? || :phone.blank?
errors.add(:base, "Please provide either phone or email so we can contact you!")
end
end
end
Controller
def create_order
puts "create_order object"
#order = Order.new order_params
if #order.valid?
puts #order.inspect
#everything is null here
#order.attributes.each do |attr_name, attr_value|
puts "#{attr_name}: #{attr_value}"
end
#this prints out fine!
puts "dessert: #{#order.dessert}"
end
end
Parameters
Parameters: {"utf8"=>"✓", "authenticity_token"=>"randomtoken", "order"=>{"name"=>"jim", "email"=>"test#email.com", "phone"=>"12345678", "dessert_type"=>"Cake", "size"=>"25.0", "dessert"=>"Chocolate Caramel", "date"=>"2018-04-15", "quantity"=>"1", "comments"=>""}, "commit"=>"Submit Order"}
Any insight much appreciated!
That's because this line:
attr_accessor :name, :email, :phone, :date, :dessert_type, :size, :quantity, :dessert, :comments, :total
is overriding the Order attributes in the way Rails works with them. As working with Rails you don't need that declaration, so you can remove them as attr_accessor.
As Order is an ActiveRecord model, then the getters and setters are already generated by ActiveRecord for all of your object attributes.
What you're doing right now is defining all of your attributes, with the attr_accessor as virtual attributes which are attributes on the model that don't persist in the database, just "an attribute not corresponding to a column in the database".

Rails activeadmin save data in associated table

I have one table for Products and the product can either be in the interior or exterior or both. So I created another table to save the Products location. Now when admin adds the product I have provided the option to select the location(s) the product can be in, but when it is posted the code says the field can't be blank because of the validation. I am not sure what I am missing or the approach is wrong.
The product model:
class Product < ApplicationRecord
validates :name, presence: true
has_many :product_locations
accepts_nested_attributes_for :product_locations
end
The product location model:
class ProductLocation < ApplicationRecord
enum locations: [:exterior, :interior]
validates :location, presence: true
validates :product_id, presence: true
belongs_to :product
end
The ActiveAdmin file for Product:
ActiveAdmin.register Product do
permit_params :name, product_locations_attributes: {}
actions :all, except: [:show, :destroy]
filter :name
index do
column 'Product Name', :name
actions
end
form do |f|
f.semantic_errors *f.object.errors.keys
f.inputs "Products" do
f.input :name
end
f.has_many :product_locations do |location|
location.inputs "Locations" do
location.input :location, as: :select, multiple: true, collection: ProductLocation.locations.keys
end
end
f.actions
end
controller do
def scoped_collection
Product.where(user_id: nil)
end
end
end
I get a multi-select for the locations which has "Interior" and "Exterior" for selection, but it says the field can't be blank when I select the location and submit the form
The error on save click I get is:
Location can't be blank
The params that get posted are:
Parameters: {"utf8"=>"✓", "product"=>{"name"=>"Test Product", "product_locations_attributes"=>{"0"=>{"location"=>["0", "1"]}}}, "commit"=>"Create Product"}
First, the permit attributes should be,
product_locations_attributes: [:id, :location]
Then, in your form
location.input :location, as: :select, multiple: true, collection: ProductLocation.locations.keys
Since ProductLocation.locations is an array, array.keys is an invalid method.
So, use directly
location.input :location, as: :select, multiple: true, collection: ProductLocation.locations.map { |n| [n,n] }
To store an array of multiple values take serialize field as an array,
class ProductLocation < ApplicationRecord
enum locations: [:exterior, :interior]
serialize :location, Array
validates :location, presence: true
validates :product_id, presence: true
belongs_to :product
end
Note: Inorder to get the serialize work, you need to have the dataType of the location as a text. If it is not text run a migration to change to text data type
Reason for text field: Rails will convert all those object into plain text when storing in database

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_admin new model configuration

I just installed Rails Admin, and I want to have a model called "Business". Through Rails Admin, I want to be able to create new businesses, edit them, etc. I've written the code for the model already, but I don't know how to use the rails_admin.rb file to configure the model. Here's what I have so far.
Business.rb
class Business < ActiveRecord::Base
#attr_accessible :title, :body
attr_accessible :name, :website, :phone, :manager, :email, :type, :mobile,
:foursquare, :facebook, :yelp, :google
validates_presence_of :name, :website, :phone, :manager, :email, :type, :mobile,
:foursquare, :facebook, :yelp, :google
def type_enum
['Agencies', 'Automotive', 'Contractor', 'Country Club', 'Entertainment',
'Restaurant and Bar', 'Funeral', 'Furniture', 'Healthcare', 'Laundry', 'Legal',
'Office', 'Other', 'Personal Trainer', 'Real Estate', 'Religious', 'Retail',
'Salon', 'Wedding Hall']
end
def mobile_enum
['Yes', 'No']
end
def foursquare_enum
['Yes', 'No']
end
def facebook_enum
['Yes', 'No']
end
def yelp_enum
['Yes', 'No']
end
def google_enum
['Yes', 'No']
end
end
What should I include in my rails_admin.rb? Ideally I want to have text fields to enter data for all the fields, except for the ones for which I created 'enum' methods - these should be dropdown menus. I'm new to Rails Admin, and relatively new to rails so I appreciate your help greatly.
Thanks!
Your configuration will look something like this:
RailsAdmin.config do |config|
config.model Business do
list do
field :name
field :website
end
show do
# e.g. include_all_fields
end
edit do
# e.g. include_all_fields
# exclude_fields :website
end
end
end
You can read additional field configuration at the RailsAdmin field configuration wiki page.

Resources