I am having difficulty translating the Headfirst into Rails book which is based on Rails 2 into Rails 4 which is set up on my machine.
The exercise is trying to retrieve a record from a database and then, once edited, update the table.
I have tried many different ways and my current configuration is as follows - this will present the record for editing but will not actually update the record! (Infuriating!)
NB - I am not using 'strong_parameters' nor 'protected_attributes' - I did try this but was getting stack to deep and other errors.
My ad model is also empty - I have removed the att_accessible entries that I tried with the protected attributes gem.
Here is my - ad controller entry:
def update
#ad = Ad.find(params[:id])
#ad.update_attributes(update_params[:id])
redirect_to "/ads/#{#ad.id}"
end
private
def update_params
params.permit(:name, :description, :price, :seller_id, :email, :ad, :img_url)
end
end
EDIT VIEW:
<h1>Editing <%= #ad.name %></h1>
<%= form_for(#ad,:url=>{:action=>'update'}) do |f| %>
<p><b>Name</b><br /><%= f.text_field :name %></p>
<p><b>Description</b><br /><%= f.text_area :description %></p>
<p><b>Price</b><br /><%= f.text_field :price %></p>
<p><b>Seller</b><br /><%= f.text_field :seller_id %></p>
<p><b>Email</b><br /><%= f.text_field :email %></p>
<p><b>Img Url</b><br /><%= f.text_field :img_url %></p>
<p><%= f.submit "update" %></p>
<% end %>
Log Entry on Update:
Started PATCH "/ads/1/update" for 127.0.0.1 at 2013-08-13 22:35:51 +0100
Processing by AdsController#update as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"O4cN72FXCCkfkL7M6bozodbB0Aqor
NctOOV5sfXdado=", "ad"=>{"name"=>"Typewriter", "description"=>"Old manual typewr
iter. Many years useful service. Works best with a bottle next to it.", "price"=
>"71.95", "seller_id"=>"54", "email"=>"dhammett#email.com1", "img_url"=>"http://
homepage.mac.com/david_griffiths/typewriter.png"}, "commit"=>"update", "id"=>"1"
}
←[1m←[35mAd Load (1.0ms)←[0m SELECT "ads".* FROM "ads" WHERE "ads"."id" = ? L
IMIT 1 [["id", "1"]]
Unpermitted parameters: utf8, _method, authenticity_token, ad, commit, id
←[1m←[36m (0.0ms)←[0m ←[1mbegin transaction←[0m
←[1m←[35m (0.0ms)←[0m commit transaction
Redirected to http://localhost:3000/ads/1
Completed 302 Found in 54ms (ActiveRecord: 1.0ms)
Related
So I was working on my app and trying to put on an uploader feature.
First I generated a course uploader and allowed jpeg, jpg, png and gif.
Next I've added the ff code mount on my course model:
mount_uploader :thumb_image, CoursesUploader
mount_uploader :main_image, CoursesUploader
Next, I place the file upload form code on my new.html.erb file:
<div class="field">
<%= f.file_field :main_image %>
</div>
<div class="field">
<%= f.file_field :thumb_image %>
</div>
And when I tried to submit my form with my images uploaded it did not even show the index page instead I refresh the page and then see if it got uploaded and the form was submitted successfully but it did not.
I also look at the strong params on my controller and these two items are there:
# Never trust parameters from the scary internet, only allow the white list through.
def course_params
params.require(:course).permit(:title, :price, :body, :main_image, :thumb_image)
end
Any idea what am I missing here?
Here's something I got from my terminal after submission:
Started POST "/courses" for 127.0.0.1 at 2019-01-16 20:52:20 +0800
Processing by CoursesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"wlKpv8czsuC6AZjCctxYk203wry4cb0dnOYI9IoAkzRZNV2vB4/vREU5L5u4G7vh5ZhCbHZlJ6nHPN95qO+cbA==", "course"=>{"title"=>"Goody", "price"=>"33", "main_image"=>#<ActionDispatch::Http::UploadedFile:0x007f81e52eed48 #tempfile=#<Tempfile:/var/folders/3_/8bmsd3j13bxfdl1jp7gzvvsm0000gn/T/RackMultipart20190116-2359-17w6pb.jpg>, #original_filename="61230.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"course[main_image]\"; filename=\"61230.jpg\"\r\nContent-Type: image/jpeg\r\n">, "thumb_image"=>#<ActionDispatch::Http::UploadedFile:0x007f81e52eecd0 #tempfile=#<Tempfile:/var/folders/3_/8bmsd3j13bxfdl1jp7gzvvsm0000gn/T/RackMultipart20190116-2359-2mcy4i.jpg>, #original_filename="61230.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"course[thumb_image]\"; filename=\"61230.jpg\"\r\nContent-Type: image/jpeg\r\n">, "body"=>""}, "commit"=>"Create Course"}
(0.5ms) BEGIN
↳ app/controllers/courses_controller.rb:27
Course Exists (1.5ms) SELECT 1 AS one FROM "courses" WHERE "courses"."id" IS NOT NULL AND "courses"."slug" = $1 LIMIT $2 [["slug", "goody"], ["LIMIT", 1]]
↳ app/controllers/courses_controller.rb:27
(0.6ms) ROLLBACK
↳ app/controllers/courses_controller.rb:27
Rendering courses/new.html.erb within layouts/application
Rendered courses/new.html.erb within layouts/application (12.6ms)
Rendered shared/_application_nav.html.erb (6.2ms)
Rendered shared/_application_footer.html.erb (1.3ms)
Completed 200 OK in 394ms (Views: 356.6ms | ActiveRecord: 2.6ms)
UPDATE: FULL MODEL CONTENT
class Course < ApplicationRecord
include DefaultsConcern
enum status: { draft: 0, published: 1 }
validates_presence_of :title, :price, :body, :main_image, :thumb_image
mount_uploader :thumb_image, CoursesUploader
mount_uploader :main_image, CoursesUploader
extend FriendlyId
friendly_id :title, use: :slugged
end
FULL FORM CONTENT:
<h1>New Form</h1>
<%= form_for(#course) do |f| %>
<div class="field">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :price %>
<%= f.number_field :price %>
</div>
<div class="field">
<%= f.file_field :main_image %>
</div>
<div class="field">
<%= f.file_field :thumb_image %>
</div>
<div class="field">
<%= f.label :body %>
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Validation failed as params[:course][:body] is nil due to which creating course rolled back
validates_presence_of :title, :price, :body, :main_image, :thumb_image
=> So just fillup body field in form or remove validates_presence_of :body
I can see the Image is ActionDispatch already but are you sure you created your table column like this -Regardless of creating table or adding_column-
I'm focusing on
:string, array: true, default: []
Migration should look like:
add_column :courses, :main_image, :string, array: true, default: []
As creating the column as String won't let carrierwave add it's object as an array inside it, so it should be an array
Also you can set thumb and main images in one uploader if you are going to change the size only, otherwise you're fine to use :thumb_image and :main_image but make sure the migration is correct
If you can't change it, just drop and re-create it
How can I use a conditional to do one thing if :name is passed to the _form and another thing if that :name isn't passed?
With :name passed:
Started GET "/inspirations/new?inspiration%5Bname%5D=Always+trust+yourself+more+than+you+doubt+yourself" for 127.0.0.1 at 2016-11-08 01:00:44 -0500
Processing by InspirationsController#new as HTML
Parameters: {"inspiration"=>{"name"=>"Always trust yourself more than you doubt yourself"}}
Without :name passed:
Started GET "/inspirations/new" for 127.0.0.1 at 2016-11-08 01:16:18 -0500
Processing by InspirationsController#new as */*
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 1]]
Inspiration Load (0.4ms) SELECT "inspirations".* FROM "inspirations" WHERE "inspirations"."id" IS NULL LIMIT 1
Rendered inspirations/_form.html.erb (4.1ms)
Rendered inspirations/new.html.erb within layouts/modal (5.9ms)
Completed 200 OK in 49ms (Views: 41.9ms | ActiveRecord: 0.7ms)
_form
<%= simple_form_for(#inspiration) do |f| %>
<%= f.text_area :name %>
<% if params[:name].nil? %> # Should Be Triggered If No :name Is Present in URL
etc...
<% end %>
<% end %>
So for example when a URL includes a string:
http://www.livetochallenge.com/inspirations/new?inspiration%5Bname%5D=Life+would+be+easier+if+I+had+the+source+code.
But I often use a URL shortener.
Didn't work for me:
Is there a way to check if part of the URL contains a certain string
including url parameters in if statement
Try this:
<%= simple_form_for(#inspiration) do |f| %>
<%= f.text_area :name %>
<% if params[:inspiration].try(:[], :name).nil? %> # Should Be Triggered If No :name Is Present in URL
etc...
<% end %>
<% end %>
This will check :name inside params[:inspiration] only if the later is present. So, no error should occur.
You can avoid the error using fetch.
<%= simple_form_for(#inspiration) do |f| %>
<%= f.text_area :name %>
<%= f.text_area :name %>
<% name = params.fetch(:inspiration, {}).fetch(:name, nil) %>
<% if name.nil? %>
etc...
<% end %>
<% end %>
I have a form submitting a value to my create controller. In the server log, I see the parameter (:style) being passed, but not inserted into database. Does someone know how that could happen?
Server log
Started POST "/users/25/cupboards" for ::1 at 2016-08-19 19:11:39 -0400
Processing by CupboardsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"asWeoSFSisr62oMOPXZnb//KJ8LnAhT1h07NOm1Yn2O8t06N4yrDGugkd01AMQcujYzSahH+O7bEA/jpH+L9fQ==", "style"=>"WEEKEND", "commit"=>"Make a new closet", "user_id"=>"25"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 25]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 25]]
(0.1ms) begin transaction
SQL (0.5ms) INSERT INTO "cupboards" ("user_id", "created_at", "updated_at") VALUES (?, ?, ?) [["user_id", 25], ["created_at", "2016-08-19 23:11:39.219003"], ["updated_at", "2016-08-19 23:11:39.219003"]]
(0.7ms) commit transaction
Redirected to http://localhost:3000/users/25/cupboards/35/edit
Completed 302 Found in 46ms (ActiveRecord: 1.4ms)
Form
<%= form_for #cupboard, url: { action: "create" }, html: { class: "listform"} do |f| %>
<%= f.label "ATHLEISURE", class: "welcomelistitem" %>
<%= radio_button_tag(:style, "ATHLEISURE") %>
<%= f.label "CASUAL", class: "welcomelistitem" %>
<%= radio_button_tag(:style, "CASUAL") %>
<%= f.label "PROFESISONAL", class: "welcomelistitem" %>
<%= radio_button_tag(:style, "PROFESSIONAL") %>
<%= f.label "WEEKEND", class: "welcomelistitem" %>
<%= radio_button_tag(:style, "WEEKEND") %>
<%= f.label "FESTIVAL", class: "welcomelistitem" %>
<%= radio_button_tag(:style, "FESTIVAL") %>
<%= f.label "DATENIGHT", class: "welcomelistitem" %>
<%= radio_button_tag(:style, "DATENIGHT") %>
<%= f.submit 'Make a new closet' %>
<% end %>
Controller
def create
#user = User.find(params[:user_id])
#cupboard = #user.cupboards.new(cupboard_params)
if #cupboard.save
redirect_to edit_user_cupboard_path(#user, #cupboard)
else
render :new
end
end
Params
private
def cupboard_params
# I used .fetch because .permit wasnt working. workaround found at http://stackoverflow.com/questions/24944871/actioncontrollerparametermissing-param-is-missing-or-the-value-is-empty-film
params.fetch(:cupboard, {}).permit(:style, :season, :neutral1, :neutral2, :accent1, :accent2)
end
end
Thank you for the assistance!
This happens because your form submits the styleattribute value like style instead of cupboard[style]. Looks like you're mixing form_for methods with form_tag ones and you need to replace radio_button_tag with radio_button. Also note that there are 2 forms of notations: either the function invocation radio_button(:model_name, :col_name, 'value') or the method invocation on the form object itself f.radio_button(:col_name, 'value'). Another issue with your form is that you're using label for each radio while it's designed to be used once for every group of radio buttons. Hence, the form should look like this:
<%= form_for #cupboard, html: { class: 'listform' } do |f| %>
<%= f.label :style, class: 'welcomelistitem' %>
<%= f.radio_button :style, 'ATHLEISURE' %>
<%= f.radio_button :style, 'CASUAL' %>
<%= f.radio_button :style, 'PROFESSIONAL' %>
<%= f.radio_button :style, 'WEEKEND' %>
<%= f.radio_button :style, 'FESTIVAL' %>
<%= f.radio_button :style, 'DATENIGHT' %>
<%= f.submit 'Make a new closet' %>
<% end %>
You'll then have to rewrite the cupboard_params method like this:
def cupboard_params
params.require(:cupboard).permit(:style)
end
Didn't have time to check if this works, but seems like it should.
The parameter "style" is not being passed inside of params[:cupboard]. It is directly in params.
I don't see the other params (besides style) in your form so I'm not sure what is going on there but try this
def cupboard_params
params.permit(:style)
end
Or change your radio buttons in the view to this
radio_button_tag('cupboard[style]', "ATHLEISURE")
This is my first question on here, so I am hoping I have not asked it incorrectly.
I have a generic new action on my tickets controller. Whenever I load tickets/new, it is creating a new item in the DB and committing it.
Here is the output from the server when the page is loading.
Started GET "/tickets/new" for ::1 at 2016-02-10 21:14:47 -0800
Processing by TicketsController#new as HTML
Customer Load (0.4ms) SELECT `customers`.* FROM `customers` WHERE `customers`.`email` = 'tim#tim.com' LIMIT 1
(0.3ms) BEGIN
SQL (0.5ms) INSERT INTO `tickets` (`category`, `created_at`, `updated_at`) VALUES (3, '2016-02-11 05:14:47', '2016-02-11 05:14:47')
(6.4ms) COMMIT
Rendered tickets/_new_form.html.erb (23.3ms)
Rendered tickets/new.html.erb within layouts/application (48.4ms)
Rendered layouts/_user_nav.html.erb (0.8ms)
Rendered layouts/_navbar.html.erb (0.5ms)
Rendered layouts/_flashes.html.erb (0.5ms)
Rendered layouts/_minimal.html.erb (759.5ms)
Completed 200 OK in 893ms (Views: 822.1ms | ActiveRecord: 21.3ms)
This is the from the tickets controller.
def new
#ticket = Ticket.new
end
Here is the code for the form.
<%= form_for(#ticket, html: { class: 'form-horizontal' }) do |f| %>
<%= f.error_notification %>
<%= f.hidden_field(:category) %>
<%= f.hidden_field(:severity) %>
<br>
<%= f.form_group :summary do |f| %>
<%= f.label :summary, class: 'control-label col-md-2' %>
<div class='col-md-8'>
<%= f.text_field :summary, class: 'form-control' %>
<%= f.error_messages %>
</div>
<% end %>
<%= f.form_group :detail do |f| %>
<%= f.label :detail, class: 'control-label col-md-2' %>
<div class='col-md-8'>
<%= f.text_area :detail, class: 'form-control' %>
<%= f.error_messages %>
</div>
<% end %>
<br>
</div>
<div class="form-actions col-md-offset-2 col-md-10">
<%= f.submit 'Create', class: 'btn btn-primary' %>
<%= link_to "Cancel", tickets_path, class: 'btn' %>
</div>
<% end %>
Here are the relevant routes.
resources :tickets do
collection do
get :step_1
get :new_ticket
get :billing_new_1
get :internet_step_1
get :internet_step_2
get :internet_modem_reset
get :internet_step_1
get :internet_step_2
get :internet_create_1
get :internet_create_2
get :tv_step_1
get :tv_step_2
get :tv_step_3
get :tv_create_1
get :tv_create_2
get :tv_create_3
get :closed
get :sidenav
end
member do
put :close
end
resources :notes
resources :appointments
end
Help!!
--Tim
INSERT INTO `tickets` (`category`, `created_at`, `updated_at`) VALUES (3, '2016-02-11 05:14:47', '2016-02-11 05:14:47')
This is getting category (3) from somewhere, suggesting that there is some functionality somewhere which is saving the #ticket.
The simplest explanation I can see is that you have a before_action somewhere. It would benefit to show your entire TicketsController:
#app/controllers/tickets_controller.rb
class TicketsController < ApplicationController
before_action :set_user #-> something like this??
end
Since you're new, you can make your routes much more succinct (multiple resources):
#config/routes.rb
methods = %i(step_1 new_ticket billing_new_1 internet_step_1 internet_step_2 internet_modem_reset internet_create_1 internet_create_2 tv_step_1 tv_step_2 tv_step_3 tv_create_1 tv_create_2 tv_create_3 closed sidenav)
resources :tickets do
resources :notes, :appointments
collection do
methods.each {|method| get method }
end
put :close, on: :member
end
I ended up starting the whole ticket class over.
I think the error was in my html.
My guess is that the if statement with the bang was causing the ticket to save, because of an enum with that name on the model.
Here is what I think was the bad html.
<% if #ticket.category == :tv %>
Ok. Your tv is down, but your internet is still working.
<br>
Do you have any more details to add? If so, add them here. If not, just hit sumbit and we will open up a ticket with all of the information that you have provided us.
<% elsif #ticket.internet! %>
Ok. Your internet is down, but your tv is still working.
<br>
Do you have any more details to add? If so, add them here. If not, just hit sumbit and we will open up a ticket with all of the information that you have provided us.
<% elsif #ticket.billing %>
I am fresh out of questions.
<br>
Do you have any more details to add? If so, add them here. If not, just hit sumbit and we will open up a ticket with all of the information that you have provided us.
<% elsif #ticket.category == :internet_and_tv %>
Ok. Your cable and internet are both down.'%>
<br>
Do you have any more details to add? If so, add them here. If not, just hit sumbit and we will open up a ticket with all of the information that you have provided us.'%>
<% else #ticket.category == :plant %>
<%end%>
I'm new to Ruby, and I'm developing my own app in Nitrous.
When I complete a form on my new.html.erb, and hit save, the show view loads. The page renders with HTML headers as expected, but no data fields from my model. I have also tried the index view, but there is no data being saved, I think.
I have generated a model called income, and run rake db:migrate successfully, wiht the right tables set up. I'm stumped as to what the problem is.
Any ideas gratefully received.
This is my controller: incomes_controller.rb
class IncomesController < ApplicationController
def index
#incomes = Income.all
end
def new
#income = Income.new
end
def create
#income = Income.new(income_params)
if #income.save
redirect_to(:action => 'show', :id => #income.id)
end
end
def show
#income = Income.find(params[:id])
end
private
def income_params
params.require(:income).permit(:first_name, :last_name, :date_of_birth, :income1, :income2, :income3, :income4, :income5, :income6, :income7, :income8, :income9, :income10)
end
end
My form in new.html.erb, is:
<%= simple_form_for #income do |f| %>
<%= f.input :first_name, label: 'First Name' %>
<%= f.input :last_name, label: 'Last Name' %>
<%= f.input :date_of_birth, label: 'Date of Birth', hint: 'dd/mm/yyyy' %>
<p>Income: Salary or Wages</p>
<%= f.input :income1, label: 'Take home salary or Wage' %>
<%= f.input :income2, label: 'Partner\'s salary or wage' %>
<%= f.input :income3, label: 'Other income from salary or wages' %>
<p>Other Income</p>
<%= f.input :income4, label: 'Maintanence or child support' %>
<%= f.input :income5, label: 'Boarders or lodgers' %>
<%= f.input :income6, label: 'Non-dependent contributions' %>
<%= f.input :income7, label: 'Student loands or grants' %>
<%= f.input :income7, label: 'Other' %>
<p>Benefits </p>
<%= f.input :income8, label: 'Sample input' %>
<%= f.input :income9, label: 'Sample input' %>
<%= f.input :income10, label: 'More sample inputs' %>
<%= f.button :submit, "Save and Proceed" %>
<h3>You will have a chance to review your form before you submit it. Once you click Save, you can come back and complete the rest of the form at a later date</h3>
<% end %>
And my show.html.erb file is:
<p>
<strong>First name:</strong>
<%= #income.first_name %>
</p>
<p>
<strong>Last name:</strong>
<%= #income.last_name %>
</p>
<p>
<strong>Date of Birth:</strong>
<%= #income.date_of_birth %>
</p>
<p>
<strong>Take home salary or Wage:</strong>
<%= #income.income1 %>
</p>
My model income.rb is:
class Income < ActiveRecord::Base
attr_accessor :first_name, :last_name, :date_of_birth, :income1, :income2, :income3, :income4, :income5, :income6, :income7, :income8, :income9, :income10
end
Development log output....
Processing by IncomesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"D4F40TAMcVsb7RbdUZwxXfsgGn1u/iD7R+DWvAwrtJ1q83mgequQbkyKPaheFjsLSZHlMBpDy+H7Rm+HdVeTFw==", "income"=>{"first_name"=>"Barak", "last_name"=>"Obama", "date_of_birth"=>"02/07/1990", "income1"=>"12345", "income2"=>"12345", "income3"=>"", "income4"=>"", "income5"=>"", "income6"=>"", "income7"=>"", "income8"=>"", "income9"=>"", "income10"=>""}, "commit"=>"Save and Proceed"}
[1m[35m (0.1ms)[0m begin transaction
[1m[36mSQL (0.5ms)[0m [1mINSERT INTO "incomes" ("created_at", "updated_at") VALUES (?, ?)[0m [["created_at", "2015-02-19 17:39:54.471034"], ["updated_at", "2015-02-19 17:39:54.471034"]]
[1m[35m (32.8ms)[0m commit transaction
Redirected to http://o-bot-laboratory-190030.euw1.nitrousbox.com/incomes/42
Started GET "/incomes/42" for 88.215.13.57 at 2015-02-19 17:39:54 +0000
Processing by IncomesController#show as HTML
Parameters: {"id"=>"42"}
[1m[36mIncome Load (0.3ms)[0m [1mSELECT "incomes".* FROM "incomes" WHERE "incomes"."id" = ? LIMIT 1[0m [["id", 42]]
Rendered incomes/show.html.erb within layouts/application (0.8ms)
Completed 200 OK in 94ms (Views: 75.6ms | ActiveRecord: 0.3ms)
Routes as requested....
Rails.application.routes.draw do
resources :incomes
root 'incomes#new'
end
Thanks to #RailsOuter and #jyrkim for your help. I found that the problem was indeed with my model file, and migration file.
I needed to remove the line attr_accessor from my model. I have since discovered that I must have modified my migration file to add columns, instead of generating a new migration. Now I have generated the new migration with the data columns, my data is showing!
Thanks again, very appreciative of your input to help out a newbie!