form fields not appearing inside the object hash - ruby-on-rails

I've created a Rails form to create an "event" (that's nested inside a group resource) with the following fields. The fields when and exactwhen (extremely poorly named, i know, I'm just creating a quick demo) are meant to refer to date and time
<%= form_for [#group, #event], url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
<%= label_tag(:title, "Event Title") %>
<%= f.text_field :title %>
<%= label_tag(:description, "Event Description") %>
<%= f.text_area :description, size: "60x12" %>
<%= label_tag(:address, "Address") %>
<%= f.text_field :address %>
<%= label_tag(:when, "When") %>
<%= text_field_tag(:when) %>
<%= label_tag(:exactwhen, "exactwhen") %>
<%= text_field_tag(:exactwhen) %>
<%= f.submit "Create" %>
<% end %>
These fields exist on the event model in the database
create_table "events", force: true do |t|
t.string "title"
t.text "description"
t.string "address"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "group_id"
t.date "when"
t.time "exactwhen"
end
However, when I submit the form, you'll notice that when and exactwhen are not contained in the event hash
Parameters: {"utf8"=>"✓", "authenticity_token"=>"5kkL2a3yDHEINSqSg+1cXd708GtRPgymbKmASs+eih8=", "event"=>{"title"=>"First Wankers Meeting", "description"=>"get drunk", "address"=>"57 Robert Crescent"}, "when"=>"08/23/2013", "exactwhen"=>"12", "commit"=>"Create", "group_id"=>"38"}
and the data for when and exactwhen are not getting inserted into the record
Group Load (0.6ms) SELECT "groups".* FROM "groups" WHERE "groups"."id" = $1 LIMIT 1 [["id", "38"]]
(0.2ms) BEGIN
SQL (2.0ms) INSERT INTO "events" ("address", "created_at", "description", "group_id", "title", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["address", "57 Robert Crescent"], ["created_at", Sat, 03 Aug 2013 16:38:30 UTC +00:00], ["description", "get drunk"], ["group_id", 38], ["title", "First Wankers Meetup"], ["updated_at", Sat, 03 Aug 2013 16:38:30 UTC +00:00]]
I'm assuming that the form data for when and exactwhen are not getting inserted into the db because they're not in the event hash. If that's the case, can you explain why, or explain how I could otherwise correct this problem?
This is the create action in the events_controller.rb
def create
#group = Group.find(params[:group_id])
#event = #group.events.build(event_params)
if #event.save
....
private
def event_params
params.require(:event).permit(:title, :description, :when, :exactwhen, :address)
end

You are using form_for. Change all your fields (and labels) to normal fields, not tag fields. So change text_field_tag to text_field.
If you do that, everything should work. Then all the attributes should be in the right params hash.
For more info check out form_for in the rails api docs.

Use f.text_field instead of text_field_tag like you do with the first few form fields

Related

Unpermitted parameter in HABTM relationship

So I'm building an HABTM relationship and I always get this error back in the terminal when I submit the form:
Unpermitted parameter: :color_ids
No other errors. The app works fine, except that the associations are always an empty array.
Schema.rb:
create_table "colors", force: :cascade do |t|
t.string "color"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "colors_products", id: false, force: :cascade do |t|
t.integer "color_id", null: false
t.integer "product_id", null: false
end
create_table "products", force: :cascade do |t|
t.string "title"
t.decimal "price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
color.rb:
class Color < ApplicationRecord
has_and_belongs_to_many :products
end
product.rb:
class Product < ApplicationRecord
has_and_belongs_to_many :colors
end
_form.html.erb:
<div class="field">
<%= form.label :color %>
<%= form.collection_select :color_ids, Color.all, :id, :color, {:multiple => true}, class: "input-field-data" %>
</div>
product_controller.rb
def product_params
params.require(:product).permit(:title, :price, color_ids: [])
end
changing the param hash from color ids to color_ids:[:id, :color]
makes no difference.
This example is obviously just something I recreated to see if I did something else wrong in my original app, probably also easier to debug.
Any ideas what's wrong with that setup? I actually have another project with the exact same setup and it works? Because of that, I think that I'm missing something, but I don't actually find anything wrong with my code.
Thanks in advance for any input!
Edit:
As requested, here is the terminal log when submitting a new product with a collection_select as shown above:
Started POST "/products" for 127.0.0.1 at 2019-02-10 14:02:59 +0100
Processing by ProductsController#create as HTML
Parameters: {"authenticity_token"=>"+f+GJaN58M029eGICvMqlwtjYB4Qmv/KNBY0OnymrxyFy+zNYXKfZtCXR0NM3kLY16QIzfLb+takhNjgIQXeEw==", "product"=>{"title"=>"abc", "price"=>"9.99", "color_ids"=>"1"}, "commit"=>"Create Product"}
Unpermitted parameter: :color_ids
(0.1ms) begin transaction
↳ app/controllers/products_controller.rb:30:in `block in create'
Product Create (1.0ms) INSERT INTO "products" ("title", "price", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["title", "abc"], ["price", 9.99], ["created_at", "2019-02-10 13:02:59.634965"], ["updated_at", "2019-02-10 13:02:59.634965"]]
↳ app/controllers/products_controller.rb:30:in `block in create'
(1.1ms) commit transaction
↳ app/controllers/products_controller.rb:30:in `block in create'
Redirected to http://localhost:3000/products/15
Completed 302 Found in 14ms (ActiveRecord: 2.3ms | Allocations: 3885)
Started GET "/products/15" for 127.0.0.1 at 2019-02-10 14:02:59 +0100
Processing by ProductsController#show as HTML
Parameters: {"id"=>"15"}
Product Load (0.4ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT ? [["id", 15], ["LIMIT", 1]]
↳ app/controllers/products_controller.rb:67:in `set_product'
Rendering products/show.html.erb within layouts/application
Rendered products/show.html.erb within layouts/application (Duration: 1.1ms | Allocations: 302)
Completed 200 OK in 23ms (Views: 16.0ms | ActiveRecord: 0.4ms | Allocations: 8945)
Also:
Submitting via rails console works fine, so this has definitely something to do with the form i guess:
irb(main):010:0> p = Product.last
=> #<Product id: 15, title: "abc", price: 0.999e1, created_at: "2019-02-10 13:02:59", updated_at: "2019-02-10 13:02:59">
irb(main):011:0> p.colors
=> #<ActiveRecord::Associations::CollectionProxy []>
irb(main):012:0> p.colors << [Color.last]
=> #<ActiveRecord::Associations::CollectionProxy [#<Color id: 2, col: "Red", created_at: "2019-02-10 09:04:42", updated_at: "2019-02-10 09:04:42">]>
irb(main):013:0> p.colors
=> #<ActiveRecord::Associations::CollectionProxy [#<Color id: 2, col: "Red", created_at: "2019-02-10 09:04:42", updated_at: "2019-02-10 09:04:42">]>
_form.html.erb (generated by scaffold and adjusted with the collection_select field)
<%= form_with(model: product, local: true) do |form| %>
<% if product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% product.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :title %>
<%= form.text_field :title %>
</div>
<div class="field">
<%= form.label :price %>
<%= form.text_field :price %>
</div>
<div class="field">
<%= form.label :color_ids %>
<%= form.collection_select( :color_ids, Color.all, :id, :col, {multiple: true}) %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
Greetings!
You are expecting an array/hash but you are receiving a single string. It looks like the helper is not creating a multiple select, do you see the multiple="true" attr on the select tag? If not, try changing the method to this:
form.collection_select( :color_ids, Color.all, :id, :col, {}, {multiple: true})
Note the extra {}. The helper expect the first hash to be the options for the helper and the second hash to be the options for the tag.

Geo coder not saving any information in table

Ive installed geocoder gem but when i type the address in the form it doesnt save any params in the table, its just an empty object. is there something im missing?
The location model:
class Location < ApplicationRecord
attr_accessor :postcode, :longitude, :latitude
geocoded_by :postcode
after_validation :geocode, :if => :postcode_changed?
end
The location controller:
def create
#location = Location.new(location_params)
if #location.save
redirect_to message_path(current_user.id)
flash[:success] = "Success"
else
redirect_to root_path
flash[:danger] = "failed"
end
end
private
def location_params
params.require(:location).permit(:postcode, :user_id)
end
Here is the form:
<%= form_for #location, :url => locations_path do |f| %>
<p>
<%= f.label "postcode" %><br />
<%= f.text_field :postcode %>
<%= f.hidden_field :user_id, :value => current_user.id %>
</p>
<p><%= f.submit %></p>
<% end %>
And here is my schema:
create_table "locations", force: :cascade do |t|
t.string "postcode"
t.float "longitude"
t.float "latitude"
t.bigint "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_locations_on_user_id"
end
So the idea is that a user would enter his postcode in the form on his profile page his location would show for all the other users to see.
I may not have grasped the concept of it so any help or guidance would be much appreciated. Thanks
Oh and here is the table entry after save:
irb(main):011:0> Location.last
Location Load (0.4ms) SELECT "locations".* FROM "locations" ORDER BY "locations"."id" DESC LIMIT $1 [["LIMIT", 1]]
=> #<Location id: 10, postcode: nil, longitude: nil, latitude: nil,
user_id: 9, created_at: "2017-10-17 09:40:43", updated_at: "2017-10-17 09:40:43">

Rails rolling back twice every time I try to post Data

I am trying to create an app that allows users to make lists of items and view only the lists they themselves have created. Every time I press submit on the form this happens
Started POST "/lists" for 127.0.0.1 at 2017-08-18 15:56:40 -0400
Processing by ListsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"VnsMdQq3mw5XabkYCZFTgvgwFc3H89paHA0VE5gunFbiMfa0xGr0p1GEZDHc3yemwBx07K1h4CXuS0l5XL1VbA==", "list"=>{"income"=>"12", "put_into_savings"=>"12", "month"=>"12", "year"=>"21"}, "commit"=>"Create List"}
(0.1ms) begin transaction
(0.1ms) rollback transaction
(0.0ms) begin transaction
(0.0ms) rollback transaction
Rendering lists/new.html.erb within layouts/application
Rendered lists/new.html.erb within layouts/application (9.3ms)
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 5], ["LIMIT", 1]]
Completed 200 OK in 269ms (Views: 222.2ms | ActiveRecord: 2.7ms)
Here is all my code:
lists_controller.rb
class ListsController < ApplicationController
def show
#user = User.find(params[:id])
#lists = #user.lists
end
def new
end
def edit
end
def create
#list = List.create(list_params)
if #list.save
redirect_to home_url
else
render :new
end
end
private
def list_params
params.require(:list).permit(:income, :put_into_savings, :month, :year)
end
end
lists/new.html.erb
<%= form_for List.new do |f| %>
<div class="field">
<%= f.label :income %><br />
<%= f.text_field :income %>
</div>
<div class="field">
<%= f.label :put_into_savings %><br />
<%= f.text_area :put_into_savings %>
</div>
<div class="field">
<%= f.label :month %><br />
<%= f.number_field :month %>
</div>
<div class="field">
<%= f.label :year %><br />
<%= f.number_field :year %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
schema.rb
ActiveRecord::Schema.define(version: 20170818185700) do
create_table "items", force: :cascade do |t|
t.string "item_name"
t.integer "item_cost"
t.string "item_waste"
t.string "item_group"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "lists", force: :cascade do |t|
t.integer "income"
t.integer "put_into_savings"
t.string "month"
t.string "year"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "Item_id"
t.integer "User_id"
end
create_table "users", force: :cascade do |t|
t.string "email"
t.string "password_digest"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
end
end
Routes.rb
Rails.application.routes.draw do
root 'home#index'
get 'home' => 'home#index'
resources :lists
resources :sessions, only: [:new, :create, :destroy]
resources :users, only: [:new, :create]
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
Here is my list model:
class List < ApplicationRecord
has_many :items
belongs_to :user
end
How can I solve this?
You are having logic problem with your model association.
Assuming that a List could have more than one Item, you shouldn't have declared your table List with the attribute item_id. (Doing that it means a List could ONLY have one item). I recommend you read ruby-on-rais-guide-for-associations.
For the problem with the user_id, you need to explicit declared the user_id in your list object (considering that you want to associate a List with a User in the moment the List is created). One way to do it could be:
def create
#list = List.new(list_params)
#list[:user_id] = current_user.id # Considering you add this method
if #list.save
redirect_to home_url
else
render :new
end
And add some validation in model:
class List < ApplicationRecord
has_many :items
belongs_to :user
validates :user_id, presence: true
end
It seems you need to read more about validation too ruby-on-rais-guide-for-validation. About your twice rollback, it is unclear the reason, but fixing you association and validations problems, I think you can fix it.
Try read more about rails, the problem you are having are really basic. Good luck!
UPDATE:
As suggested by at0misk answer, to solve the problem with twice rollback:
In List controller:
#list = List.new(list_params)
# instead of #list = List.create(list_params)
The create method create a new object and save immediately. So, rails was trying to save twice, in the method create first, then in the method save in sequence.
In your create method, you're calling create and then calling save. Create creates an object and saves it to the database, so calling save is redundent.
Have you checked to see if your record is saving? If it is then this is definitely what's wrong. I prefer to use this pattern, using new instead of create, and then attempting to save in an if block:
def create
#list = List.new(list_params)
if #list.save
redirect_to home_url
else
render :new
end
end

