attr_accessor not accessible in accept_nested_attributes_for - ruby-on-rails

On my payments page there are certain variables such as card_number that I want to pass from the View to the Model but I do not want to store them in the db. I can usually easily achieve this by simply using attr_accessor but in this case the model is being passed in params through accepts_nested_attributes_for and for some reason the params are not being passed through:
in User.rb i have
has_many :credit_cards
accepts_nested_attributes_for :credit_cards
in the view file i have a nested form field, something like:
blah blah
<h2>Credit card</h2>
<%= f.fields_for :credit_cards do |builder| %>
<%= render "credit_card_fields", :f => builder %>
<% end %>
inside that
<p>
<%= f.label :test %><br />
<%= f.text_field :test %>
</p>
now back in credit_card.rb i have:
attr_accessor :test
before_create :show_me_test_param
private
def show_me_test_param
raise "#{test}"
end
Now the strange thing is that when I try to save a record, it simply returns an empty exception. The param does not seem to have been passed through from User to CreditCard through accepts_nested_attributes_for?
The param being passed in is:
{"email"=>"name#example.com", "password"=>"pass123", "password_confirmation"=>"pass123", "credit_cards_attributes"=>{"0"=>{"test"=>"helllo this is the second attempt", "name_on_card"=>"first lastname", "card_number"=>"987498742897", "card_verification_value"=>"232", "expiry_date"=>"2141"}}}
Does anyone know whats going on? Does accepts_nested_attributes_for work with attr_accessor?

This has messed me up several times in the past! Params for nested objects come to the controller with the key model_name_attributes which gets passed to the new or update_attributes method of the model in the controller.
So you'll need to add :credit_card_attributes to your attr_accessor to allow that key to be passed in.

Related

NoMethodError (undefined method 'aluno' for ActionController:Parameters) - aluno_attributes

