Rails_admin new model configuration - ruby-on-rails

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.

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.

What is wrong with my RABL file?

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

Rails 4 strong params get permit from nested model

There are several questions for strong params, but I couldn't find any answer for achieving my goal. Please excuse any duplicates (and maybe point me in the right direction).
I'm using strong params in a model that has several 'has_one' associations and nested attributes with 'accepts_attributes_for'.
In my routes I have: (updated for better understanding)
resources :organisations do
resources :contact_details
end
So, i.e. for one associated model I have to use
def organisation_params
params.require(:organisation).permit(:org_reference, :supplier_reference, :org_type, :name, :org_members, :business, :contact_person, contact_detail_attributes: [:id, :contactable_id, :contactable_type, :phone, :fax, :mail, :state, :province, :zip_code, :street, :po_box, :salutation, :title, :last_name, :first_name, :description])
end
This works, but I have to retype all my permitted params for each associated model. When I modify my permitted attributes for contact_details , I have to change it in several locations (every model that has the polymorphic association).
Is there a way to get the parameter whitelist of contact_details and include it into the parent whitelist?
Something like:
def organisation_params
my_params = [:org_reference, :supplier_reference, :org_type, :name, :org_members, :business, :contact_person]
contact_params = #get permitted params, that are defined in contact_details_controller
params.require(:organisation).permit(my_params, contact_params)
end
I don't want to workaround security, but I had already defined the permitted attributes for the contact_details and don't want to repeat it in every associated "parent" model (because it's exhausting and very prone to stupid mistakes like omitting one attribute in one of several parent models).
Use a method defined inside ApplicationController, or a shared module:
ApplicationController:
class ApplicationController
def contact_details_permitted_attributes
[:id, :contactable_id, :contactable_type, ...]
end
end
class ContactDetailsController < ApplicationController
def contact_details_params
params
.require(contact_details)
.permit(*contact_details_permitted_attributes)
end
end
class OrganisationsController < ApplicationController
def organisation_params
params
.require(:organisation)
.permit(:org_reference, ...,
contact_detail_attributes: contact_details_permitted_attributes)
end
end
Shared module:
module ContactDetailsPermittedAttributes
def contact_details_permitted_attributes
[:id, :contactable_id, :contactable_type, ...]
end
end
class ContactDetailsController < ApplicationController
include ContactDetailsPermittedAttributes
def contact_details_params
params
.require(contact_details)
.permit(*contact_details_permitted_attributes)
end
end
class OrganisationsController < ApplicationController
include ContactDetailsPermittedAttributes
def organisation_params
params
.require(:organisation)
.permit(:org_reference, ...,
contact_detail_attributes: contact_details_permitted_attributes)
end
end
Rails has even dedicated directories for shared modules, concerns inside app/controllers and app/models; indeed, in your case you should use app/controllers/concerns
I don't see why not. In your ApplicationController you could have
def contact_attributes
[:id, :contactable_id, :contactable_type, :phone, :fax,
:mail, :state, :province, :zip_code, :street, :po_box,
:salutation, :title, :last_name, :first_name, :description]
end
Then in your organisation_params
def organisation_params
my_params = [:org_reference, :supplier_reference, :org_type, :name, :org_members, :business, :contact_person]
params.require(:organisation).permit(*my_params, contact_detail_attributes: contact_attributes)
end
In some other location you might do...
def contact_params
params.require(:contact).permit(*contact_attributes)
end

ActiveModel::MassAssignmentSecurity::Error in CustomersController#create (attr_accessible is set)

In my controller, I've got error when create action and try create model [can't mass-assignment], but
in my spec, my test of mass-assignment model its pass!?!
My Model:
class Customer < ActiveRecord::Base
attr_accessible :doc, :doc_rg, :name, :birthday, :name_sec, :address, :state_id, :city_id, :district_id,
:customer_pj, :is_customer, :segment_id, :activity_id, :person_type, :person_id
belongs_to :person , :polymorphic => true, dependent: :destroy
has_many :histories
has_many :emails
def self.search(search)
if search
conditions = []
conditions << ['name LIKE ?', "%#{search}%"]
find(:all, :conditions => conditions)
else
find(:all)
end
end
end
I`ve tired set attr_accessible in controller too, in my randomized way.
the Controller:
class CustomersController < ApplicationController
include ActiveModel::MassAssignmentSecurity
attr_accessible :doc, :doc_rg, :name, :birthday, :name_sec, :address, :state_id, :city_id, :district_id, :customer_pj, :is_customer
autocomplete :business_segment, :name, :full => true
autocomplete :business_activity, :name, :full => true
[...]
end
The test, my passed test
describe "accessible attributes" do
it "should allow access to basics fields" do
expect do
#customer.save
end.should_not raise_error(ActiveModel::MassAssignmentSecurity::Error)
end
end
The error:
ActiveModel::MassAssignmentSecurity::Error in CustomersController#create
Can't mass-assign protected attributes: doc, doc_rg, name_sec, address, state_id, city_id, district_id, customer_pj, is_customer
https://github.com/megabga/crm
1.9.2p320
Rails 3.2
MacOS
pg
my bad, in my controller its setting an oldest class. Then old class don`t have attributes passing in parameters. Sorry!

Rails - How to declare attr_accessible for multiple roles without duplication

Is there a way to declare attr_accessible for multiple roles without a ton of duplication?
If I have several user roles, and each role is allowed to edit a different subset of attributes, here's what my attr_accessible declaration looks like:
attr_accessible :first_name, :last_name, :active, :as => :admin
attr_accessible :first_name, :last_name, :as => :manager
attr_accessible :first_name, :last_name, :as => :guest
I'd like to either
A) define an array of accessible attributes that can be shared among
different roles or
B) define an array of roles than can access the same
attributes
Is this possible?
I just spent a long time trying to figure out the best way to do this. It seemed strange that the rails folk would expect you to duplicate a whole bunch of code!
After some digging around in the rails source, it turns out you can simply pass an array to assign attributes to multiple roles at once (:default being the default Active Record role)
attr_accessible :name, :email, :as => [ :default, :admin ]
attr_accessible :featured, :as => :admin
No messy ruby arrays in your model!
All ruby code is still just ruby code... and is thus infinitely hackable. eg
ROLES = [:admin, :manager, :support, :user, :guest]
ACTIVE_ROLES = [:admin, :support]
ROLES.each do |role|
fields = [:first_name, :last_name]
fields += [:active] if ACTIVE_ROLES.include?(role)
attr_accessible *fields, :as => role
end
Did you try something like:
COMMON_FIELDS = [:first_name, :last_name]
attr_accessible COMMON_FIELDS | [:active, :as => :admin]
attr_accessible COMMON_FIELDS | [:as => :manager]
attr_accessible COMMON_FIELDS | [:as => :guest]
Another possible way (untested):
attr_accessible :first_name, :last_name
ADMIN_ACCESSIBLE = [:active]
MANAGER_ACCESSIBLE = []
GUEST_ACCESSIBLE = []
protected
def mass_assignment_authorizer
if role == :all
self.class.protected_attributes
else
super + (eval("#{role}_accessible".upcase) || [])
end
end

Resources