0321944275 {B5DCD326} the rails 4 way (3rd ed ) fernandez 2014 06 08

783 940 0
0321944275 {B5DCD326} the rails 4 way (3rd ed ) fernandez 2014 06 08

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

The Rails Way Obie Fernandez, Kevin Faustino and Vitaly Kushner This book is for sale at http://leanpub.com/tr4w This version was published on 2014-06-03 This is a Leanpub book Leanpub empowers authors and publishers with the Lean Publishing process Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and many iterations to get reader feedback, pivot until you have the right book and build traction once you ©2013 - 2014 Obie Fernandez, Kevin Faustino and Vitaly Kushner Tweet This Book! Please help Obie Fernandez, Kevin Faustino and Vitaly Kushner by spreading the word about this book on Twitter! The suggested tweet for this book is: I just bought the beta release of The Rails Way The suggested hashtag for this book is #tr4w Find out what other people are saying about the book by clicking on this link to search for this hashtag on Twitter: https://twitter.com/search?q=#tr4w Taylor, your hard work and dedication to your craft is an inspiration to me every day I love you… Contents Foreword ii Foreword (to The Rails Way) iii Foreword (to The Rails Way) v Acknowledgments vi About the Authors Obie Fernandez Kevin Faustino vii vii vii Introduction About This Book Recommended Reading and Resources Goals Prerequisites Required Technology viii viii ix x xi xi Rails Environments and Configuration 1.1 Bundler 1.2 Startup and Application Settings 1.3 Development Mode 1.4 Test Mode 1.5 Production Mode 1.6 Configuring a Database 1.7 Configuring Application Secrets 1.8 Logging 1 16 20 21 24 26 27 Routing 2.1 The Two Purposes of Routing 2.2 The routes.rb File 2.3 Route Globbing 2.4 Named Routes 2.5 Scoping Routing Rules 2.6 Listing Routes 2.7 Conclusion 34 34 35 47 48 53 55 56 CONTENTS REST, Resources, and Rails 3.1 REST in a Rather Small Nutshell 3.2 Resources and Representations 3.3 REST in Rails 3.4 Routing and CRUD 3.5 The Standard RESTful Controller Actions 3.6 Singular Resource Routes 3.7 Nested Resources 3.8 Routing Concerns 3.9 RESTful Route Customizations 3.10 Controller-Only Resources 3.11 Different Representations of Resources 3.12 The RESTful Rails Action Set 3.13 Conclusion 57 57 58 58 59 62 65 66 70 71 75 77 79 83 Working with Controllers 4.1 Rack 4.2 Action Dispatch: Where It All Begins 4.3 Render unto View… 4.4 Additional Layout Options 4.5 Redirecting 4.6 Controller/View Communication 4.7 Action Callbacks 4.8 Streaming 4.9 Variants 4.10 Conclusion 85 85 88 91 99 100 103 104 109 114 115 Working with Active Record 5.1 The Basics 5.2 Macro-Style Methods 5.3 Defining Attributes 5.4 CRUD: Creating, Reading, Updating, Deleting 5.5 Database Locking 5.6 Where Clauses 5.7 Connections to Multiple Databases in Different Models 5.8 Using the Database Connection Directly 5.9 Other Configuration Options 5.10 Conclusion 117 117 118 121 125 138 141 152 153 157 157 Active Record Migrations 6.1 Creating Migrations 6.2 Data Migration 6.3 schema.rb 6.4 Database Seeding 6.5 Database-Related Rake Tasks 6.6 Conclusion 159 159 172 174 174 175 179 CONTENTS Active Record Associations 7.1 The Association Hierarchy 7.2 One-to-Many Relationships 7.3 The belongs_to Association 7.4 The has_many Association 7.5 Many-to-Many Relationships 7.6 One-to-One Relationships 7.7 Working with Unsaved Objects and Associations 7.8 Association Extensions 7.9 The CollectionProxy Class 7.10 Conclusion 180 180 181 189 197 205 215 219 220 221 222 Validations 8.1 Finding Errors 8.2 The Simple Declarative Validations 8.3 Common Validation Options 8.4 Conditional Validation 8.5 Short-form Validation 8.6 Custom Validation Techniques 8.7 Skipping Validations 8.8 Working with the Errors Hash 8.9 Testing Validations with Shoulda 8.10 Conclusion 224 224 224 234 236 238 239 242 242 243 244 Advanced Active Record 9.1 Scopes 9.2 Callbacks 9.3 Calculation Methods 9.4 Single-Table Inheritance (STI) 9.5 Abstract Base Model Classes 9.6 Polymorphic has_many Relationships 9.7 Enums 9.8 Foreign-key Constraints 9.9 Modules for Reusing Common Behavior 9.10 Modifying Active Record Classes at Runtime 9.11 Using Value Objects 9.12 Non-Persisted Models 9.13 PostgreSQL enhancements 9.14 Conclusion 245 245 250 259 261 267 268 272 274 274 278 280 283 285 292 10 Action View 10.1 Layouts and Templates 10.2 Partials 10.3 Conclusion 293 293 302 308 11 All About Helpers 309 CONTENTS 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 11.10 11.11 11.12 11.13 11.14 11.15 11.16 11.17 11.18 11.19 11.20 11.21 11.22 11.23 11.24 ActiveModelHelper AssetTagHelper AtomFeedHelper CacheHelper CaptureHelper CsrfHelper DateHelper DebugHelper FormHelper FormOptionsHelper FormTagHelper JavaScriptHelper NumberHelper OutputSafetyHelper RecordTagHelper RenderingHelper SanitizeHelper TagHelper TextHelper TranslationHelper and the I18n API UrlHelper Writing Your Own View Helpers Wrapping and Generalizing Partials Conclusion 12 Haml 12.1 Getting Started 12.2 The Basics 12.3 Doctype 12.4 Comments 12.5 Evaluating Ruby Code 12.6 Helpers 12.7 Filters 12.8 Haml and Content 12.9 Configuration Options 12.10 Conclusion 309 315 323 325 325 326 327 333 333 347 355 360 361 366 366 367 367 369 371 375 393 397 399 404 406 406 407 412 412 413 415 416 417 418 420 13 Session Management 13.1 What to Store in the Session 13.2 Session Options 13.3 Storage Mechanisms 13.4 Cookies 13.5 Conclusion 421 421 422 422 426 427 14 Authentication and Authorization 428 14.1 Devise 428 CONTENTS 14.2 has_secure_password 434 14.3 Pundit 439 14.4 Conclusion 445 15 Security 15.1 Password Management 15.2 Log Masking 15.3 SSL (Secure Sockets Layer) 15.4 Model mass-assignment attributes protection 15.5 SQL Injection 15.6 Cross-Site Scripting (XSS) 15.7 XSRF (Cross-Site Request Forgery) 15.8 Session Fixation Attacks 15.9 Keeping Secrets 15.10 Conclusion 447 447 449 449 450 452 453 456 458 459 460 16 Action Mailer 16.1 Setup 16.2 Mailer Models 16.3 Receiving Emails 16.4 Server Configuration 16.5 Testing Email Content 16.6 Previews 16.7 Conclusion 461 461 461 467 469 470 471 472 17 Caching and Performance 17.1 View Caching 17.2 Data Caching 17.3 Control of Web Caching 17.4 ETags 17.5 Conclusion 473 473 488 490 491 492 18 Background Processing 18.1 Delayed Job 18.2 Sidekiq 18.3 Resque 18.4 Rails Runner 18.5 Conclusion 494 494 497 503 508 510 19 Ajax on Rails 19.1 Unobtrusive JavaScript 19.2 Turbolinks 19.3 Ajax and JSON 19.4 Ajax and HTML 19.5 Ajax and JavaScript 19.6 Conclusion 511 512 516 518 520 522 523 CONTENTS 20 Asset Pipeline 20.1 Asset Pipeline 20.2 Wish List 20.3 The Big Picture 20.4 Organization Where does everything go? 20.5 Manifest files 20.6 Custom format handlers 20.7 Post-Processing 20.8 Helpers 20.9 Fingerprinting 20.10 Serving the files 20.11 Rake Tasks 20.12 Conclusion 524 524 525 525 525 526 531 532 533 535 535 537 537 21 RSpec 21.1 Introduction 21.2 Basic Syntax and API 21.3 Matchers 21.4 Custom Expectation Matchers 21.5 Shared Behaviors 21.6 Shared Context 21.7 RSpec’s Mocks and Stubs 21.8 Running Specs 21.9 RSpec Rails Gem 21.10 RSpec Tools 21.11 Conclusion 538 538 541 551 552 555 555 556 558 559 573 574 22 XML 22.1 The to_xml Method 22.2 The XML Builder 22.3 Parsing XML 22.4 Conclusion 575 575 585 587 589 Active Model API Reference AttributeMethods Callbacks Conversion Dirty Errors 590 590 592 594 594 596 600 600 601 602 603 604 604 ForbiddenAttributesError Lint::Tests Model Name Naming SecurePassword Serialization 746 Active Support API Reference (other) Compares this timezone to the parameter The two are compared first based on their offsets, and then by name =∼(re) Compare name and TZInfo identifier to a supplied regexp Returns true if a match is found TimeZone[] (arg) Locates a specific timezone object If the argument is a string, it is interpreted to mean the name of the timezone to locate >> ActiveSupport::TimeZone['Dublin'] => # If it is a numeric value it is either the hour offset, or the second offset, of the timezone to find (The first one with that offset will be returned.) Returns nil if no such timezone is known to the system TimeZone.all Returns an array of all 146 TimeZone objects There are multiple TimeZone objects per timezone (in many cases) to make it easier for users to find their own timezone >> ActiveSupport::TimeZone.all => [# "Hawaii" # => 946684800.0 # => Fri, 31 Dec 1999 14:00:00 HST -10:00 TimeZone.create(name, offset) Creates a new TimeZone instance with the given name and offset Active Support API Reference 747 >> ActiveSupport::TimeZone.create("Atlanta", -5.hours) => # TimeZone.find_tzinfo(name) Returns a TZInfo instance matching the specified name formatted_offset(colon=true, alternate_utc_string = nil) Returns the offset of this timezone as a formatted string, in the format HH:MM If the offset is zero, this method will return an empty string If colon is false, a colon will not be inserted into the output initialize(name, utc_offset = nil, tzinfo = nil) Create a new TimeZone object with the given name and offset The offset is the number of seconds that this time zone is offset from UTC (GMT) Seconds were chosen as the offset unit because that is the unit that Ruby uses to represent time zone offsets (see Time#utc_offset) The tzinfo parameter can be explicitly passed in, otherwise the name will be used to find it: TimeZone.find_tzinfo(name) local(*args) Creates a new ActiveSupport::TimeWithZone instance in time zone of self from given values local_to_utc(time, dst=true) Adjust the given time to the simultaneous time in UTC Returns a Time.utc() instance now Returns Time.now adjusted to this timezone >> => >> => Time.now 2013-10-16 17:45:49 -0400 ActiveSupport::TimeZone['Hawaii'].now Wed, 16 Oct 2013 11:46:05 HST -10:00 parse(str, now=now) Creates a new ActiveSupport::TimeWithZone instance in time zone of self from parsed string 748 Active Support API Reference >> => >> => Time.zone = 'Hawaii' "Hawaii" Time.zone.parse('1999-12-31 14:00:00') Fri, 31 Dec 1999 14:00:00 HST -10:00 period_for_local(time, dst=true) Method exists so that TimeZone instances respond like TZInfo::Timezone period_for_utf(time) Method exists so that TimeZone instances respond like TZInfo::Timezone TimeZone.seconds_to_utc_offset(seconds, colon = true) Assumes self represents an offset from UTC in seconds (as returned from Time#utc_offset) and turns this into an +HH:MM formatted string ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00" to_s Returns a textual representation of this timezone ActiveSupport::TimeZone['Dublin'].to_s # => "(GMT+00:00) Dublin" today Returns the current date in this timezone >> => >> => Date.today Wed, 16 Oct 2013 ActiveSupport::TimeZone['Darwin'].today Thu, 17 Oct 2013 TimeZone.us_zones A convenience method for returning a collection of TimeZone objects for timezones in the USA Active Support API Reference 749 >> ActiveSupport::TimeZone.us_zones.map(&:name) => ["Hawaii", "Alaska", "Pacific Time (US & Canada)", "Arizona", "Mountain Time (US & Canada)", "Central Time (US & Canada)", "Eastern Time (US & Canada)", "Indiana (East)"] utc_offset Returns the offset of this time zone from UTC in seconds utc_to_local(time) Adjust the given time to the simultaneous time in the timezone TrueClass active_support/core_ext/object/blank blank? Returns false active_support/json/encoding as_json Returns "true" ActiveSupport::XmlMini The XmlMini module contains code that allows Rails to serialize/deserialize and parse XML using a number of different libraries • JDOM (requires JRuby) • LibXML (fast native XML parser) • Nokogiri (requires nokogiri gem) active_support/xml_mini If you’re doing anything of significance with XML in your application, you should definitely use the super-fast native libxml parser Install the binaries (instructions vary depending on platform) then the Ruby binding: 750 Active Support API Reference gem 'libxml-ruby', '=0.9.7' Set XmlMini to use libxml in application.rb or an initializer XmlMini.backend = 'LibXML' Constants The TYPE_NAMES constant holds a mapping of Ruby types to their representation when serialized as XML 10 11 12 13 14 TYPE_NAMES = { "Symbol" "Fixnum" "Bignum" "BigDecimal" "Float" "TrueClass" "FalseClass" "Date" "DateTime" "Time" "Array" "Hash" } => => => => => => => => => => => => "symbol", "integer", "integer", "decimal", "float", "boolean", "boolean", "date", "dateTime", "dateTime", "array", "hash" The FORMATTING constant holds a mapping of lambdas that define how Ruby values are serialized to strings for representation in XML FORMATTING = "symbol" "date" "dateTime" "binary" "yaml" } { => => => => => Proc.new Proc.new Proc.new Proc.new Proc.new { { { { { |symbol| symbol.to_s }, |date| date.to_s(:db) }, |time| time.xmlschema }, |binary| ::Base64.encode64(binary) }, |yaml| yaml.to_yaml } The PARSING constant holds a mapping of lambdas used to deserialize values stored in XML back into Ruby objects Active Support API Reference 10 11 12 13 14 15 16 PARSING = { "symbol" => Proc.new { |symbol| symbol.to_sym }, "date" => Proc.new { |date| ::Date.parse(date) }, "datetime" => Proc.new { |time| Time.xmlschema(time).utc rescue ::DateTime.parse(time).utc }, "integer" => Proc.new { |integer| integer.to_i }, "float" => Proc.new { |float| float.to_f }, "decimal" => Proc.new { |number| BigDecimal(number) }, "boolean" => Proc.new { |boolean| %w(1 true).include?(boolean.strip) }, "string" => Proc.new { |string| string.to_s }, "yaml" => Proc.new { |yaml| YAML::load(yaml) rescue yaml }, "base64Binary" => Proc.new { |bin| ::Base64.decode64(bin) }, "binary" => Proc.new { |bin, entity| _parse_binary(bin, entity) }, "file" => Proc.new { |file, entity| _parse_file(file, entity) } } PARSING.update( "double" => PARSING["float"], "dateTime" => PARSING["datetime"] ) 751 Rails Essentials Chances are you learned about Rails from watching beginner screencasts or studying our highly-rated companion in the Pro Ruby Series, the excellent Ruby on Rails Tutorial by Michael Hartl Those resources will get you through the initial slope of the learning curve and on a trajectory towards serious productivity But to continue making progress, it helps to know the tools that real Rails masters use every day Environmental Concerns No, I’m not about to go off on a tangent about carbon credits and global warming As a Rails pro, you’re going to spend a lot of time using the command line, so you might as well save yourself as much confusion and extra typing as possible The following little tips and tricks should make your life easier and more enjoyable Operating System While it is certainly possible to write Rails application on a Windows platform, and quite a few people that, it is far from being optimal The fact is, your application is most probably going to run on a Linux server in production, and so, being able to install all the essential pieces locally is very important Many of the gems that you might want to use will simply refuse to compile in a non-Unix environment Note that while your server is most probably runs Linux, you can quite easily use OS X as your development environment At first glance this goes against the notion of running the same OS as the server, but fortunately most Rails developers use Apple machines for development and so historically they’ve made sure all relevant gems and software packages are available and compatible with those from the Linux environment Practically all the gems that can be compiled on Linux will happily compile on OS X as well If you are stuck with Windows as your development machine it is usually better to run a Linux virtual machine to host the Ruby environment Check out Vagrant¹ for easy installation of development virtual machines Aliases At minimum you should add aliases for starting your Rails server and console to your shell’s execution environment Geoffrey Grosenbach suggests alias ss 'bundle exec rails server' and alias sc 'bundle exec rails console' Vitaly says… You might want to add –debugger to your aliases if you always include a debugger gem in your applications ¹http://www.vagrantup.com Rails Essentials 753 Essential Gems Some gems are so valuable that (arguably) they should be a part of the core Rails distribution However, because of the “less is more” philosophy of the core team, the Rails core distribution is actually shrinking, not growing The following section contains an alphabetical list of essential gems for the Rails pro to be aware of and use on a regular basis Better Errors https://github.com/charliesome/better_errors Better Errors replaces the standard Rails error page with a much better and more useful error page It is also usable outside of Rails in any Rack app as Rack middleware Instead of a plain default error page, Better Errors will display a full interactive stack trace with source code inspection If you also include the companion binding_of_caller² gem into your application Better Errors will be able to also let you inspect local and instance variables and even embed a full REPL into every stack frame of your error page backtrace Of course you should only ever that in a development environment To use it simply add the following to your Gemfile: group :development gem "better_errors" gem 'binding_of_caller' end Country Select https://github.com/stefanpenner/country_select This plugin, previously in Rails core, provides a simple way to get an HTML select tag with a list of countries It lists countries as their full names and can optionally take a list of priority countries to display at the top of the options It is English only and provides no i18n support Debugger https://github.com/cldwalker/debugger Debugger is a fork of a once-popular ruby-debug and ruby-debug19 gems It will work with Ruby 1.8.7, and 1.9.x out of the box With the ruby-debug and ruby-debug19 gems, you had to choose one of them according to your Ruby version, whereas debugger will just work Debugger is usually added to the :development and :test groups of your Gemfile ²https://github.com/banister/binding_of_caller Rails Essentials 754 Once installed you can simply add a call to debugger method in any place of your code to force the execution of the application to stop and start Debugger REPL Draper https://github.com/drapergem/draper As Rails applications grow, so can the complexity in the view layer Some common symptoms for a complex view can include if/else conditions, multiple instance variables, and extensive chaining The Draper gem provides an elegant solution to this problem by adding an object-oriented layer of presentation logic to your Rails application Instead of using a model instance variable directly in a view, using Draper, one can define a decorator instead A decorator wraps an instance of a model with presentation-related logic This allows you to encompass view specific logic for a model in one place Not only is this a cleaner solution, it’s also easier to test, as Draper supports RSpec, MiniTest::Rails, and Test::Unit out of the box To get started, add the draper gem to your Gemfile and run bundle # Gemfile gem 'draper' To write a decorator for a model, create a new class in app/decorators which inherits from Draper::Decorator For the purposes of our examples, assume we have an Active Record model Post that we wish to decorate # app/decorators/post_decorator.rb class PostDecorator < Draper::Decorator end Draper also comes with a Rails generator to automatically create a decorator for a given model $ rails generate decorator Post Within a decorator, you can access the underlying model via the object method Draper also provides access to Rails helpers within your decorators via the h method To demonstrate, the method below renders an avatar if the post author has one Rails Essentials 755 # app/decorators/post_decorator.rb class PostDecorator < Draper::Decorator def author_avatar return unless object.author.avatar? h.image_tag(object.author.avatar, class: 'avatar') end end To assign a decorator to an object, call the decorate method on a given object instance This will automatically infer the decorator based on the object @post = Post.first.decorate Alternatively, you can always explicitly instantiate a decorator yourself, supplying an instance of the decorated model as its argument @post = PostDecorator.new(Post.first) Note that Draper also supports decoration on a collection Each item in the collection will be decorated with the inferred decorator @posts = Posts.all.decorate Kaminari https://github.com/amatsuda/kaminari One frequent need in a Rails application is paginating the database query results For a long time the number one plugin to it was will_paginate, but lately it is being replaced by a better alternative - “Kaminari” “A Scope & Engine based, clean, powerful, customizable and sophisticated paginator for Rails” The interface is scope based For example, to paginate a list of projects you can this: @projects = Project.page(params[:page]) One area where Kaminari shines is customization If you need a custom markup for your pagination links you don’t need to edit obscure configuration files Instead, you just edit html templates To get the templates to customize run the following command: Rails Essentials 756 $ rails g kaminari:views THEME where THEME is ‘default’ or one of the themes from https://github.com/amatsuda/kaminari_themes Nested Form Fields https://github.com/ncri/nested_form_fields It’s super common to want to edit records along with their has_many associations on a single page This Rails gem helps creating forms for models with nested has_many associations and relies on jQuery to dynamically add and remove nested form fields without a page reload • Works for arbitrarily deeply nested associations (tested up to levels) • Works with form builders like simple_form • Requires at least Ruby 1.9 and the Rails asset pipeline To install, add nested_form_fields to your application’s Gemfile, run bundle and in your application.js file add: //= require nested_form_fields Usage is straightforward The Readme file uses the following example (assuming that you have a User model with nested videos): class User < ActiveRecord::Base has_many :videos accepts_nested_attributes_for :videos, allow_destroy: true end Use the nested_fields_for helper inside your user form to add the video fields: = form_for @user |f| = f.nested_fields_for :videos |ff| = ff.text_field :video_title Links to add and remove fields can be added using the add_nested_fields_link and remove_nested_fields_link helpers: 757 Rails Essentials = form_for @user |f| = f.nested_fields_for :videos |ff| = ff.remove_nested_fields_link = ff.text_field :video_title = f.add_nested_fields_link :videos Note that remove_nested_fields_link needs to be called within the nested_fields_for call and add_nested_fields_link outside of it via the parent builder Pry and friends Pry³ is a powerful alternative to the standard IRB shell for Ruby It features syntax highlighting, a flexible plugin architecture, runtime invocation and source and documentation browsing The pry plugin pry-debugger⁴ adds navigation commands via the debugger (formerly ruby-debug) gem These two gems allow you to debug like a pro Instead of debugger you use binding.pry as your breakpoint command Once the execution stops you have all the power of Pry, including syntax highlighted source listing, variables inspections, shell access etc To use Pry, just add the following two gems to your Gemfile development and test groups: group :development, :test gem 'pry-rails' gem 'pry-debugger' end Note that the standard debugger commands won’t work at a Pry prompt Try help to see available commands You add the following to ∼/.pryrc file to make the n, c, s, f, and l work as before: Pry.commands.alias_command Pry.commands.alias_command Pry.commands.alias_command Pry.commands.alias_command Pry.commands.alias_command 'l', 'c', 'n', 's', 'f', 'whereami' 'continue' 'next' 'step' 'finish' Another useful pry plugin to be aware of is pry-rescue⁵ If an exception is raised and is not rescued, pry-rescue will automatically start a Pry session for you ³http://pryrepl.org ⁴https://github.com/nixme/pry-debugger ⁵https://github.com/ConradIrwin/pry-rescue Rails Essentials 758 Rails Admin https://github.com/sferik/rails_admin Unlike some other frameworks, for example Django, Rails doesn’t come with a standard admin interface Not to worry though, as there is no shortage of gems that provide this functionality Rails Admin is one of the better looking and functional ones It will allow you to display, create, edit, and delete records in the database, export data to CSV, JSON, or XML formats, manage your record associations and more To install it just add ‘rails_admin’ gem to your Gemfile, run bundle install and then run the provided generator: $ rails g rails_admin:install Rails Admin uses devise for authentication and will install it if it is not yet present in your project It is recommended to use a separate user model Admin in a separate table admins to authenticate access to the admin interface as it is less susceptible to accidental security exposure Remote debugger In you are using Pow or any other web server that runs in a background, you can not directly use the debugger console In this case remote debugger can be used Add the following code to the bottom of config/application.rb: if ENV['RUBY_DEBUG_PORT'] Debugger.start_remote nil, ENV['RUBY_DEBUG_PORT'].to_i end Now you just need to start your server with RUBY_DEBUG_PORT environment variable set to a port value, like 25001, to enable remote debugger To connect to this server you use rdebug command line: $ rdebug -c -p 25001 Simple Form Generating complex forms by hand can be a very tedious and error prone process A number of gems are available to help One of the most popular lately is SimpleForm https://github.com/plataformatec/simple_form “SimpleForm aims to be as flexible as possible while helping you with powerful components to create your forms.” To add it to your project, first add the gem to your Gemfile: Rails Essentials 759 gem 'simple_form' Then run bundler to install it and a generator to install configuration file: $ bundle install $ rails g simple_form:install bootstrap The bootstrap switch causes the generated markup to be Twitter Bootstrap compatible Refer to the documentation for other markups supported out of the box State Machine State machines can be a very powerful tool to describe, validate and maintain a complex object state You can get by with using a couple of booleans for simple case, but it becomes too messy pretty soon A proper state machine, on the other hand, can make even a quite complex case manageable The most popular state machine implementation at the time of writing is the state_machine gem It has been described as the “gorilla of state machine gems” because it is packed with features like multiple state machines per class, event parallelization and namespacing, plus it includes adapters for ActiveRecord, DataMapper, Mongoid, MongoMapper and Sequel https://github.com/pluginaweek/state_machine Be sure to check its state machine drawing functionality: $ rake state_machine:draw CLASS=Project,Issue The Graphiz-based visualizations can be invaluable when you have complicated state transitions Some people think that it is overkill for simple uses cases A popular alternative is the lighter-weight Workflow gem, which is fairly lightweight at only 500 lines of code, and also features visualization capabilities https://github.com/geekq/workflow The primary difference between the two libraries is that in Workflow, you define events inside of their related states You possibility lose some reusability, but the definitions are somewhat easier to read and understand class Article include Workflow workflow state :new event :submit, :transitions_to => :awaiting_review end 10 state :awaiting_review event :review, :transitions_to => :being_reviewed Rails Essentials 11 760 end 12 13 14 15 16 state :being_reviewed event :accept, :transitions_to => :accepted event :reject, :transitions_to => :rejected end 17 18 19 20 21 state :accepted state :rejected end end Ruby Toolbox Didn’t see what you’re looking for in the list above? https://www.ruby-toolbox.com This site lists and organizes a lot of Ruby and Rails gems by category and popularity It’s usually the first place to look if you’re searching for 3rd-party functionality to add to your Rails application Screencasts Screencasts are videos distributed online that teach you a narrowly focused topic of interest by capturing actual screen output (hence the name) while the author explains concepts and writes code The Rails community loves to create screencasts! Railcasts http://railscasts.com/ Short on cash? Host Ryan Bates posts a new screencast almost every two weeks for free Episodes range between to 15 minutes in length and are focused on Rails specific topics ... 44 7 44 7 44 9 44 9 45 0 45 2 45 3 45 6 45 8 45 9 46 0 16 Action Mailer 16.1 Setup 16.2 Mailer Models 16.3 Receiving Emails 16 .4 Server Configuration 16.5... 40 6 40 6 40 7 41 2 41 2 41 3 41 5 41 6 41 7 41 8 42 0 13 Session Management 13.1 What to Store in the Session 13.2 Session Options 13.3 Storage Mechanisms 13 .4 Cookies ... (0.3. 3) Installing treetop (1 .4. 1 5) Installing mail (2.5 . 4) Installing actionmailer (4. 0. 2) Installing activemodel (4. 0. 2) Installing activerecord-deprecated_finders (1.0. 3) Installing arel (4. 0.1)

Ngày đăng: 07/01/2017, 20:47

Từ khóa liên quan

Mục lục

  • Table of Contents

  • Foreword

  • Foreword (to The Rails 3 Way)

  • Foreword (to The Rails Way)

  • Acknowledgments

  • About the Authors

    • Obie Fernandez

    • Kevin Faustino

    • Introduction

      • About This Book

      • Recommended Reading and Resources

      • Goals

      • Prerequisites

      • Required Technology

      • Rails Environments and Configuration

        • Bundler

        • Startup and Application Settings

        • Development Mode

        • Test Mode

        • Production Mode

        • Configuring a Database

        • Configuring Application Secrets

        • Logging

Tài liệu cùng người dùng

Tài liệu liên quan