I have a class MatriculaForm with some associations (belongs_to and has_many):
class MatriculaForm < Reform::Form
property :aluno, form: PessoaForm
properties :atributos_extras, :mensalidade
#validation
validates :aluno, :dia_vencimento, :empresa, presence: true
end
And the _form.html.erb
<%= form_for #matricula_form do |f| %>
<%= f.fields_for :aluno do |aluno| %>
<%= aluno.text_field :nome %>
<% end %>
<% end %>
On controller, I do
MatriculaForm.new(params[:matricula])
But the initialize reform method raise a error:
NoMethodError (undefined method `aluno' for #<ActionController::Parameters:0x007fe835772a70>
I saw that the parameters become with aluno_attributes key name. But reading the docs, thoses parameters names are accepeted.
I am doing something wrong?
Did you try to whitelist the attributes for association?
association_attributes: [:id .... etc.]
When the method error appears it might be that the association is not correct? Did you correctly set up the belongs_to and has_many
Does this only happen while validating? Does the form save without validation? I am not sure whether the validation can be done that way. May be you want to use validates_association
Please check the docs for correct syntax.

Rails fields_for returning nil

Think I've solved this in the process of writing it. I'll post my solution below.
tl;dr Rails fields_for not generating the expected params.
I have a User class, with the following code:
class User < ActiveRecord::Base
has_one :woojit, dependent: :destroy, validate: true
accepts_nested_attributes_for :woojit
# ... more
end
and a Woojit class
class Woojit < ActiveRecord::Base
belongs_to :user
end
Our UsersController includes this method (we're using the gem Administrate, but it's a subclass of Rails' ApplicationController):
class WoojitsController < Admin::ApplicationController
def new
# ... other stuff
#woojit = #user.build_woojit
end
end
And our user _form.html.erb partial looks like this:
<%= form_for([namespace, page.resource], html: { class: "form" }) do |f| %>
<!-- User fields -->
<fieldset>
<legend>Woojit fields</legend>
<%= f.fields_for #woojit do |ff| %>
<%= render 'woojit_fields', f: ff %>
<% end %>
</fieldset>
<% end %>
So when I submit the form, what I'm hoping to see is a params hash with this subset:
{
"user" => {
"woojit_attributes" => {
"attr_1"=>"Foo", # etc
}
}
}
But what I'm actually getting in the create action is a params hash with this subset:
{
"user" => {
"woojit" => {
"attr_1"=>"Foo", # etc
}
}
}
Ie 'woojit' instead of 'woojit_attributes'. I could hack this in the create action, but that seems like a horrible way of resolving the problem. I want to know why the key is getting mis-named to begin with.
I originally tried the alternative of using the line <%= f.fields_for :woojit do |ff| %> (ie symbol instead of instance var), and not building a Woojit object in the #new action.
The #fields_for guide suggests in the One-To-One section that this should work, but the code in the block was never executed, so the line returned nil - and the woojit params never made it to the create action in any form.
So the problem was apparently that #fields_for behaves differently when given an instance of a model (#woojit), rather than a symbol (:woojit).
In the former instance it generates fields that reference (model name), eg:
<input type="text" name="user[woojit][woojit_attr]" id="user_pledge_pledgor_name" />
In the latter instance it generates fields fields that reference the model attributes, eg:
<input type="text" name="user[woojit_attributes][woojit_attr]" id="user_pledge_attributes_pledgor_name" />
Hope that saves someone some of the frustration I've just been through!

simple_form rails 4, set automatic association

is a little project and I try to associate patient model with consultations. one patient has_many :consultations, in my form I have:
<%= f.association :patient %>
I pass the id parameter from the patient to the action 'new' in this way:
<%= link_to new_consultum_path(:id => #patient.id) %>
And in the view I have:
How can I make that the f.association field take the correspondent patient_id automatically?
How can I be sure that the patient_id is the current patient?
If I want to hide this field is that ok if I put
instead of
Is a better way to do this?
And why in the view shows me # patient:0x007f4e7c32cbd0 ?
thanks for your help.
And why in the view shows me # patient:0x007f4e7c32cbd0
This is a Patient object.
It means you need to call an attribute of this object - EG #patient.name.
--
f.association field take the correspondent patient_id automatically
This might help:
It looks like Organization model doesn't have any of these fields: [
:to_label, :name, :title, :to_s ] so SimpleForm can't detect a default
label and value methods for collection. I think you should pass it
manually.
#app/models/patient.rb
class Patient < ActiveRecord::Base
def to_label
"#{name}"
end
end
Apparently, you need to have either title, name or to_label methods in your model in order for f.association to populate the data.
-
How can I be sure that the patient_id is the current patient?
If you're having to verify this, it suggests inconsistencies with your code's structure. If you need the patient_id to be set as the current patient, surely you could set it in the controller:
#app/controllers/consultations_controller.rb
class ConultationsController < ApplicationController
def create
#consultation = Constultation.new
#consultation.patient = current_patient
#consultation.save
end
end
I can provide more context if required.
You want to associate consultations to patients using fields_for, which is similar to form_for, but does not build the form tags.
It you start with your patient object, you can iterate through the consultation associations binding it to form fields as you go.
it would look something like this
<%= form_for #patient do |patient_form| %>
<% patient_form.text_field :any_attribute_on_patient %>
<% #patient.consultations.each do |consultation| %>
<%= patient_form.fields_for consultation do |consultation_fields| %>
<% consultation_fields.text_field :any_attribute_on_consulatation %>
<% end %>
<% end %>
<% end %>
Sorry, the code may not be exactly right.
Check out the docs for field_for here
You will also have to set accepts_nested_attributes_for consultations on patient. When you set accepts_nested_forms_for, Rails will automatically update the associated consultations object to the patient and save any edits you have made. You DEFINITELY want to use accepts_nested_attributes_for most nested form handling of this type.

Unexpected naming of fields using Reform Form Object with Composition

ANSWER: The model calls were redundant. There should only be one and the last one in this example was the winner. I was misusing the Form Object DSL. :/
I've got a Reform Form object in a Rails 4.1 form that is structured like...
Form Object
class MyForm < Reform::Form
include Composition
model :user
model :user_group
property :name, on: :user_group
property :email, on: :user
end
Controller
# ...
#form = MyForm.new(user: User.new, user_group: UserGroup.new)
# ...
View
<%= form_for(#form) do |f| %>
<%= f.text_field(:name) %>
<%= f.email_field(:email) %>
<% end %>
Rendered HTML
<input type="text" name="user_group[name]" id="user_group_name">
<input type="email" name="user_group[email]" id="user_group_email">
My question is why are the fields seeming to ignore the model mappings and rendering them to the wrong model name? What am I doing incorrectly here?
You can call ::model only once! Once you call it with the correct model (or any name), the rendering will name the fields to whatever ::model you specify. The point about Reform is to hide internals about your model names!

Rails: how to save form data after posting

When I use form_for :model the data is saved when I submit the form.
However when I use form_tag, the data is lost after the form is processed.
I need to use form_tag because I have two models in one form.
Is there a way to save form data with form_tag?
You are making two incorrect assumptions in your question. First, form_tag is not necessary or even recommended for multiple-model forms; Second, form_tag doesn't do anything fundamentally different from form_for, you are most likely not formatting the field names correctly for your controller.
In order to create a form with nested models, you need to use the fields_for helper in conjunction with form_for. The relationship needs to be defined first in the model with accepts_nested_attributes_for. Since you have not given us any information about your models, I will give you a made-up example:
class Person < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
end
class Address < ActiveRecord::Base
belongs_to :person
end
This tells ActiveRecord that the Person model can accept attributes for Address, and will pass along the attributes to the correct model to be created.
<% form_for :person do |p| %>
<% p.fields_for :address do |a| %>
use the a form builder to create
fields for the address model here
<% end %>
<% end %>
chaining the fields_for helper from the p form builder lets the helpers generate attributes in the correct format.
More information: Nested Model Forms
Pretty much the same way as before except you'll need to build the params. You can look at your log to see how params are being sent.
eg.
def create
#silly_hat = SillyHat.new( :name => params[:name], :size => params[:size], :colour => params[:colour] )
if #silly_hat.save
...

Resources