I have a Client resource with 2 types: Person and Company.
routes.rb:
resources :clients
resources :people, :controller => "clients", :type => "Person"
resources :companies, :controller => "clients", :type => "Company"
clients_controller:
def new
@client = Client.new()
@client.type = params[:type]
end
def create
@client = current_partner.clients.new(client_params)
if @client.save
redirect_to clients_path
...
end
...
private
def client_params
params.require(:client).permit(:type, :partner_id, :name, :email, :phone, :cui, :registration_id, :address)
end
def find_client
@client ||= Client.find(params[:id])
end
client.rb
class Client < ActiveRecord::Base
validates_presence_of :type
CLIENT_TYPES = ['Person', 'Company']
end
person.rb
class Person < Client
validates_presence_of :name, :email, :phone
end
compay.rb
class Company < Client
validates_presence_of :name, :email, :cui, :registration_id, :phone
validates_uniqueness_of :cui, :registration_id, uniqueness: {scope: :partner_id}
end
The problem is when I'm trying to edit a client's details and I submit the changes, I get param is missing or the value is empty: client. The route from where I'm getting this error is .../companies/3.
Any help on this noobie question? Thanks!
You can disguise your inherited model to it's parent before the permit action by
def client_params
if params.has_key? :person
params[:client] = params.delete :person
elsif params.has_key? :company
params[:client] = params.delete :company
end
params.require(:client).permit(...)
end
Its just renaming the model's key in the params hash, and does the trick.
Models
I think you're not using STI's properly
STI's are for Model
s, not controllers
. As per the MVC programming pattern, your Models
handle all the data-construction methodology. Your controllers are used as an interim between your user
inputs & your views
:
This means that if you want to use or create STI-driven functionality, you'll be best just using the backend classes
for it (instead of manually passing type
etc):
#app/models/person.rb
Class Person < Client
...
end
#app/models/company.rb
Class Company < Client
end
#app/models/client.rb
Class Client < ActiveRecord::Base
end
This will give you the ability to do this:
#config/routes.rb
resources :clients
resources :people, controller: "clients", type: "Person"
resources :companies, controller: "clients", type: "Company"
#app/controllers/clients_controller.rb
Class ClientsController < ApplicationController
def create
model = get_model(params[:type])
@model = model.new(model_params)
@model.save
end
private
def get_model type
return type.singularize.titleize.camelize.constantize
end
def model_params
params.require(params[:type].to_sym).permit(:client, :model, :attributes)
end
end
This will the various STI Model
that you've set by accessing /people
or /companies
, and then give you the ability to save data to it (which will save to the Client
model with type
set, of course)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With