You are on page 1of 13

Rails 3.x (or now 4.

x)
Page

To:

Head First (Rails 2.x)

Changes Needed

7

create new rails application

> rails tickets

> rails new tickets

Not in book specify rails version
8

start built-in web server

Notes

> rails _3.x.x_ new app_name

rails 4.0 is out and may be your default install. You may want to change it to 3.x at the start. To
check your default rails version >rails -v will >>version# you're using by default. Trying to
change the version in the Gemfile after installing using rails4 will cause problems later.

> ruby script/server

> rails s

fd

8

> ruby script/server -p 8000

> rails s -p 8000

there is also a long form for this > rails server and >rails server -p 8000

Not in book stop server

press keys "ctrl" and "c" together

press keys "ctrl" and "c" together

in windows you need to press "ctrl" and "pause/break". Not sure if the book includes this but it
could help

11

generate scaffolding code

> ruby script/generate scaffold ...

> rails generate scaffold ...

can also use the short form > rails g scaffold ...

34

generate migration

> ruby script/generate migration ...

> rails generate migration ...

can also use the short form > rails g migration ...

35

the code of the migration

class AddPhoneToTickets < ActiveRecord::Migration
def self.up
add_column :tickets, :phone, :string
end

class AddPhoneToTickets < ActiveRecord::Migration
def change
add_column :tickets, :phone, :string
end
end

the code generated by rails 3 is different, the method change replaces self.up and self.down

def self.down
remove_column :tickets, :phone
end
end
36-37

add phone_no

add phone field to 4 views files (index,edit,new,show)

Add phone field to 3 views files (index.html.erb, _form.html.erb,
show.html.erb,) similar to what is indicated in pages 36-37.
Also add “:phone” to the list of attributes after attr_accessible in
ticket.rb model file. if using Rails 3.2.8 or above

1 Add phone field to 3 views files (index.html.erb, _form.html.erb, show.html.erb,) similar to what
is indicated in pages 36-37.
the only difference is that _form now is called inside edit and new so one less form to edit.
2 (if u use rails 3.x use this way)Must also add “:phone” to the list of attributes after
attr_accessible in ticket.rb model file. (app/models/ticket.rb)
(but ,if use rauls 4.x) you should edit (app/controller/ticket_controller.rb) and then find
"def ticket_params
params.require(:ticket).permit(:name, :seat_id_seq, :address, :price_paid, :email_address)
end " and add ":phone" after :email_address
if not then it will throw error: "Can't mass-assign protected attributes: phone" when clicking on
create or update button (Required from Rails 3.2.8)

QA comment on the need of
=h

The book highlights the use of <%=h ...%> to escape html

escaped by default in rails 3

In rails 3 you no longer need to call h(string) to escape HTML output, it is on by default in all
view templates. If you want the unescaped string, call raw(string).

40

excercise solution

ruby script/generate scaffold ...

> rails generate scaffold ...

41

excercise solution

asks about which four files to change index, edit, new,
show

need to change only 3: index, show and _form

48

excercise solution

rails mebay

rails new mebay

50

generate model

> ruby script/generate model ...

> rails generate model ...

can also use the short form > rails g model ...

52

generate controller

> ruby script/generate controller

> rails generate controller ...

can also use the short form > rails g controller ...

57

create a route

map.connect 'ads/id', :controller=>'ads', :action=>'show'

(rails 3)match '/ads/:id', to: 'ads#show'
(rails 4)get '/ads/:id' => 'ad#show'
(also rails 4)get '/ads/:id', to: 'ads#show'

this is the routing used in Rails 3.2.14

76

create a route

map.connect '/ads/', :controller=>'ads', :action=>'index'

match '/ads', to: 'ads#index'

this is the routing used in Rails 3.2.14

116

metoda Ad.find(:all)

Ad.find(:all)

kod w notatce, najedź kursorem [1]

95

refer to a stylesheet

95
97
97

edit css

108

routes

112 code line
2

'default.css'

'default.css'

put images in /public/images

put images in /app/assets/images

put default.css in /public/stylesheets

put default.css in /app/assets/stylesheets

In rails 3 you no longer need to call h(string) to escape HTML output, it is on by default in all
view templates. If you want the unescaped string, call raw(string).

not needed, but the convention is <%= stylesheet_link_tag

"application", :media => "all" %>

Cory wrote: "When I worked on chapter two I had to play with the stylesheet to get the images
to display. I had to remove the /images/ from the path."
map.connect '/ads/new', :controller=>'ads',
:action=>'new'
map.connect '/ads/create', :controller=>'ads',
:action=>'create'
map.connect '/ads/', :controller=>'ads', :action=>'index'
map.connect '/ads/:id', :controller=>'ads', :action=>'show'
<% form_for ...

122

params[:ad]

138

link to edit

<a href="/ads/<%= @ad.id %>/edit">Edit</a>

138

routes

map.connect '/ads/:id/edit', :controller=>'ads',
:action=>'edit'
map.connect '/ads/:id/update', :controller=>'ads',
:action=>'update'

148

routes

map.connect '/ads/:id/delete', :controller=>'ads',
:action=>'destroy'

get '/ads/new', to: 'ads#new'
post '/ads/create', to: 'ads#create'
get '/ads', to: 'ads#index'
get '/ads/:id', to: 'ads#show'
<%= form_for ...
(rails 4)<%= form_for @ad, url: {action: "create"} do |f| %>

this is the routing used in Rails 3.2.14

Rails 3 needs the "="

kod w notatce, najedź kursorem [2]

<%= link_to :Edit, action: :edit %>
get '/ads/:id/edit', to: 'ads#edit'
put'/ads/:id', to: 'ads#update' or patch'/ads/:id', to: 'ads#update'
get '/ads/:id/delete', to: 'ads#destroy'

In this case both work but the second one is the convention
this is the routing used in Rails 3.2.14

this is the routing used in Rails 3.2.14

