Reputation: 2195
I'm trying to implement a has_one relationship through a basic form and am getting completely stuck.
I seem to have tried huge numbers of combinations of things in controllers and forms but don't seem to be getting anywhere.
I have a phone number for which I use an external service populated by an api.
Eventually I would like to have all the phone numbers of this type set up for this, but right now I'd be happy with getting just one working.
parent.rb
has_one :clever_phone
And a phone model
clever_phone.rb
attr_accessible :number, :parent_id, :prefix, :country_iso
belongs_to :parent
Controller
clever_phones_controller
def new
@parent = Parent.find(params[:parent_id])
@clever_phone = @parent.build_clever_phone
def create
@parent = Parent.find(params[:parent_id]
@clever_phone = Parent.create_clever_phone(params[:clever_phone])
View I really don't want to do a nested form from the parent here as I have some complicated code which generates information used in the creation through an api that sits, correctly I think, in the clever_phones_controller
@simple_form_for @clever_phone do |f|
= f.input :country_iso, as: :country, :iso_codes => true, priority: ["gb"]
= f.input :prefix
= f.submit
Routes
resources :parent do
resource :clever_phone
end
My issue is that the params for @parent don't seem to be being passed to the create method in the controller and thus I get a 'Can't find parent without ID' error
If I try it as a nested form I get NoMethodError undefined method 'parent_clever_phones_path' When in fact I've not used that, only parent_clever_phone_path (note the absence of plural).
I'm sure this should be really simple but I've stared at it for hours now and am at the end of my tether...
Any ideas?
Upvotes: 2
Views: 174
Reputation: 2195
Right: Worth putting in the solution that finally worked. Thanks to Rich Peck for getting me halfway there... model
parent.rb
has_one :clever_phone
clever_phone.rb
belongs_to :parent
view
simple_form_for @clever_phone, url: parent_clever_phone_path(@parent) do |f|
-----
f.input :parent_id, :value: @parent.id
-----
routes
resources :parent do
resource :clever_phone
controller
def new
....
@parent = Parent.find(params[:parent_id])
@clever_phone = @parent.build_clever_phone
def create
@parent = Parent.find(params[:parent_id]
@clever_phone = CleverPhone.new(params[:clever_phone]
Unless you do build_clever_phone the parent_id won't populate. I couldn't get @parent.create_clever_phone to work, but this seemed to do the trick...
Hope that saves somebody a days work...
Upvotes: 1
Reputation: 76774
Okay, there are several issues which you need to contend:
--
Variable
The reason why @parent
params are not being passed is because you've not included them in your form. This is where nesting your forms would come in very handy - passing your parent
params, and your clever_phone
params in a single call
Since you don't want to do this, I would recommend at least populating a hidden field
with the parent_id
that the clever_phone
is associated with:
#app/views/clever_phones/new.html.erb
= simple_form_for @clever_phone do |f|
= f.input :parent_id, as: :hidden, value: params[:parent_id]
= f.input :country_iso, as: :country, :iso_codes => true, priority: ["gb"]
= f.input :prefix
= f.submit
--
Route
Alternatively, you have to make sure you're able to create the correct route for your form (as I think the @parent = Parent.find params[:parent_id]
is not being called on your create
method:
#app/views/clever_phones/new.html.erb
= simple_form_for [@parent, @clever_phone] do |f|
This will give you the ability to point your create
action to the nested version of your route; hence providing the parent_id
param for you
--
Having written, this I don't think it will address the core of your issue. If you need more information, please write a comment & I'll happily work to create a more appropriate answer!
Upvotes: 1