foreign key removed on new/build - ruby-on-rails

hopefully someone can help me understand why this is happening. i setup the following instances...
#product = Product.find(params[:id])
#new_image = #product.images.new
when i debug #new_image, it correctly has the foreign key set.
--- !ruby/object:Image
attributes:
product_id: 1
however, when saving, the product_id was not being set. that's when i noticed that also in that debug info, was this...
changed_attributes:
product_id:
basically nulling my foreign key. same thing if i use build. why isnt that instance not holding onto the foreign key?
UPDATE:
to make things simpler, even if i just output debug Product.find(1).images.new in my view, i get:
!ruby/object:ProductImage
attributes:
created_at:
product_id: 1
updated_at:
attributes_cache: {}
changed_attributes:
product_id:
destroyed: false
marked_for_destruction: false
new_record: true
previously_changed: {}
readonly: false

The way I understand it, your product's show view contains a form to post to the images controller. When you create the #new_image variable based on #product in your view, it properly assigned the product_id to the image. However, this does NOT persist when you post your form.
You have two options. The simplest would be to just add a <%= f.hidden_field :product_id %> item to your form, that way the product_id actually gets posted to Image#create. Alternatively, you could create a nested resource and do a <%= form_for [#product, #new_image] do |f| %> instead of the <%= form_for #new_image %> that you're probably using right now, and then in your create method do:
#product = Product.find(params[:product_id])
#new_image = #product.images.new(params[:image])

Related

Error in displaying data in Rails