rb file to look like this resources :client_workouts do collection do get 'find' end end And edit the first line of the form_tag in app/views/layouts/application. by default the form is associated with the 'post' method but the correct one should be 'get' Specify the route to 'find' and select that route in the form_tag as follows. Instead of "erros.erb and copying into seats and modifying 235 passing the seat to the partial <%= render :partial=>"new_seat".14 269 partial for listing booked seats def flight_seats @flight = Flight. <%= form_tag .error_message was deprecated for rails 3.find(params[:flight_id]) render :partial=>"seats/seat_list".baggage_allowance errors.add_to_base("The flight is fully booked") end end if @ad. :locals=>{:seats=>@flight.seats. :locals=>{:seat=>Seat.save() redirect_to "/ads/#{@ad. need to specify that the validation is needed 3.capacity errors[:base]<< "The flight is fully booked" end end end 268 route map.size >= flight.x) Page To: 164 code line 11 167 routes Head First (Rails 2. This requires less modifications to the partial as there is no links to remove.html.connect '/flights/:flight_id/seats'.add(:baggage.erb <%= render :partial=>"seats/seat_list". this form can be modified as needed and left with the other seat files instead of copying it. The partial can be directly loaded into the show flight template from there..seats} end Just change so the seats partial stays with the rest of the seats templates and partials 272 include AJAX Libraries Book describes how to add prototype to the layout for handling javascript This is not needed. If using ruby 1.add_to_base("You have too much baggage") end if flight. this is valid for ruby 1.2. :locals=>{:seats=>@flight. :method => :get do %> 210 redirect syntax if @ad. :name belongs_to :flight validate :baggage_allowance_not_exceeded. this is a syntax change if using ruby 1.erb to include: write the div inside views/seats/_seat_list.seats}%> </div> modify views/flights/show. need to separate and name each validator 2. Rails 3 needs the "=" Book says that routes do not need to be modified Need to specify the root.save() redirect_to "/ads/#{@ad.9+.new} %> %> Again. jquery replaced prototype as the javascript library 273-275 placing the div id modify views/flights/show.. "You have too much baggage") end end 1.html. You can see: http://stackoverflow.error_messages %> 224-231 partial for new bookings suggests using app/views/seats/new. :flight_id.new} <%= render partial: 'seats/new_seat'.id}" else render :template=> "ads/new" end 212 error messages <%= f.com/questions/3873190/f-error-messages-in-rails-3-0 rails 3 creates a form that is used both for edit and new on seats.seats} end def flight_seats @flight = Flight.8 then render should be: <%= render :partial => 'seats/new_seat'> def baggage_allowance_not_exceeded if baggage > flight.9+ 243-246 partial for listing booked seats <%= auto_discovery_link_tag(:rss.x (or now 4.id}" else render action: "new" end <%= render partial: 'seats/new_seat'> No error here.org/active_record_validations. by default the javascript libraries are included with: <%= javascript_include_tag "application" %> In rails 3. leave it under seats and reference to it as shown 249-259 custom validators class Seat < ActiveRecord::Base attr_accessible :baggage.seats}%> . :locals=>{:seats=>@flight.erb to include: <div id="seats"> <%= render :partial=>"seats/seat_list". just do not copy the file into flights.size >= flight_capacity errors. :flight_capacity_not_exceeded Custom validators are declared differently in rails 3 def validate if baggage > flight. :locals=>{:seats=>@flight. :controller=>'seats' resources :seats do collection do get :flight_seats end end after some tests this is the best way to specify this route routing in Rails 3. locals: {seat: Seat.find(params[:flight_id]) render :partial=>"flights/seat_list".. {:action=>'news'.html. the code in the book will work on rails 3 but the syntax has changed and could also be written as shown on the second column f.html.Rails 3.html#custom-validators def flight_capacity_not_exceeded if flight.rb to look like this <%= form_tag "/client_workouts/find".9+. the first method will add a custom error message linked to the baggage field 4.baggage_allowance errors. the book sample will work on both but the new syntax is recomended to get used working with ruby 1.add_to_base" use "errors[:base]<<" for more details see: http://edgeguides. Edit the config/routes.:format=>:rss})%> In this case the book is right on suggesting building the partial from the index on seats.rubyonrails.x) Changes Needed Notes <% form_tag . the second method will add a generic message related to the capacity of the flight being exceeded.. :action=>'flight_seats'.seats.html. Notice the syntax change.

add the code at the bottom of the /app/views/flights/show. dataType: "script" }).x) Changes Needed Notes 273-275 put div inside _seat_list.id.seats}} format... use link_to.replaceWith("<%= updated_list%>").html { render action: "new" } end format.each do |seat| %> <tr> <td><%= seat.#2 and #3. :remote => true) do |f| %> remote_form_for was deprecated for rails 3 . :locals=>{:seats=>@flight.replace_html 'seats'.erb Not in book <div id="seats"> <h1>Listing seats</h1> when replaceWith is called from javascript.html.:update=>'seats') do |f| %> 288-292 refresh list when adding a new #Changes required in the create method: Lines #1. :remote => true %> link_to_remote is not used anymore.errors. Line #1 will get the flight which will be used for reloading the seats list. Much of these was adapted from the response of EdJones on http://stackoverflow. seat. notice: 'Seat was successfully else booked. # Changes required on rails 3 record def create Lines #2 and #3 indicate what to do if the method is called with remote set to true (js call) def create @seat = Seat.json { render json: @seat.id%>".html.erb if @seat. method: :delete. data: "id=<%= @flight..erb and save it on the same path as other seat templates (app/views/seats). action: :flight_seats. Use the code to create a file called flight_seats.new(params[:seat]) @seat = Seat. controller: :seats. :locals => {:seats => @flight. :partial => 'flights/seat_list'.the seat could not format.erb if update was not ok end end end in Rails 3 the change needed is from: <%= form_for(seat) do |f| %> to <%= form_for(seat.' } page.seats } format.5000) }). The second function calls the flight_seats method on the seats controller. 'Sorry . generating javascript code that is returned for updating list of seats.Rails 3. 280 autorefresh <%= periodically_call_remote . } <% end -%> link_call_remote was deprecated on rails 3.js {@seat} #3 this calls the js. status: end :unprocessable_entity } format.name %></td> <td><%= seat.erb Not in book <% updated_list = escape_javascript(render(:partial => 'seat_list'. <%= link_to "refresh seats". but the updater is not generated so more code is needed.js end end Add respond_to and format. 'Seat was successfully if @seat.new(params[:seat]) render :update do |page| @flight = @seat.x) Page To: Head First (Rails 2. so it needs to be in the partial <table> <tr> <th>Name</th> <th>Baggage</th> <th></th> <th></th> <th></th> </tr> <% seats. <%= javascript_tag do -%> $(document). That is all that's required 285-287 refresh list when adding a new in page 287 it says change: record <% form_for(seat) do |f| %> to <% remote_form_for(seat. :id => @flight. edit_seat_path(seat) %></td> <td><%= link_to 'Destroy'. location: @seat be booked' } end format. This is the code that does the replacement.save respond_to do |format| page. else :locals => {:seats => @seat.html { redirect_to @seat.erb is rendered. the controller will look for it in there.replace_html 'notice'. seat %></td> <td><%= link_to 'Edit'. The first javascript sets the counter to 5000 milliseconds (= 5 seconds). function refresh_seats(){ $.js.js.erb. but the updater is not generated so more code is needed 273-275 Edit controller method to return javascript Not in book def flight_seats @flight = Flight.seats}))%> $("#seats").flight.js {@seat} #2 this calls the js.erb if update was ok page.baggage %></td> <td><%= link_to 'Show'. status: :created.html {render :partial=>"seats/seat_list".save booked' format.x (or now 4.ready( function(){setInterval("refresh_seats()".com/questions/4016285/rails-3-simple-ajaxy-page-updates 273-275 Create js template: flight_seats.flight #1 need to pass the flight to the js.replace_html 'notice'. with :remote => true.ajax({type: "GET". data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </table> <br /> </div> 273-275 link to refresh <%= link_to_remote .js so the js. method: :get. the <div> would be lost after first call.. url: "/seats/flight_seats/".find(params[:id]) respond_to do |format| format.json { render json: @seat.