Rails 4: Update_attributes does not work but update_column does

Currently I have an edit form as follows:
<li>
<%= form_for #ingredient do |f| %>
<span class="span2"><%= f.text_field :name, placeholder: "#{#ingredient.name}" %></span>
<span class="span1"><%= f.text_field :quantity, placeholder: "#{#ingredient.quantity}" %></span>
<span class="span1"><%= f.text_field :unit, placeholder: "#{#ingredient.unit}" %></span>
<span class="span3">Added: <%= #ingredient.updated_at.strftime("%d %b. at %H:%M") %></span>
<span class="span2"><%= f.text_field :expiration, placeholder: "#{#ingredient.expiration}" %></span>
<span class="span2"><%= f.submit "Submit", class: "btn btn-small" %></span>
<% end %>
</li>
When I click submit my log file shows the follow:
Started PATCH "/pantries/112" for 127.0.0.1 at 2014-04-29 18:03:35 -0400
Processing by PantriesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"NUSmadjWCVVLHOZmncKD5D48L+7ZMa3DEbZ9Y+Y+Pnc=", "pantry"=>{"name"=>"test1", "quantity"=>"1", "unit"=>"cup", "expiration"=>"2015-05-05"}, "commit"=>"Submit", "id"=>"112"}
[1m[35mUser Load (0.5ms)[0m SELECT "users".* FROM "users" WHERE "users"."remember_token" = '27ecdc04fc67375fd3567c89fbe831e4d4919d09' LIMIT 1
[1m[36mPantry Load (0.3ms)[0m [1mSELECT "pantries".* FROM "pantries" WHERE "pantries"."id" = $1 LIMIT 1[0m [["id", "112"]]
[1m[35m (0.2ms)[0m BEGIN
[1m[36m (0.1ms)[0m [1mCOMMIT[0m
Redirected to http://localhost:3000/users/1/pantry
Completed 302 Found in 6ms (ActiveRecord: 1.1ms)
It doesn't raise an error it just does not update at all, but says that the update completed successfully.
pantry.rb
class Pantry < ActiveRecord::Base
before_save { self.name = name.downcase }
belongs_to :user
validates :name, presence: true
validates :user_id, presence: true
end
pantries_controller
def update
#ingredient = Pantry.find(params[:id])
if #ingredient.update_attributes(params[ingredient_params])
redirect_to pantry_user_path(current_user), :flash => {info: "Ingredient Updated"}
else
redirect_to pantry_user_path(current_user), :flash => {info: "Failed"}
end
end
private
def ingredient_params
params.require(:pantry).permit(:name, :quantity, :unit, :expiration, :created_at, :updated_at)
end
schema:
create_table "pantries", force: true do |t|
t.string "name"
t.string "quantity"
t.string "unit"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.date "expiration"
end
add_index "pantries", ["expiration"], name: "index_pantries_on_expiration", using: :btree
add_index "pantries", ["quantity"], name: "index_pantries_on_quantity", using: :btree
add_index "pantries", ["unit"], name: "index_pantries_on_unit", using: :btree
If I replace #ingredients.update_attributes with #ingredient.update_column(:expiration, params[:pantry][:expiration]) the update takes place on that column. Falling back to update_column is not ideal. I understand update_attributes and update_attributes! call callbacks while update_column does not. I don't see any issue with the callbacks and no error messages are given. Anyone have an idea on what the issue might be?
Change your update action as below:
def update
#ingredient = Pantry.find(params[:id])
if #ingredient.update_attributes(ingredient_params) ## Call ingredient_params
redirect_to pantry_user_path(current_user), :flash => {info: "Ingredient Updated"}
else
redirect_to pantry_user_path(current_user), :flash => {info: "Failed"}
end
end
With Rails 4 strong parameters concept, you need to whitelist the attributes that you would like to be saved in database.
Currently, you are using params[ingredient_params] instead of calling ingredient_params which is causing this issue

Paperclip isn't storing file on my inherited model

(I am new to paperclip)
I have this model hierarchy:
base model:
class QuestDescription < ActiveRecord::Base
end
inherited model:
class ImageDescription < QuestDescription
has_attached_file :img
end
and I'm using Single Table Inheritance from ActiveRecord
[part of] schema.rb:
create_table "quest_descriptions", :force => true do |t|
t.string "type"
t.datetime "img_updated_at"
t.integer "img_file_size"
t.string "img_file_name"
t.string "img_content_type"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
ImageDescription controller:
class ImageDescriptionsController < ApplicationController
def new
#imgD = ImageDescription.new
end
def create
#imgD=ImageDescription.new(params[:imgD])
if #imgD.save
redirect_to :back, :flash => {:notice => "saved"}
else
redirect_to :back, :flash => {:error => "error"}
end
end
def show
#imgD=ImageDescription.find(params[:id])
end
end
new view (using formtastic):
<%= semantic_form_for #imgD do |form| %>
<%= form.input :img%>
<%= form.actions %>
<%end%>
show view:
<%= image_tag #imgD.img.url %>
when i use the new view (and select the file to upload), the POST is working, but no file is being saved/attached, the "img_file_size", "img_file_name", "img_content_type" are set to nil.
If I try to show it, the result is a "missing" field.
EDIT:
if i try to create a ImageDscription from the console, it works:
ImageDescription.create(:img => File.new(Rails.root + "public/images/grid.png"))
(0.1ms) begin transaction
SQL (31.9ms) INSERT INTO "quest_descriptions" ("created_at", "img_content_type", "img_file_name", "img_file_size", "img_updated_at", "type", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) ["created_at", Wed, 15 Feb 2012 00:07:48 UTC +00:00], ["img_content_type", "image/png"], ["img_file_name", "grid.png"], ["img_file_size", 206], ["img_updated_at", Wed, 15 Feb 2012 00:07:48 UTC +00:00], ["type", "ImageDescription"], ["updated_at", Wed, 15 Feb 2012 00:07:48 UTC +00:00] commit transaction
=> #
You need define your post contain some file inside with multipart HTML tag
<%= semantic_form_for #imgD, :html => { :multipart => true } do |form| %>
<%= form.input :img%>
<%= form.actions %>
<%end%>
really stupid mistake:
#imgD=ImageDescription.new(params[:imgD])
means nothing... right line is
#imgD=ImageDescription.new(params[:image_description])

Resources