I am trying to display data in the view for a member's profile. When I run the inspect option on the variable, it prints out all of the data on the profile variable. But, when I have it only call a column, I get an error.
I run the same code on a different variable and it prints out; so, I am a bit confused on what is going on. Is it because the Active Record has a relation? Here is the code:
profiles_controller.rb
def show
#show_page = params[:id]
#member = current_member
#profile = Profile.where(member_id: current_member.id)
end
show.html.erb
<hr>
<%= #show_page.inspect %>
<hr>
<%= #profile.inspect %>
<hr>
<%= #member.inspect %>
<hr>
<p>
<strong>Member ID:</strong>
<%= #member.id %>
</p>
View in Browser
"8"
#<ActiveRecord::Relation [#<Profile id: 6, f_name: "Test", l_name: "Member", u_name: "testing", security: "10", private: "1", avatar: nil, birthday: nil, phone: nil, address1: nil, address2: nil, city: nil, state: nil, zip: nil, long: nil, lat: nil, facebook: nil, twitter: nil, instagram: nil, pinterest: nil, googleplus: nil, motto: nil, created_at: "2017-12-23 05:15:53", updated_at: "2017-12-23 05:15:53", member_id: 8>]>
#<Member id: 8, email: "testing#t.com", created_at: "2017-12-19 20:02:34", updated_at: "2017-12-23 05:15:37">
Member ID: 8
Now, when I add the following code into the show page, I get an error.
show.html.erb
<p>
<strong>User Name:</strong>
<%= #profile.u_name %>
</p>
ERROR
Showing /Users/topher/Dropbox/railsapps/~sandboxes/temporary/app/views/profiles/show.html.erb where line #21 raised:
undefined method `u_name' for #<Profile::ActiveRecord_Relation:0x00007fcb2583b920>
Did you mean? name
I am just confused on if there is a different way that I need to be calling the data found in the variable. The only difference between the #member and #profile print outs that I can see is the #<ActiveRecord::Relation [ prefixed to #profile. Does this mean that I need to call the information differently?
#where is query method, and returns records matching query conditions wrapped in ActiveRecord::Relation object. Which explains why you are getting this error. To resolve it, you need to change it to:
#profile = Profile.where(member_id: current_member.id).first
Which will return first record matching given member id to #profile instead of ActiveRecord::Relation object.
However, you must use a finder method in case you want to find a particular record. So better and cleaner approach would be:
#profile = Profile.find_by(member_id: current_member.id)
Change the line in profiles_controller.rb like
#profile = Profile.find_by(member_id: current_member.id)
As you are using where clause on Profile it will return an array of ActiveRecord::Relation objects. But you need a single #profile object not #profiles object. Thats you should use find_by method instead of where clause.
I think the problem is your line on the show method
#show_page = params[:id]
You need to indicate model where to contain the params id
#show_page = Model.find(params[:id]) #=> model is your model which you can using
I think will help

Rails does not add "field_with_errors' wrapper for fields created with fields_for

What I am trying to do is namespace a custom-made object in a dyamically-built form by passing it to fields_for. The object is not an ActiveRecord model and I am doing my best to make it quack like one with minimal effort.
Everything works with the exception of the "field_with_errors" wrapper which does not get added. Any ideas on how to make that part work?
I have a form which submits data to FormResponses model and runs its validations. Once the validations are run, the form_response object contains the namespaced form data as well as errors:
[1] pry(#<#<Class:0x007fe743c64418>>)> form_response
=> #<FormResponse:0x007fe74d30aa98
id: nil,
data: {"name_prefix"=>"Mr.", "first_name"=>"", "middle_initial"=>"", "last_name"=>"", "name_suffix"=>"", "title"=>""},
form_id: 2,
created_at: nil,
updated_at: nil>
[2] pry(#<#<Class:0x007fe743c64418>>)> form_response.errors
=> #<ActiveModel::Errors:0x007fe74d309080
#base=
#<FormResponse:0x007fe74d30aa98
id: nil,
data: {"name_prefix"=>"Mr.", "first_name"=>"", "middle_initial"=>"", "last_name"=>"", "name_suffix"=>"", "title"=>""},
form_id: 2,
created_at: nil,
updated_at: nil>,
#messages={:will_attend=>["Please indicate your attendance"], :first_name=>["Please provide your first name"]}>
# this is what I pass to the form_for builder
[3] pry(#<#<Class:0x007fe743c64418>>)> form_response.form_data
=> #<OpenStruct name_prefix="Mr.", first_name="", middle_initial="", last_name="", name_suffix="", title="">
I display this object in the following way:
form.html.slim
= form_for form_response, url: "", authenticity_token: false, html: {class: "form"} do |ff|
= hidden_field_tag "authenticity_token", csrf_token
= ff.hidden_field "_prefilled_status", value: is_prefilled.prefilled
= ff.hidden_field "_prefilled_condition", value: is_prefilled.condition
= fields_for :form_data, form_response.form_data do |f|
= ff.hidden_field "form_id", value: form_response.form_id
# form_components holds the form field tree data which lets us create the form dynamically
- form_components.each do |component|
= render partial: "./#{component.kind}", locals: { f: f, component: component }
having each of the fields processed by a partial corresponding to the field type, for example:
_text.html.slim
li class=component.container_css
= f.label component.field_name, component.label, class: concat_and_trim('desc', component.required_class)
span = f.text_field component.field_name, component.tag_options_with_css
The issue is that the fields created with f.field_name do not get the "field_with_errors" wrapper when errors are present.
Given that the errors are on the form_response active record model passed on to the "ff" form builder, shouldn't they trigger the wrapping on the form_for objects?
The form_for fields retainthe submitted values if I include form_response.form_data which contains the form field values submitted under the form_data namespace, like this:
= fields_for :form_data, form_response.form_data do |f|
If I omit the form_response.form_data part, the fields get cleared on submit
= fields_for :form_data do |f|
Which means that the fields_for uses that information to prefill the fields. How do I pass the error information to fields_for so that the fields get the error class wrapper?

Rails pass object through form select

In my form:
<%= f.select :user, User.all %>
This generates a select with a collection of all users.
When I hit submit, it's currently passing the object as a string, looks like below:
[3] pry(#<PermissionFormsController>)> params[:permission_form][:user]
=> "John Doe <John.Doe#foo.com> - Bar (something)"
and
[4] pry(#<PermissionFormsController>)> params[:permission_form][:user].class
=> String
I'd like to get the object rather, like current_user
[5] pry(#<PermissionFormsController>)> current_user
=> Homer Simpson <homer#gmail.com> - Foo (admin)
Which is an object of class User:
[6] pry(#<PermissionFormsController>)> current_user.class
=> User(id: integer, status: string, ...)
Is there a way to achieve this?
You cannot pass Ruby objects directly from a form to the server, only strings. Your controller is responsible for turning this data into actual models. This is normally done by passing the object id and calling YourModel.find in the controller.
So you need to change your form like this:
<%= f.select :user_id, User.all.map{|u| [u.to_s, u.id]} %>
And then in your controller's action:
user = User.find(params[:permission_form][:user_id])
Hope this helps.

Cannot pass parameters to controller

I have the following haml code in index.haml
%h1.content-header{id: 'content-header'} HEADER
%section.form
%form.standard{action: some_path, method: 'get'}
%fieldset.search{'aria-labelledby' => 'content-header'}
%input{type: 'search', name: 'name', placeholder: 'something', role: 'textbox'} -----(6)
%fieldset.input-actions
%input.primary-action{type: 'submit', value: 'search' , name: 'invokeSearch'}
I have the following in my controller
def index
Rails.logger.debug "#{params[:name]}"
unless #invalid_characters
unless params[:name].blank?
....
....
....
The issue is if i change the name: 'name' in line 6 to say name: 'test' .... params[:test] is always blank in my controller. But if i use name: 'name' , params[:name] seems to work . No clue what i am doing wrong here
If you are using rails you should probably benefit from using one of the form helpers for generating the form. For example forms_for that makes you access things in your model directly. It may look like this.
= forms_for #thing do |f|
= f.text_field :name
= f.text_field :test
= f.submit
In this case there will be a map for the model instance in the params map. Something like
params[:thing][:name]
or
params[:thing][:test]
you can take that map and pass it into a model to create or update it. If you don't want the tight coupling with the model there is the form_tag method that does much the same thing except you need to be more explicit in what value goes where. And fields ends up directly in params instead of in a model hash.
To see how your params come in you can use the inspect method.
puts "params: #{params.inspec}"
or install pry to set a break point with
binding pry
Some ideas. Hope it works out for you. I think you should start with trying to use the rails forms helpers and it will probably sort itself out.

rails controller, undefined method error - based off edge guides

I'm building a fairly simple recipe site to learn RoR, and I've been following the getting started guide, except that I've exchanged posts for recipes and comments for ingredients.
I got all the way to deleting a comment (ingredient) http://edgeguides.rubyonrails.org/getting_started.html#deleting-comments
now i'm getting an error
undefined method `recipe' for #
The line which in the partial which is causing the problem is here
<%= link_to 'Delete Ingredient', [ingredient.recipe_id, ingredient],
:confirm => 'Are you sure',
:method => :delete %>
The controller method (which I don't think has any effect, but I'm not completely sure) is
def destroy
#recipe = Recipe.find(params[:recipe_id])
#ingredient = #recipe.ingredient.find(params[:id])
#ingredient.destroy
redirect_to post_path(#recipe)
end
I use 'recipe_id' in the link_to because when I output the debug, it doesn't have a 'recipe' attribute, but has a recipe_id attribute.
The output of the debug is
--- !ruby/object:Ingredient
attributes:
id: 3
ingredient: testing
amount: 10
measure: "10"
description: "10"
recipe_id: 2
created_at: 2010-09-06 22:16:17.599217
updated_at: 2010-09-06 22:16:17.599217
attributes_cache: {}
changed_attributes: {}
destroyed: false
marked_for_destruction: false
new_record: false
previously_changed: {}
readonly: false
I'm assuming the [ingredient.recipe_id, ingredient] is simply a hash of the variables??
Is that correct? Am I coming at this from the wrong angle?
Shot in the dark, are your associations proper ? Kinda like:
class Ingredient < ActiveRecord::Base
belongs_to :recipe
...
That will give you
#ingredient.recipe
Hope that helps.

Resources