:controller match 'incidents/news'=> 'incidents#news' => 'incidents'. notice: 'Seat was successfully booked.html { render action: "new" } format.com/questions/5544871/jquery-equivalent-to-prototype-ajax-request https://googledevelopers. mark1.erb if update was not ok end end end this js template will update the list and clean the form if the creation succeeds or present the error if it does not.14 this code will work and return three types of data: rss. width: 400px. status: :unprocessable_entity } format. height: 200px.openInfoWindowHtml(contentString).errors. dataType: 'html' The code in the book from pages 361-365 should work OK.rss.x) Changes Needed 292-306 New js template: create.' } format. } $.'>" + data + "</div>".x) Page To: Head First (Rails 2. Edit file: _map. Just need to name the builder template as news.js. the controller will look for it in there.erb Not in book Notes # Changes required on rails 3 def create @seat = Seat. EXPLORER: the rss button is in the command bar. firefox and chrome do: CRHOME: the rss feed is a plugin that needs to be added.connect 'incidents/map/:id. the javascript library for rails 3. '. by default the javascript libraries are included with: <%= javascript_include_tag "application" %> In rails 3.json { render json: @seat.:format'.builder def news @incidents = Incident. using firebug it appears that the problem is the call "new Ajax.14 Looking at the documentation of the GoogleMaps JavaScript API and examples on Stackoverflow helped in getting the code right. go to settings/extensions and click on get extensions then look for rss subscription extension and click on the add button (it is free) FIREFOX: from the menu go to options/toolbar layout or right click on the toolbar and select customise.html.responseText + "</div>". This is because the original code was made to work with the old JavaScript library for Rails (Prototype). json.json { render json: @incidents } end end 352 builder file code in book works on 3. }. :remote=>true) do |f| %> remote_form_for was deprecated for rails 3 . min-height: 300px.openInfoWindowHtml(html).:format' is implicit in all routes. height: 300px. this needs to go before the resources :incidents line in the routes. min-height: 200px.builder.yesterday]) not necesary in rails 3.'>" + transport.connect 'incidents/map/:id'. if the bar is hidden just rightclick on the top of the browser and select Command bar to see the icon 360 include AJAX Libraries Book describes how to add prototype to the layout for handling javascript This is not needed. If format is not specified the redirection when clicking the RSS feed buton will not work NOTE: Browsers do not automathically display the rss button on the address bar(box) for explorer. :action => 'show_with_map'. :conditions=>['[when] >= ?'.2.html. Lines 5157 need to be changed new Ajax.rss { render :layout => false } #news.14 The builder works as expected but it can also be named news.new(params[:seat]) @flight = @seat. location: @seat } format.:format to path map. { method: 'get'. :update=>'map_info'.find(:all. jquery replaced prototype as the javascript library 362-366 NOT IN THE BOOK. If it is placed afte it will not work.builder format. then drag the rss icon to the toolbar. :controller => 'incidents' match 'incidents/map/:id'=> 'incidents#show_with_map' 345 route to news map. Use the code to create a file called create. References: http://stackoverflow.com/posts/07-creating-a-100ajax-crud-using-rails-3-and-unobtrusive-javascript 312 Route to show with map map.save format. :action => 'news'.rss. onSuccess: function(transport) { var html = "<div align='left' id='map_info' style='min-width: 400px. got some hints on how to do the required changes from: http://stjhimy.x (or now 4.xml {render :xml=> @incidents} format.appspot.js.request".json { render json: @seat. Time.erb partial <% remote_form_for(incident) do |f| %> <%= form_for(incident.2. url:link. :action => 'show_with_map'. status: :created.rss. However.com/maps/documentation/javascript/examples/infowindow-simple http://stackoverflow. The javascript on the _map. The code must be edited to make it work with jquery.ajax({type: "GET". respond_to do |format| format.rss.html { redirect_to @seat.erb respond_to do |format| if @seat. throwing an error saying something like "cannot find incident with id news" 349 news method in incidents controller code in book works on 3.erb if update was ok else format.erb to show incident in the map.erb and save it on the same path as other seat templates (app/views/seats).connect 'incidents/news'.erb file is incorrect.rb file. :controller => 'incidents' match 'incidents/map/:id'=> 'incidents#show_with_map' 330 add . :format=>'xml' the order is important. success: function(data){ var contentString = "<div align='left' id='map_info' style='minwidth: 400px.com/questions/8142265/jquery-ajax-get-response 372 second line on the _new. xml.html.Request(link.2.now.Rails 3. the info window with the content is not shown. when trying it. {:action=>'news'})%> In this case the format needs to be specified so the url in the link is build properly as localhost:3000/incidents/news.flight #1 need to pass the flight to the js. width: 400px.js {@seat} #3 this calls the js. this way the adress in the bar will be http://localhost:3000/incidents/news. mark1.rss which looks more like an actual feed 353 autodicovery tag <%= auto_discovery_link_tag(:rss.js {@seat} #2 this calls the js.

The code was intended for Prototype (Rails 2 preferred javascript library) so it needs to be params.js format. marker.replaceWith("<%= new_incident%>").new(params[:incident]) respond_to do |format| if @incident. so that the html is rendered correctly in the popup box 379-396 add link to edit in the _show. :remote => true %> link_to_remote is deprecated.rb partial should be: <% remote_form_for(incident.mountain %> </p> <p> <b>When:</b> <%= @incident.html. we need to use link_to.Request(new_path(). min-height: 300px. :update=>'map_info'. longitude: point. onSuccess: function(transport) { marker.openInfoWindowHtml(contentString). updated to use JQuery instead params. { var contentString = "<div align='left' id='map_info' style='minmethod: 'get'.set("longitude".errors. format. status: :unprocessable_entity } end end end 377-378 refresh popup after adding a new incident Not in book <% new_incident = escape_javascript(render(:partial => 'show'. width: 400px.html.y).js and a new template create.json { render json: @incident.html.description %> </p> <%= link_to 'Edit'.erb partial. status: :created.html { redirect_to @incident.json { render json: @incident.' } format.14 this changes to: <%= form_for(incident.js format. height: dataType: 'html' 300px.2.Rails 3. $. url: new_path(). height: 300px. data: {latitude: point.'> <p id="notice"><%= notice %></p> <p> <b>Mountain:</b> <%= @incident.js. :locals This is the code that goes into the create. transport. location: @incident } end end Notes remote_form_for was deprecated for rails 3 . with :remote => true. notice: 'Incident was successfully created. location: @incident } else format.title %> </p> <p> <b>Description:</b> <%= @incident. status: :created. min-height: 300px.html. 377-378 refresh popup after adding a new incident in page 377-378 it says that the start of the form in the _new. :remote => true) do |f| %> # GET /incidents/1/edit def edit @incident = Incident. Lines 166-177 need to be changed var params = new Hash().x) Page To: Head First (Rails 2.js. point. success: function(data){ new Ajax.x}. edit_incident_path(@incident).when %> </p> <p> <b>Title:</b> <%= @incident.erb partial and replace with _edit. width: 400px.x) Changes Needed 372-373 NOT IN THE BOOK.erb needs to be created def create @incident = Incident. point. height: 300px.responseText + "</div>".x (or now 4.html. Edit file: _map.erb partial and replace with _edit.erb file => {:incident => @incident}))%> $("#map_info"). width: 400px.x). 377-378 refresh popup after adding a new incident Not in book <div align='left' id='map_info' style='min-width: 400px.erb partial <%= link_to_remote 'Edit'.:update=>'map_info') do |f| %> 377-378 refresh popup after adding a new incident In pages 377-378 the book says that no change is needed The create method response needs to specif a javascript response: this is needed to produce the behavior that remote_form_for used to provide for the create method.html.erb to show input form in the map.'>" + }). width: 400px. var html = "<div align='left' id='map_info' style='min}. :url=> edit_incident_url(@incident) %> <%= link_to 'Edit'. but the update action is not handled like in prototype so more code is needed 379-396 add link to edit in the _show. :remote => true %> </div> The map_info <div> needs to be added to the _show.save format.json { render json: @incident. data + "</div>".ajax({type: "GET". edit_incident_path(@incident).find(params[:id]) respond_to do |format| format.y. min-height: 300px. width: 400px.'>" + parameters: params.html format.html.openInfoWindowHtml(html).html { render action: "new" } format.set("latitude".erb partial Not in book # GET /incidents/1/edit this is needed to produce the behavior that remote_form_for used to provide The edit method in the incidents controller needs to be modified to respond with javascript as follows: For Rails 3. } }).

:locals => This is the code that goes into the edit.html.html.text_field :mountain %> </p> <%= f.erb partial Not in book <% edit_incident = escape_javascript(render(:partial => 'edit'.js.'> <h1>Editing incident</h1> <%= form_for(incident.text_field :title %> </p> <div class="field"> <%= f.erb partial and replace with _edit.erb partial Not in book <% edit_incident = escape_javascript(render(:partial => 'edit'.erb partial and replace with _edit.text_area :description.erb partial Not in book <div align='left' id='map_info' style='min-width: 400px.js. min-height: 300px.submit %> </div> <%end%> </div> The map_info <div> needs to be added to the _edit.x) Changes Needed 379-396 add link to edit in the _show.label :description %><br /> <%= f.html.erb partial and replace with _edit.html.html.Rails 3.html. height: 300px.replaceWith("<%= edit_incident%>").html.erb template file {:incident => @incident}))%> $("#map_info").label :mountain %> <%= f. :locals => This is the code that goes into the edit.hidden_field :longitude %> <p> <%= f.:rows=>3 %> </div> <div class="actions"> <%= f. :remote=>true) do |f| %> <p> <%= f.hidden_field :latitude %> <%= f.label :title %> <%= f.erb partial. 379-396 add link to edit in the _show.replaceWith("<%= edit_incident%>").datetime_select :when %> </p> <p> <%= f.erb template file {:incident => @incident}))%> $("#map_info"). Notes 379-396 add link to edit in the _show. so that the html is rendered correctly in the popup box . width: 400px.x (or now 4.x) Page To: Head First (Rails 2.label :when %> <%= f.

14 116 metoda Ad. can also use the short form > rails g model . :controller=>'ads'.14 76 create a route map. (rails 4)<%= form_for @ad.show) Add phone field to 3 views files (index.14 this is the routing used in Rails 3.. show and _form 48 excercise solution rails mebay rails new mebay 50 generate model > ruby script/generate model . :action=>'update' 148 routes map.down def self. _form. :controller=>'ads'..css in /public/stylesheets put default. to: 'ads#show' (rails 4)get '/ads/:id' => 'ad#show' (also rails 4)get '/ads/:id'.connect '/ads/:id/delete'.id %>/edit">Edit</a> 138 routes map..2.. Not sure if the book includes this but it could help 11 generate scaffolding code > ruby script/generate scaffold .x (or now 4.require(:ticket).. :controller=>'ads'. if using Rails 3.2. to: 'ads#edit' put'/ads/:id'. 34 generate migration > ruby script/generate migration .. can also use the short form > rails g scaffold .x) Page To: Head First (Rails 2. > rails generate model .erb. :action=>'edit' map.erb.if use rauls 4. > rails generate migration . to: 'ads#update' or patch'/ads/:id'. not needed.. to: 'ads#destroy' In this case both work but the second one is the convention this is the routing used in Rails 3.rb model file. it is on by default in all view templates. :action=>'destroy' get '/ads/new'. show.x) Changes Needed 7 create new rails application > rails tickets > rails new tickets Not in book specify rails version 8 start built-in web server Notes > rails _3.x. _form. :email_address) end " and add ":phone" after :email_address if not then it will throw error: "Can't mass-assign protected attributes: phone" when clicking on create or update button (Required from Rails 3. :controller=>'ads'.0 is out and may be your default install.. the only difference is that _form now is called inside edit and new so one less form to edit..find(:all) kod w notatce. 2 (if u use rails 3..x use this way)Must also add “:phone” to the list of attributes after attr_accessible in ticket. > rails generate scaffold . it is on by default in all view templates.. :phone. 122 params[:ad] 138 link to edit <a href="/ads/<%= @ad. 40 excercise solution ruby script/generate scaffold .14 Rails 3 needs the "=" kod w notatce. action: :edit %> get '/ads/:id/edit'. Also add “:phone” to the list of attributes after attr_accessible in ticket. but the convention is <%= stylesheet_link_tag "application". :phone end end 36-37 add phone_no add phone field to 4 views files (index.. :seat_id_seq.8 or above 1 Add phone field to 3 views files (index..14 .down remove_column :tickets. :controller=>'ads'. new.. to: 'ads#create' get '/ads'.html.connect '/ads/:id/update'.2.2..connect 'ads/id'. :action=>'create' map.rb model file. :controller=>'ads'... to: 'ads#index' get '/ads/:id'. Trying to change the version in the Gemfile after installing using rails4 will cause problems later. :media => "all" %> Cory wrote: "When I worked on chapter two I had to play with the stylesheet to get the images to display..html..rb) (but .. :string end end the code generated by rails 3 is different. :address. can also use the short form > rails g migration . I had to remove the /images/ from the path.find(:all) Ad... :action=>'show' (rails 3)match '/ads/:id'.2.connect '/ads/:id/edit'.2. 52 generate controller > ruby script/generate controller > rails generate controller . :phone. :controller=>'ads'. najedź kursorem [4] <%= link_to :Edit.erb.x at the start. > rails generate scaffold ." map.html. to: 'ads#show' <%= form_for .erb. call raw(string).html.up add_column :tickets.edit..rb) and then find "def ticket_params params..permit(:name. :string end class AddPhoneToTickets < ActiveRecord::Migration def change add_column :tickets. To check your default rails version >rails -v will >>version# you're using by default. to: 'ads#show' this is the routing used in Rails 3.) similar to what is indicated in pages 36-37. :action=>'new' map. to: 'ads#index' this is the routing used in Rails 3.connect '/ads/new'.html. :controller=>'ads'.erb. If you want the unescaped string. edit..connect '/ads/'. url: {action: "create"} do |f| %> this is the routing used in Rails 3.x) you should edit (app/controller/ticket_controller.. can also use the short form > rails g controller . to: 'ads#update' get '/ads/:id/delete'.. 57 create a route map.. show need to change only 3: index.css' put images in /public/images put images in /app/assets/images put default. :action=>'index' map. to: 'ads#new' post '/ads/create'..html.css' 'default.css in /app/assets/stylesheets In rails 3 you no longer need to call h(string) to escape HTML output. :controller=>'ads'.x_ new app_name rails 4.%> to escape html escaped by default in rails 3 In rails 3 you no longer need to call h(string) to escape HTML output.2.Rails 3. the method change replaces self.connect '/ads/:id'. 35 the code of the migration class AddPhoneToTickets < ActiveRecord::Migration def self. > ruby script/server > rails s fd 8 > ruby script/server -p 8000 > rails s -p 8000 there is also a long form for this > rails server and >rails server -p 8000 Not in book stop server press keys "ctrl" and "c" together press keys "ctrl" and "c" together in windows you need to press "ctrl" and "pause/break".connect '/ads/'..up and self. show. najedź kursorem [3] 95 refer to a stylesheet 95 97 97 edit css 108 routes 112 code line 2 'default. 41 excercise solution asks about which four files to change index..8) QA comment on the need of =h The book highlights the use of <%=h .erb. (app/models/ticket. call raw(string).new.) similar to what is indicated in pages 36-37. :action=>'show' <% form_for . If you want the unescaped string. You may want to change it to 3..connect '/ads/create'. :action=>'index' match '/ads'. :price_paid.

capacity errors[:base]<< "The flight is fully booked" end end end 268 route map.add(:baggage.seats} end def flight_seats @flight = Flight.id}" else render action: "new" end <%= render partial: 'seats/new_seat'> No error here. :name belongs_to :flight validate :baggage_allowance_not_exceeded.save() redirect_to "/ads/#{@ad. jquery replaced prototype as the javascript library 273-275 placing the div id modify views/flights/show. <%= form_tag . You can see: http://stackoverflow. Edit the config/routes. :flight_capacity_not_exceeded Custom validators are declared differently in rails 3 def validate if baggage > flight.size >= flight. by default the javascript libraries are included with: <%= javascript_include_tag "application" %> In rails 3. the first method will add a custom error message linked to the baggage field 4..html#custom-validators def flight_capacity_not_exceeded if flight. by default the form is associated with the 'post' method but the correct one should be 'get' Specify the route to 'find' and select that route in the form_tag as follows.Rails 3.add_to_base" use "errors[:base]<<" for more details see: http://edgeguides. :method => :get do %> 210 redirect syntax if @ad.save() redirect_to "/ads/#{@ad.9+ 243-246 partial for listing booked seats <%= auto_discovery_link_tag(:rss. leave it under seats and reference to it as shown 249-259 custom validators class Seat < ActiveRecord::Base attr_accessible :baggage. the second method will add a generic message related to the capacity of the flight being exceeded. this form can be modified as needed and left with the other seat files instead of copying it. need to specify that the validation is needed 3.8 then render should be: <%= render :partial => 'seats/new_seat'> def baggage_allowance_not_exceeded if baggage > flight. Instead of "erros. :locals=>{:seats=>@flight.html.2. the book sample will work on both but the new syntax is recomended to get used working with ruby 1.html.. :action=>'flight_seats'.rubyonrails.html.rb file to look like this resources :client_workouts do collection do get 'find' end end And edit the first line of the form_tag in app/views/layouts/application. :locals=>{:seats=>@flight.html.x) Page To: 164 code line 11 167 routes Head First (Rails 2.add_to_base("The flight is fully booked") end end if @ad.erb to include: <div id="seats"> <%= render :partial=>"seats/seat_list".seats. this is a syntax change if using ruby 1..:format=>:rss})%> In this case the book is right on suggesting building the partial from the index on seats. {:action=>'news'. :locals=>{:seats=>@flight.org/active_record_validations.x) Changes Needed Notes <% form_tag .erb <%= render :partial=>"seats/seat_list".error_messages %> 224-231 partial for new bookings suggests using app/views/seats/new.new} %> %> Again.add_to_base("You have too much baggage") end if flight.size >= flight_capacity errors.rb to look like this <%= form_tag "/client_workouts/find".new} <%= render partial: 'seats/new_seat'.x (or now 4.seats} end Just change so the seats partial stays with the rest of the seats templates and partials 272 include AJAX Libraries Book describes how to add prototype to the layout for handling javascript This is not needed.find(params[:flight_id]) render :partial=>"flights/seat_list". :controller=>'seats' resources :seats do collection do get :flight_seats end end after some tests this is the best way to specify this route routing in Rails 3.com/questions/3873190/f-error-messages-in-rails-3-0 rails 3 creates a form that is used both for edit and new on seats.html.14 269 partial for listing booked seats def flight_seats @flight = Flight.seats}%> .erb to include: write the div inside views/seats/_seat_list. Notice the syntax change.9+.error_message was deprecated for rails 3. locals: {seat: Seat.erb and copying into seats and modifying 235 passing the seat to the partial <%= render :partial=>"new_seat".seats}%> </div> modify views/flights/show.baggage_allowance errors. "You have too much baggage") end end 1.connect '/flights/:flight_id/seats'. :flight_id. the code in the book will work on rails 3 but the syntax has changed and could also be written as shown on the second column f. The partial can be directly loaded into the show flight template from there.9+. If using ruby 1.id}" else render :template=> "ads/new" end 212 error messages <%= f. :locals=>{:seats=>@flight. just do not copy the file into flights. This requires less modifications to the partial as there is no links to remove. Rails 3 needs the "=" Book says that routes do not need to be modified Need to specify the root.baggage_allowance errors. :locals=>{:seat=>Seat.find(params[:flight_id]) render :partial=>"seats/seat_list".seats.. this is valid for ruby 1. need to separate and name each validator 2.

use link_to. :id => @flight.save respond_to do |format| page.js so the js.flight #1 need to pass the flight to the js. generating javascript code that is returned for updating list of seats.x) Changes Needed Notes 273-275 put div inside _seat_list. status: :created.Rails 3. :partial => 'flights/seat_list'.id. 280 autorefresh <%= periodically_call_remote .new(params[:seat]) @seat = Seat.js. seat %></td> <td><%= link_to 'Edit'.replace_html 'notice'.html. Use the code to create a file called flight_seats. action: :flight_seats. notice: 'Seat was successfully else booked. the controller will look for it in there. so it needs to be in the partial <table> <tr> <th>Name</th> <th>Baggage</th> <th></th> <th></th> <th></th> </tr> <% seats. data: "id=<%= @flight. <%= javascript_tag do -%> $(document). with :remote => true. # Changes required on rails 3 record def create Lines #2 and #3 indicate what to do if the method is called with remote set to true (js call) def create @seat = Seat. add the code at the bottom of the /app/views/flights/show.. url: "/seats/flight_seats/". 'Seat was successfully if @seat.each do |seat| %> <tr> <td><%= seat.5000) }). The first javascript sets the counter to 5000 milliseconds (= 5 seconds). :locals=>{:seats=>@flight.:update=>'seats') do |f| %> 288-292 refresh list when adding a new #Changes required in the create method: Lines #1. :locals => {:seats => @flight.ready( function(){setInterval("refresh_seats()". Line #1 will get the flight which will be used for reloading the seats list.replace_html 'notice'.erb.seats } format. controller: :seats.seats}))%> $("#seats"). else :locals => {:seats => @seat. but the updater is not generated so more code is needed.' } page.json { render json: @seat.id%>".html { redirect_to @seat. method: :delete. function refresh_seats(){ $.baggage %></td> <td><%= link_to 'Show'.erb Not in book <% updated_list = escape_javascript(render(:partial => 'seat_list'.the seat could not format.new(params[:seat]) render :update do |page| @flight = @seat. That is all that's required 285-287 refresh list when adding a new in page 287 it says change: record <% form_for(seat) do |f| %> to <% remote_form_for(seat. :remote => true %> link_to_remote is not used anymore.html.save booked' format.js {@seat} #3 this calls the js. the <div> would be lost after first call. edit_seat_path(seat) %></td> <td><%= link_to 'Destroy'. method: :get.erb if update was ok page. 'Sorry .json { render json: @seat. location: @seat be booked' } end format.html {render :partial=>"seats/seat_list".js.erb is rendered. seat.x (or now 4.erb and save it on the same path as other seat templates (app/views/seats).x) Page To: Head First (Rails 2. This is the code that does the replacement. } <% end -%> link_call_remote was deprecated on rails 3.js end end Add respond_to and format. but the updater is not generated so more code is needed 273-275 Edit controller method to return javascript Not in book def flight_seats @flight = Flight.ajax({type: "GET". :remote => true) do |f| %> remote_form_for was deprecated for rails 3 ..errors.erb if update was not ok end end end in Rails 3 the change needed is from: <%= form_for(seat) do |f| %> to <%= form_for(seat. status: end :unprocessable_entity } format.html { render action: "new" } end format. <%= link_to "refresh seats".name %></td> <td><%= seat..seats}} format.erb Not in book <div id="seats"> <h1>Listing seats</h1> when replaceWith is called from javascript.#2 and #3. The second function calls the flight_seats method on the seats controller.js {@seat} #2 this calls the js.flight.erb if @seat.find(params[:id]) respond_to do |format| format. data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </table> <br /> </div> 273-275 link to refresh <%= link_to_remote .replace_html 'seats'. dataType: "script" }).com/questions/4016285/rails-3-simple-ajaxy-page-updates 273-275 Create js template: flight_seats.. Much of these was adapted from the response of EdJones on http://stackoverflow.replaceWith("<%= updated_list%>").

then drag the rss icon to the toolbar.erb partial <% remote_form_for(incident) do |f| %> <%= form_for(incident.'>" + data + "</div>". mark1.request". This is because the original code was made to work with the old JavaScript library for Rails (Prototype).14 this code will work and return three types of data: rss. :controller => 'incidents' match 'incidents/map/:id'=> 'incidents#show_with_map' 330 add .rss { render :layout => false } #news.x) Changes Needed 292-306 New js template: create. mark1. location: @seat } format. width: 400px.openInfoWindowHtml(html).Request(link. Lines 5157 need to be changed new Ajax.:format'. :update=>'map_info'.x) Page To: Head First (Rails 2.erb if update was not ok end end end this js template will update the list and clean the form if the creation succeeds or present the error if it does not.appspot.Rails 3.14 Looking at the documentation of the GoogleMaps JavaScript API and examples on Stackoverflow helped in getting the code right. If format is not specified the redirection when clicking the RSS feed buton will not work NOTE: Browsers do not automathically display the rss button on the address bar(box) for explorer. json. :controller => 'incidents' match 'incidents/map/:id'=> 'incidents#show_with_map' 345 route to news map. }.rss.connect 'incidents/news'.com/questions/8142265/jquery-ajax-get-response 372 second line on the _new.connect 'incidents/map/:id'.js {@seat} #2 this calls the js.find(:all. EXPLORER: the rss button is in the command bar. the info window with the content is not shown.html. Just need to name the builder template as news.html { render action: "new" } format.json { render json: @incidents } end end 352 builder file code in book works on 3. dataType: 'html' The code in the book from pages 361-365 should work OK. this needs to go before the resources :incidents line in the routes.js. if the bar is hidden just rightclick on the top of the browser and select Command bar to see the icon 360 include AJAX Libraries Book describes how to add prototype to the layout for handling javascript This is not needed.2.com/posts/07-creating-a-100ajax-crud-using-rails-3-and-unobtrusive-javascript 312 Route to show with map map. Time. :remote=>true) do |f| %> remote_form_for was deprecated for rails 3 .yesterday]) not necesary in rails 3. status: :created. when trying it. this way the adress in the bar will be http://localhost:3000/incidents/news. onSuccess: function(transport) { var html = "<div align='left' id='map_info' style='min-width: 400px.rss.rss which looks more like an actual feed 353 autodicovery tag <%= auto_discovery_link_tag(:rss.rss. using firebug it appears that the problem is the call "new Ajax.json { render json: @seat. The javascript on the _map. min-height: 300px.erb file is incorrect.builder. got some hints on how to do the required changes from: http://stjhimy. } $.flight #1 need to pass the flight to the js.html { redirect_to @seat. :conditions=>['[when] >= ?'.now.:format to path map. However. throwing an error saying something like "cannot find incident with id news" 349 news method in incidents controller code in book works on 3.new(params[:seat]) @flight = @seat.14 The builder works as expected but it can also be named news.builder def news @incidents = Incident.erb and save it on the same path as other seat templates (app/views/seats).ajax({type: "GET". If it is placed afte it will not work.connect 'incidents/map/:id.erb Not in book Notes # Changes required on rails 3 def create @seat = Seat. height: 300px. width: 400px. '. :format=>'xml' the order is important. References: http://stackoverflow.errors.json { render json: @seat. status: :unprocessable_entity } format.erb to show incident in the map.com/maps/documentation/javascript/examples/infowindow-simple http://stackoverflow.xml {render :xml=> @incidents} format. notice: 'Seat was successfully booked.js.com/questions/5544871/jquery-equivalent-to-prototype-ajax-request https://googledevelopers. by default the javascript libraries are included with: <%= javascript_include_tag "application" %> In rails 3.erb respond_to do |format| if @seat.openInfoWindowHtml(contentString).' } format. :action => 'show_with_map'.rss.'>" + transport. jquery replaced prototype as the javascript library 362-366 NOT IN THE BOOK. Edit file: _map. :controller match 'incidents/news'=> 'incidents#news' => 'incidents'.responseText + "</div>".builder format. go to settings/extensions and click on get extensions then look for rss subscription extension and click on the add button (it is free) FIREFOX: from the menu go to options/toolbar layout or right click on the toolbar and select customise. { method: 'get'. success: function(data){ var contentString = "<div align='left' id='map_info' style='minwidth: 400px.:format' is implicit in all routes.2.rb file. height: 200px.html.save format. url:link. xml.js {@seat} #3 this calls the js.html.erb if update was ok else format. respond_to do |format| format. :action => 'news'. firefox and chrome do: CRHOME: the rss feed is a plugin that needs to be added. {:action=>'news'})%> In this case the format needs to be specified so the url in the link is build properly as localhost:3000/incidents/news. the javascript library for rails 3. min-height: 200px. The code must be edited to make it work with jquery.x (or now 4. the controller will look for it in there.2. :action => 'show_with_map'. Use the code to create a file called create.

html.json { render json: @incident. The code was intended for Prototype (Rails 2 preferred javascript library) so it needs to be params.openInfoWindowHtml(contentString). :remote => true) do |f| %> # GET /incidents/1/edit def edit @incident = Incident. we need to use link_to. data: {latitude: point.title %> </p> <p> <b>Description:</b> <%= @incident. width: 400px.x) Page To: Head First (Rails 2. :remote => true %> </div> The map_info <div> needs to be added to the _show. status: :created.errors.replaceWith("<%= new_incident%>").html format.y. width: 400px. format.html.erb partial.set("longitude". url: new_path(). so that the html is rendered correctly in the popup box 379-396 add link to edit in the _show. height: 300px.erb file => {:incident => @incident}))%> $("#map_info").x (or now 4. :remote => true %> link_to_remote is deprecated. var html = "<div align='left' id='map_info' style='min}.html.' } format.html.x}.js and a new template create.'> <p id="notice"><%= notice %></p> <p> <b>Mountain:</b> <%= @incident. min-height: 300px.x). location: @incident } else format. :url=> edit_incident_url(@incident) %> <%= link_to 'Edit'.openInfoWindowHtml(html).erb partial <%= link_to_remote 'Edit'. edit_incident_path(@incident). } }). width: 400px. Lines 166-177 need to be changed var params = new Hash(). success: function(data){ new Ajax. 377-378 refresh popup after adding a new incident Not in book <div align='left' id='map_info' style='min-width: 400px. transport. 377-378 refresh popup after adding a new incident in page 377-378 it says that the start of the form in the _new. marker. status: :unprocessable_entity } end end end 377-378 refresh popup after adding a new incident Not in book <% new_incident = escape_javascript(render(:partial => 'show'.:update=>'map_info') do |f| %> 377-378 refresh popup after adding a new incident In pages 377-378 the book says that no change is needed The create method response needs to specif a javascript response: this is needed to produce the behavior that remote_form_for used to provide for the create method. :locals This is the code that goes into the create. but the update action is not handled like in prototype so more code is needed 379-396 add link to edit in the _show.erb partial Not in book # GET /incidents/1/edit this is needed to produce the behavior that remote_form_for used to provide The edit method in the incidents controller needs to be modified to respond with javascript as follows: For Rails 3. { var contentString = "<div align='left' id='map_info' style='minmethod: 'get'.set("latitude".html { redirect_to @incident. height: dataType: 'html' 300px.json { render json: @incident. point.js format.description %> </p> <%= link_to 'Edit'. onSuccess: function(transport) { marker.erb partial and replace with _edit.rb partial should be: <% remote_form_for(incident.html. edit_incident_path(@incident).erb needs to be created def create @incident = Incident.responseText + "</div>".mountain %> </p> <p> <b>When:</b> <%= @incident. width: 400px.html { render action: "new" } format. $. notice: 'Incident was successfully created.14 this changes to: <%= form_for(incident.ajax({type: "GET". with :remote => true.html. min-height: 300px. width: 400px.Request(new_path().Rails 3.'>" + parameters: params.erb partial and replace with _edit. Edit file: _map. min-height: 300px. :update=>'map_info'.js format. data + "</div>".html.'>" + }).save format. point.find(params[:id]) respond_to do |format| format.js. status: :created.new(params[:incident]) respond_to do |format| if @incident.y). location: @incident } end end Notes remote_form_for was deprecated for rails 3 .when %> </p> <p> <b>Title:</b> <%= @incident. updated to use JQuery instead params. height: 300px. longitude: point.erb to show input form in the map.2.json { render json: @incident.x) Changes Needed 372-373 NOT IN THE BOOK.js.

:locals => This is the code that goes into the edit. Notes 379-396 add link to edit in the _show. width: 400px.x) Page To: Head First (Rails 2.text_area :description.erb partial.label :when %> <%= f.html.label :description %><br /> <%= f.replaceWith("<%= edit_incident%>").replaceWith("<%= edit_incident%>"). :remote=>true) do |f| %> <p> <%= f.js.html.hidden_field :longitude %> <p> <%= f. 379-396 add link to edit in the _show.erb partial Not in book <div align='left' id='map_info' style='min-width: 400px.erb partial Not in book <% edit_incident = escape_javascript(render(:partial => 'edit'.text_field :title %> </p> <div class="field"> <%= f.datetime_select :when %> </p> <p> <%= f.:rows=>3 %> </div> <div class="actions"> <%= f.Rails 3.submit %> </div> <%end%> </div> The map_info <div> needs to be added to the _edit. min-height: 300px.x (or now 4.hidden_field :latitude %> <%= f.html.html. height: 300px.erb partial and replace with _edit.label :mountain %> <%= f.erb partial and replace with _edit.'> <h1>Editing incident</h1> <%= form_for(incident.erb template file {:incident => @incident}))%> $("#map_info").html. :locals => This is the code that goes into the edit.js.text_field :mountain %> </p> <%= f. so that the html is rendered correctly in the popup box .html.x) Changes Needed 379-396 add link to edit in the _show.erb partial and replace with _edit.erb partial Not in book <% edit_incident = escape_javascript(render(:partial => 'edit'.label :title %> <%= f.erb template file {:incident => @incident}))%> $("#map_info").html.

save end [3] def index @ads = Array. :img_url) @ad = Ad.new Ad.find_each do |a| @ads.[1] def index @ads = Array.create(ad_params) @ad. :price.permit(:name. :description.new Ad. :email.require(:ad). :img_url) @ad = Ad.create(ad_params) @ad. :email.push(a) end end [4] def create ad_params = params. :description.save end . :seller_id.find_each do |a| @ads. :price.permit(:name. :seller_id.require(:ad).push(a) end end [2] def create ad_params = params.