diff options
Diffstat (limited to 'guides/source')
-rw-r--r-- | guides/source/active_record_querying.textile | 16 | ||||
-rw-r--r-- | guides/source/active_record_validations_callbacks.textile | 2 | ||||
-rw-r--r-- | guides/source/active_support_core_extensions.textile | 2 | ||||
-rw-r--r-- | guides/source/configuring.textile | 5 | ||||
-rw-r--r-- | guides/source/engines.textile | 2 | ||||
-rw-r--r-- | guides/source/generators.textile | 2 | ||||
-rw-r--r-- | guides/source/getting_started.textile | 189 |
7 files changed, 184 insertions, 34 deletions
diff --git a/guides/source/active_record_querying.textile b/guides/source/active_record_querying.textile index 98937266ba..902ceeb78b 100644 --- a/guides/source/active_record_querying.textile +++ b/guides/source/active_record_querying.textile @@ -356,20 +356,6 @@ Client.where("created_at >= :start_date AND created_at <= :end_date", This makes for clearer readability if you have a large number of variable conditions. -h5(#array-range_conditions). Range Conditions - -If you're looking for a range inside of a table (for example, users created in a certain timeframe) you can use the conditions option coupled with the +IN+ SQL statement for this. If you had two dates coming in from a controller you could do something like this to look for a range: - -<ruby> -Client.where(:created_at => (params[:start_date].to_date)..(params[:end_date].to_date)) -</ruby> - -This query will generate something similar to the following SQL: - -<sql> - SELECT "clients".* FROM "clients" WHERE ("clients"."created_at" BETWEEN '2010-09-29' AND '2010-11-30') -</sql> - h4. Hash Conditions Active Record also allows you to pass in hash conditions which can increase the readability of your conditions syntax. With hash conditions, you pass in a hash with keys of the fields you want conditionalised and the values of how you want to conditionalise them: @@ -392,8 +378,6 @@ NOTE: The values cannot be symbols. For example, you cannot do +Client.where(:st h5(#hash-range_conditions). Range Conditions -The good thing about this is that we can pass in a range for our fields without it generating a large query as shown in the preamble of this section. - <ruby> Client.where(:created_at => (Time.now.midnight - 1.day)..Time.now.midnight) </ruby> diff --git a/guides/source/active_record_validations_callbacks.textile b/guides/source/active_record_validations_callbacks.textile index 88c4481e5e..f49d91fd3c 100644 --- a/guides/source/active_record_validations_callbacks.textile +++ b/guides/source/active_record_validations_callbacks.textile @@ -1064,6 +1064,7 @@ Additionally, the +after_find+ callback is triggered by the following finder met * +find_all_by_<em>attribute</em>+ * +find_by_<em>attribute</em>+ * +find_by_<em>attribute</em>!+ +* +find_by_sql+ * +last+ The +after_initialize+ callback is triggered every time a new object of the class is initialized. @@ -1076,7 +1077,6 @@ Just as with validations, it is also possible to skip callbacks. These methods s * +decrement_counter+ * +delete+ * +delete_all+ -* +find_by_sql+ * +increment+ * +increment_counter+ * +toggle+ diff --git a/guides/source/active_support_core_extensions.textile b/guides/source/active_support_core_extensions.textile index 5d0a3f82e8..e4a6e145b9 100644 --- a/guides/source/active_support_core_extensions.textile +++ b/guides/source/active_support_core_extensions.textile @@ -1131,7 +1131,7 @@ h4. Output Safety h5. Motivation -Inserting data into HTML templates needs extra care. For example you can't just interpolate +@review.title+ verbatim into an HTML page. On one hand if the review title is "Flanagan & Matz rules!" the output won't be well-formed because an ampersand has to be escaped as "&amp;". On the other hand, depending on the application that may be a big security hole because users can inject malicious HTML setting a hand-crafted review title. Check out the "section about cross-site scripting in the Security guide":security.html#cross-site-scripting-xss for further information about the risks. +Inserting data into HTML templates needs extra care. For example, you can't just interpolate +@review.title+ verbatim into an HTML page. For one thing, if the review title is "Flanagan & Matz rules!" the output won't be well-formed because an ampersand has to be escaped as "&amp;". What's more, depending on the application, that may be a big security hole because users can inject malicious HTML setting a hand-crafted review title. Check out the "section about cross-site scripting in the Security guide":security.html#cross-site-scripting-xss for further information about the risks. h5. Safe Strings diff --git a/guides/source/configuring.textile b/guides/source/configuring.textile index 1541428af9..68426221bf 100644 --- a/guides/source/configuring.textile +++ b/guides/source/configuring.textile @@ -362,7 +362,7 @@ h4. Configuring Action View Proc.new { |html_tag, instance| %Q(<div class="field_with_errors">#{html_tag}</div>).html_safe } </ruby> -* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+. +* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+. If you want your form builder class to be loaded after initialization (so it's reloaded on each request in development), you can pass it as a +String+ * +config.action_view.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then used to log information from Action View. Set to +nil+ to disable logging. @@ -525,7 +525,8 @@ development: password: </yaml> -If you use external connection pool manager, you can disable prepared statements in rails: +Prepared Statements can be disabled thus: + <yaml> production: adapter: postgresql diff --git a/guides/source/engines.textile b/guides/source/engines.textile index 36210aedb0..71bcf6b713 100644 --- a/guides/source/engines.textile +++ b/guides/source/engines.textile @@ -695,7 +695,7 @@ If a template is rendered from within an engine and it's attempting to use one o h4. Assets -Assets within an engine work in an identical way to a full application. Because the engine class inherits from +Rails::Engine+, the application will know to look up in the engine's +app/assets+ directory for potential assets. +Assets within an engine work in an identical way to a full application. Because the engine class inherits from +Rails::Engine+, the application will know to look up in the engine's +app/assets+ and +lib/assets+ directories for potential assets. Much like all the other components of an engine, the assets should also be namespaced. This means if you have an asset called +style.css+, it should be placed at +app/assets/stylesheets/[engine name]/style.css+, rather than +app/assets/stylesheets/style.css+. If this asset wasn't namespaced, then there is a possibility that the host application could have an asset named identically, in which case the application's asset would take precedence and the engine's one would be all but ignored. diff --git a/guides/source/generators.textile b/guides/source/generators.textile index e9d713d91d..2e9ab0526d 100644 --- a/guides/source/generators.textile +++ b/guides/source/generators.textile @@ -468,7 +468,7 @@ Replaces text inside a file. <ruby> gsub_file 'name_of_file.rb', 'method.to_be_replaced', 'method.the_replacing_code' -</ruby +</ruby> Regular Expressions can be used to make this method more precise. You can also use append_file and prepend_file in the same way to place code at the beginning and end of a file respectively. diff --git a/guides/source/getting_started.textile b/guides/source/getting_started.textile index 88d5ce6d9b..b48ebbceb2 100644 --- a/guides/source/getting_started.textile +++ b/guides/source/getting_started.textile @@ -45,10 +45,6 @@ internet for learning Ruby, including: h3. What is Rails? -TIP: This section goes into the background and philosophy of the Rails framework -in detail. You can safely skip this section and come back to it at a later time. -Section 3 starts you on the path to creating your first Rails application. - Rails is a web application development framework written in the Ruby language. It is designed to make programming web applications easier by making assumptions about what every developer needs to get started. It allows you to write less @@ -141,7 +137,7 @@ The +rails new blog+ command we ran above created a folder in your working direc h3. Hello, Rails! -One of the traditional places to start with a new language is by getting some text up on screen quickly. To do this, you need to get your Rails application server running. +To begin with, let's get some text up on screen quickly. To do this, you need to get your Rails application server running. h4. Starting up the Web Server @@ -153,7 +149,7 @@ $ rails server TIP: Compiling CoffeeScript to JavaScript requires a JavaScript runtime and the absence of a runtime will give you an +execjs+ error. Usually Mac OS X and Windows come with a JavaScript runtime installed. Rails adds the +therubyracer+ gem to Gemfile in a commented line for new apps and you can uncomment if you need it. +therubyrhino+ is the recommended runtime for JRuby users and is added by default to Gemfile in apps generated under JRuby. You can investigate about all the supported runtimes at "ExecJS":https://github.com/sstephenson/execjs#readme. -This will fire up an instance of a webserver built into Ruby called WEBrick by default. To see your application in action, open a browser window and navigate to "http://localhost:3000":http://localhost:3000. You should see the Rails default information page: +This will fire up WEBrick, a webserver built into Ruby by default. To see your application in action, open a browser window and navigate to "http://localhost:3000":http://localhost:3000. You should see the Rails default information page: !images/rails_welcome.png(Welcome Aboard screenshot)! @@ -165,7 +161,7 @@ h4. Say "Hello", Rails To get Rails saying "Hello", you need to create at minimum a _controller_ and a _view_. -A controller's purpose is to receive specific requests for the application. What controller receives what request is determined by the _routing_. There is very often more than one route to each controller, and different routes can be served by different _actions_. Each action's purpose is to collect information to provide it to a view. +A controller's purpose is to receive specific requests for the application. _Routing_ decides which controller receives which requests. Often, there is more than one route to each controller, and different routes can be served by different _actions_. Each action's purpose is to collect information to provide it to a view. A view's purpose is to display this information in a human readable format. An important distinction to make is that it is the _controller_, not the view, where information is collected. The view should just display that information. By default, view templates are written in a language called ERB (Embedded Ruby) which is converted by the request cycle in Rails before being sent to the user. @@ -404,7 +400,7 @@ turn should have a title attribute of type string, and a text attribute of type text. Rails in turn responded by creating a bunch of files. For now, we're only interested in +app/models/post.rb+ and +db/migrate/20120419084633_create_posts.rb+. The latter is responsible -for creating the dabase structure, which is what we'll look at next. +for creating the database structure, which is what we'll look at next. h4. Running a Migration @@ -416,7 +412,7 @@ and it's possible to undo a migration after it's been applied to your database. Migration filenames include a timestamp to ensure that they're processed in the order that they were created. -If you look in the +db/migrate/20100207214725_create_posts.rb+ file (remember, +If you look in the +db/migrate/20120419084633_create_posts.rb+ file (remember, yours will have a slightly different name), here's what you'll find: <ruby> @@ -465,7 +461,7 @@ invoking the command: <tt>rake db:migrate RAILS_ENV=production</tt>. h4. Saving data in the controller -Back into +posts_controller+, we need to change the +create+ action +Back in +posts_controller+, we need to change the +create+ action to use the new +Post+ model to save data in the database. Open that file and change the +create+ action to look like the following: @@ -835,7 +831,7 @@ Moving on, we need to add the +update+ action. The file +config/routes.rb+ will need just one more line: <ruby> -put "posts/:id/update" +put "posts/:id" => "posts#update" </ruby> And the +update+ action in +posts_controller+ itself should not look too complicated by now: @@ -923,13 +919,182 @@ The +show+ view will automatically include the content of the as to not be confused with regular views. However, you don't include the underscore when including them with the +helper+ method. -TIP: You can red more about partials in the "Layouts and Rendering in +TIP: You can read more about partials in the "Layouts and Rendering in Rails":layouts_and_rendering.html guide. Our +edit+ action looks very similar to the +new+ action, in fact they both share the same code for displaying the form. Lets clean them up by using a +_form+ partial. +Create a new file +app/views/posts/_form.html.erb+ with the following +content: + +<erb> +<%= form_for @post do |f| %> + <% if @post.errors.any? %> + <div id="errorExplanation"> + <h2><%= pluralize(@post.errors.count, "error") %> prohibited + this post from being saved:</h2> + <ul> + <% @post.errors.full_messages.each do |msg| %> + <li><%= msg %></li> + <% end %> + </ul> + </div> + <% end %> + <p> + <%= f.label :title %><br> + <%= f.text_field :title %> + </p> + + <p> + <%= f.label :text %><br> + <%= f.text_area :text %> + </p> + + <p> + <%= f.submit %> + </p> +<% end %> +</erb> + +Everything except for the +form_for+ declaration remained the same. I'll +explain later how +form_for+ can figure out the right +action+ and ++method+ attributes when building the form, for now let's update the ++new+ and +edit+ views: + +<erb> +# app/views/posts/new.html.erb + +<h1>New post</h1> + +<%= render 'form' %> + +<%= link_to 'Back', :action => :index %> + + +# app/views/posts/edit.html.erb + +<h1>Edit post</h1> + +<%= render 'form' %> + +<%= link_to 'Back', :action => :index %> +</erb> + +Point your browser to +"http://localhost:3000/posts/new":http://localhost:3000/posts/new and +try creating a new post. Everything still works. Now try editing the +post and you'll receive the following error: + +!images/getting_started/undefined_method_post_path.png(Undefined method +post_path)! + +To understand this error, you need to understand how +form_for+ works. +When you pass an object to +form_for+ and you don't specify a +:url+ +option, Rails will try to guess the +action+ and +method+ options by +checking if the passed object is a new record or not. Rails follows the +REST convention, so to create a new +Post+ object it will look for a +route named +posts_path+, and to update a +Post+ object it will look for +a route named +post_path+ and pass the current object. Similarly, rails +knows that it should create new objects via POST and update them via +PUT. + +If you run +rake routes+ from the console you'll see that we already +have a +posts_path+ route, which was created automatically by Rails. +However, we don't have a +post_path+ yet, which is the reason why we +received an error before. + +<shell> +# rake routes + + posts GET /posts(.:format) posts#index + posts_new GET /posts/new(.:format) posts#new +posts_create POST /posts/create(.:format) posts#create + GET /posts/:id(.:format) posts#show + GET /posts/:id/edit(.:format) posts#edit + PUT /posts/:id(.:format) posts#update + root / welcome#index +</shell> + +To fix this, open +config/routes.rb+ and modify the +get "posts/:id"+ +line like this: + +<ruby> +get "posts/:id" => "posts#show", :as => :post +</ruby> + +Now you'll be able to update posts again. + +h4. Deleting Posts + +We're now ready to cover the "D" part of CRUD, deleting posts from the +database. Following the REST convention, we're going to add a route for +deleting posts: + +<ruby> +# config/routes.rb + +delete "posts/:id" => "posts#destroy" +</ruby> + +We use the +delete+ method for destroying resources, which is mapped to +the +destroy+ action, which is provided below: + +<ruby> +# app/controllers/posts_controller.rb + +def destroy + @post = Post.find(params[:id]) + @post.destroy + + redirect_to :action => :index +end +</ruby> + +You can call +destroy+ on Active Record objects when you want to delete +them from the dabase. Note that we don't need to add a view for this +action since we're redirecting to the +index+ action. + +Finally, add a 'destroy' link to your +index+ action to wrap everything +together. + +<erb> +<table> + <tr> + <th>Title</th> + <th>Text</th> + <th></th> + <th></th> + <th></th> + </tr> + +<% @posts.each do |post| %> + <tr> + <td><%= post.title %></td> + <td><%= post.text %></td> + <td><%= link_to 'Show', :action => :show, :id => post.id %></td> + <td><%= link_to 'Edit', :action => :edit, :id => post.id %></td> + <td><%= link_to 'Destroy', { :action => :destroy, :id => post.id }, :method => :delete, :confirm => 'Are you sure?' %></td> + </tr> +<% end %> +</table> +</erb> + +Here we're using +link_to+ in a different way. We wrap the ++:action+ and +:id+ attributes in a hash so that we can pass other +arguments to +link_to+. The +:method+ and +:confirm+ +options are used as html5 attributes so that when the click is linked, +Rails will first show a confirm dialog to the user, and then submit the +link with method +delete+. This is done via javascript automatically. + +!images/getting_started/confirm_dialog.png(Confirm Dialog)! + +Congratulations, you can now create, show, list, update and destroy +posts. In the next section will see how Rails can aid us when creating +REST applications, and how we can refactor our Blog app to take +advantage of it. + h4. Using the Console To see your validations in action, you can use the console. The console is a |