From 89079b39ee625e46f21a4049a978ca24e7cec25a Mon Sep 17 00:00:00 2001 From: Sean Linsley Date: Tue, 3 Dec 2013 22:38:14 -0600 Subject: [PATCH 1/3] dependency updates --- .ruby-gemset | 1 + .ruby-version | 1 + Gemfile | 26 ++-- Gemfile.lock | 187 +++++++++++++++------------ config/application.rb | 3 + config/database.yml | 25 +--- config/initializers/active_admin.rb | 193 ++++++++++++++++++++++++---- 7 files changed, 303 insertions(+), 133 deletions(-) create mode 100644 .ruby-gemset create mode 100644 .ruby-version diff --git a/.ruby-gemset b/.ruby-gemset new file mode 100644 index 00000000..a266bb5f --- /dev/null +++ b/.ruby-gemset @@ -0,0 +1 @@ +demo-activeadmin diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 00000000..227cea21 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.0.0 diff --git a/Gemfile b/Gemfile index 23d050ec..389e6d4b 100644 --- a/Gemfile +++ b/Gemfile @@ -1,21 +1,27 @@ source 'http://rubygems.org' -gem 'rails', '3.0.10' -gem 'sqlite3-ruby', :require => 'sqlite3' -gem 'nifty-generators' -gem "activeadmin", '0.5.0' -gem "faker" -gem 'newrelic_rpm', '3.1.1' -gem 'hoptoad_notifier', '2.4.11' +gem 'rails', '3.0.20' +gem 'activeadmin', '0.6.2' +gem 'unicorn' +gem 'pg' + +gem 'mechanize' +gem 'faker' gem 'rack-throttle' +gem 'newrelic_rpm' +gem 'hoptoad_notifier' group :development do - gem 'mechanize' + # Debugging + gem 'better_errors' # Web UI to debug exceptions. Go to /__better_errors to access the latest one + gem 'binding_of_caller' # Retrieve the binding of a method's caller in MRI Ruby >= 1.9.2 + + # Performance + gem 'rack-mini-profiler' # Inline app profiler. See ?pp=help for options. + gem 'flamegraph' # Flamegraph visualiztion: ?pp=flamegraph end group :production do - gem 'unicorn' - # Enable gzip compression on heroku, but don't compress images. gem 'heroku-deflater' diff --git a/Gemfile.lock b/Gemfile.lock index e29517b4..10c03c52 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,60 +2,73 @@ GEM remote: http://rubygems.org/ specs: abstract (1.0.0) - actionmailer (3.0.10) - actionpack (= 3.0.10) + actionmailer (3.0.20) + actionpack (= 3.0.20) mail (~> 2.2.19) - actionpack (3.0.10) - activemodel (= 3.0.10) - activesupport (= 3.0.10) + actionpack (3.0.20) + activemodel (= 3.0.20) + activesupport (= 3.0.20) builder (~> 2.1.2) erubis (~> 2.6.6) i18n (~> 0.5.0) - rack (~> 1.2.1) + rack (~> 1.2.5) rack-mount (~> 0.6.14) rack-test (~> 0.5.7) tzinfo (~> 0.3.23) - activeadmin (0.5.0) - arbre (>= 1.0.1) - bourbon (>= 1.0.0) - devise (>= 1.1.2) - fastercsv - formtastic (>= 2.0.0) - inherited_resources (>= 1.3.1) - jquery-rails (>= 1.0.0) - kaminari (>= 0.13.0) - meta_search (>= 0.9.2) - rails (>= 3.0.0) - sass (>= 3.1.0) - activemodel (3.0.10) - activesupport (= 3.0.10) + activeadmin (0.6.2) + arbre (~> 1.0) + bourbon (>= 1.0.0, < 4) + devise (>= 1.5.4, < 4) + formtastic (~> 2.0) + inherited_resources (~> 1.3) + jquery-rails (>= 1.0.0, < 3) + kaminari (~> 0.13) + meta_search (~> 1.0) + rails (>= 3.0.0, < 4) + sass (~> 3.1) + activemodel (3.0.20) + activesupport (= 3.0.20) builder (~> 2.1.2) i18n (~> 0.5.0) - activerecord (3.0.10) - activemodel (= 3.0.10) - activesupport (= 3.0.10) + activerecord (3.0.20) + activemodel (= 3.0.20) + activesupport (= 3.0.20) arel (~> 2.0.10) tzinfo (~> 0.3.23) - activeresource (3.0.10) - activemodel (= 3.0.10) - activesupport (= 3.0.10) - activesupport (3.0.10) + activeresource (3.0.20) + activemodel (= 3.0.20) + activesupport (= 3.0.20) + activesupport (3.0.20) arbre (1.0.1) activesupport (>= 3.0.0) arel (2.0.10) - bcrypt-ruby (3.0.1) - bourbon (2.1.1) - sass (>= 3.1) + bcrypt-ruby (3.1.2) + better_errors (1.0.1) + coderay (>= 1.0.0) + erubis (>= 2.6.6) + binding_of_caller (0.7.2) + debug_inspector (>= 0.0.1) + bourbon (3.1.8) + sass (>= 3.2.0) + thor builder (2.1.2) - devise (1.5.3) + coderay (1.1.0) + debug_inspector (0.0.2) + devise (1.5.4) bcrypt-ruby (~> 3.0) orm_adapter (~> 0.0.3) warden (~> 1.1) + domain_name (0.5.15) + unf (>= 0.0.5, < 1.0.0) erubis (2.6.6) abstract (>= 1.0.0) - faker (0.9.5) - i18n (~> 0.4) - fastercsv (1.5.5) + faker (1.2.0) + i18n (~> 0.5) + fast_stack (0.1.0) + rake + rake-compiler + flamegraph (0.0.4) + fast_stack formtastic (2.2.1) actionpack (>= 3.0) has_scope (0.5.1) @@ -63,102 +76,118 @@ GEM hoptoad_notifier (2.4.11) activesupport builder - i18n (0.5.0) + http-cookie (1.0.2) + domain_name (~> 0.5) + i18n (0.5.2) inherited_resources (1.3.1) has_scope (~> 0.5.0) responders (~> 0.6) - jquery-rails (1.0.19) - railties (~> 3.0) - thor (~> 0.14) - kaminari (0.13.0) + jquery-rails (2.3.0) + railties (>= 3.0, < 5.0) + thor (>= 0.14, < 2.0) + json (1.8.1) + kaminari (0.15.0) actionpack (>= 3.0.0) activesupport (>= 3.0.0) - railties (>= 3.0.0) kgio (2.8.1) - mail (2.2.19) + mail (2.2.20) activesupport (>= 2.3.6) i18n (>= 0.4.0) mime-types (~> 1.16) treetop (~> 1.4.8) - mechanize (2.0.1) + mechanize (2.7.2) + domain_name (~> 0.5, >= 0.5.1) + http-cookie (~> 1.0.0) + mime-types (~> 1.17, >= 1.17.2) net-http-digest_auth (~> 1.1, >= 1.1.1) - net-http-persistent (~> 1.8) + net-http-persistent (~> 2.5, >= 2.5.2) nokogiri (~> 1.4) - webrobots (~> 0.0, >= 0.0.9) + ntlm-http (~> 0.1, >= 0.1.1) + webrobots (>= 0.0.9, < 0.2) meta_search (1.0.6) actionpack (~> 3.0.2) activerecord (~> 3.0.2) activesupport (~> 3.0.2) arel (~> 2.0.2) - mime-types (1.16) - net-http-digest_auth (1.1.1) - net-http-persistent (1.9) - newrelic_rpm (3.1.1) - nifty-generators (0.4.6) - nokogiri (1.5.0) + mime-types (1.25.1) + mini_portile (0.5.2) + net-http-digest_auth (1.4) + net-http-persistent (2.9) + newrelic_rpm (3.6.9.171) + nokogiri (1.6.0) + mini_portile (~> 0.5.0) + ntlm-http (0.1.1) orm_adapter (0.0.7) - polyglot (0.3.2) - rack (1.2.3) + pg (0.17.0) + polyglot (0.3.3) + rack (1.2.8) + rack-mini-profiler (0.1.31) + rack (>= 1.1.3) rack-mount (0.6.14) rack (>= 1.0.0) rack-test (0.5.7) rack (>= 1.0) rack-throttle (0.3.0) rack (>= 1.0.0) - rails (3.0.10) - actionmailer (= 3.0.10) - actionpack (= 3.0.10) - activerecord (= 3.0.10) - activeresource (= 3.0.10) - activesupport (= 3.0.10) + rails (3.0.20) + actionmailer (= 3.0.20) + actionpack (= 3.0.20) + activerecord (= 3.0.20) + activeresource (= 3.0.20) + activesupport (= 3.0.20) bundler (~> 1.0) - railties (= 3.0.10) + railties (= 3.0.20) rails_12factor (0.0.2) rails_serve_static_assets rails_stdout_logging rails_serve_static_assets (0.0.1) rails_stdout_logging (0.0.3) - railties (3.0.10) - actionpack (= 3.0.10) - activesupport (= 3.0.10) + railties (3.0.20) + actionpack (= 3.0.20) + activesupport (= 3.0.20) rake (>= 0.8.7) rdoc (~> 3.4) thor (~> 0.14.4) raindrops (0.12.0) - rake (0.9.2) - rdoc (3.9.4) + rake (10.1.0) + rake-compiler (0.9.2) + rake + rdoc (3.12.2) + json (~> 1.4) responders (0.6.5) - sass (3.2.1) - sqlite3 (1.3.4) - sqlite3-ruby (1.3.3) - sqlite3 (>= 1.3.3) + sass (3.2.12) thor (0.14.6) - treetop (1.4.10) + treetop (1.4.15) polyglot polyglot (>= 0.3.1) - tzinfo (0.3.29) + tzinfo (0.3.38) + unf (0.1.3) + unf_ext + unf_ext (0.0.6) unicorn (4.7.0) kgio (~> 2.6) rack raindrops (~> 0.7) - warden (1.2.1) + warden (1.2.3) rack (>= 1.0) - webrobots (0.0.11) - nokogiri (>= 1.4.4) + webrobots (0.1.1) PLATFORMS ruby DEPENDENCIES - activeadmin (= 0.5.0) + activeadmin (= 0.6.2) + better_errors + binding_of_caller faker + flamegraph heroku-deflater - hoptoad_notifier (= 2.4.11) + hoptoad_notifier mechanize - newrelic_rpm (= 3.1.1) - nifty-generators + newrelic_rpm + pg + rack-mini-profiler rack-throttle - rails (= 3.0.10) + rails (= 3.0.20) rails_12factor - sqlite3-ruby unicorn diff --git a/config/application.rb b/config/application.rb index 52af8b39..843bb1dd 100644 --- a/config/application.rb +++ b/config/application.rb @@ -6,6 +6,9 @@ # you've limited to :test, :development, or :production. Bundler.require(:default, Rails.env) if defined?(Bundler) +# https://github.com/rails/rails/issues/9619 +ActionController::Base.config.relative_url_root = '' + require 'rack/throttle' module ActiveadminDepot diff --git a/config/database.yml b/config/database.yml index 025d62a8..a83bc3ea 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,22 +1,9 @@ -# SQLite version 3.x -# gem install sqlite3-ruby (not necessary on OS X Leopard) development: - adapter: sqlite3 - database: db/development.sqlite3 - pool: 5 - timeout: 5000 + adapter: postgresql + host: localhost + database: demo-activeadmin -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. test: - adapter: sqlite3 - database: db/test.sqlite3 - pool: 5 - timeout: 5000 - -production: - adapter: sqlite3 - database: db/production.sqlite3 - pool: 5 - timeout: 5000 + adapter: postgresql + host: localhost + database: demo-activeadmin-test diff --git a/config/initializers/active_admin.rb b/config/initializers/active_admin.rb index 2fb72a4f..4c08a6a6 100644 --- a/config/initializers/active_admin.rb +++ b/config/initializers/active_admin.rb @@ -7,13 +7,24 @@ # config.site_title = "Active Admin Depot" + # Set the link url for the title. For example, to take + # users to your main site. Defaults to no link. + # + # config.site_title_link = "/" + + # Set an optional image to be displayed for the header + # instead of a string (overrides :site_title) + # + # Note: Recommended image height is 21px to properly fit in the header + # + # config.site_title_image = "/images/logo.png" # == Default Namespace # # Set the default namespace each administration resource - # will be added to. + # will be added to. # - # eg: + # eg: # config.default_namespace = :hello_world # # This will create resources in the HelloWorld module and @@ -21,19 +32,48 @@ # # To set no namespace by default, use: # config.default_namespace = false - config.default_namespace = :admin - + # + # Default: + # config.default_namespace = :admin + # + # You can customize the settings for each namespace by using + # a namespace block. For example, to change the site title + # within a namespace: + # + # config.namespace :admin do |admin| + # admin.site_title = "Custom Admin Title" + # end + # + # This will ONLY change the title for the admin section. Other + # namespaces will continue to use the main "site_title" configuration. # == User Authentication # - # Active Admin will automatically call an authentication - # method in a before filter of all controller actions to + # Active Admin will automatically call an authentication + # method in a before filter of all controller actions to # ensure that there is a currently logged in admin user. # # This setting changes the method which Active Admin calls # within the controller. config.authentication_method = false # Disabled for demo + # == User Authorization + # + # Active Admin will automatically call an authorization + # method in a before filter of all controller actions to + # ensure that there is a user with proper rights. You can use + # CanCanAdapter or make your own. Please refer to documentation. + # config.authorization_adapter = ActiveAdmin::CanCanAdapter + + # You can customize your CanCan Ability class name here. + # config.cancan_ability_class = "Ability" + + # You can specify a method to be called on unauthorized access. + # This is necessary in order to prevent a redirect loop which happens + # because, by default, user gets redirected to Dashboard. If user + # doesn't have access to Dashboard, he'll end up in a redirect loop. + # Method provided here should be defined in application_controller.rb. + # config.on_unauthorized_access = :access_denied # == Current User # @@ -43,48 +83,151 @@ # This setting changes the method which Active Admin calls # to return the currently logged in user. config.current_user_method = false # Disabled for demo - - # == Admin Notes - # - # Admin notes allow you to add notes to any model + + # == Logging Out + # + # Active Admin displays a logout link on each screen. These + # settings configure the location and method used for the link. + # + # This setting changes the path where the link points to. If it's + # a string, the strings is used as the path. If it's a Symbol, we + # will call the method to return the path. + # + # Default: + # config.logout_link_path = :destroy_<%= @underscored_user_name %>_session_path + + # This setting changes the http method used when rendering the + # link. For example :get, :delete, :put, etc.. # - # Admin notes are enabled by default, but can be disabled - # by uncommenting this line: + # Default: + # config.logout_link_method = :get + + + # == Root + # + # Set the action to call for the root path. You can set different + # roots for each namespace. + # + # Default: + # config.root_to = 'dashboard#index' + + + # == Admin Comments + # + # This allows your users to comment on any resource registered with Active Admin. + # + # You can completely disable comments: + # config.allow_comments = false + # + # You can disable the menu item for the comments index page: + # config.show_comments_in_menu = false + # + # You can change the name under which comments are registered: + # config.comments_registration_name = 'AdminComment' + + + # == Batch Actions + # + # Enable and disable Batch Actions # - config.admin_notes = true + config.batch_actions = false # == Controller Filters # # You can add before, after and around filters to all of your - # Active Admin resources from here. + # Active Admin resources and pages from here. # # config.before_filter :do_something_awesome + + + # == Setting a Favicon + # + # config.favicon = '/assets/favicon.ico' # == Register Stylesheets & Javascripts # - # We recomend using the built in Active Admin layout and loading + # We recommend using the built in Active Admin layout and loading # up your own stylesheets / javascripts to customize the look # and feel. # # To load a stylesheet: - config.register_stylesheet 'admin.css' + # config.register_stylesheet 'my_stylesheet.css' + # + # You can provide an options hash for more control, which is passed along to stylesheet_link_tag(): + # config.register_stylesheet 'my_print_stylesheet.css', :media => :print # # To load a javascript file: # config.register_javascript 'my_javascript.js' - # Set the action to call for the root path. You can set different - # roots for each namespace. - # Default: - # config.root_to = 'dashboard#index' + config.register_stylesheet 'admin.css' - # == Batch Actions - # Enable and disable Batch Actions - config.batch_actions = false # == CSV options - # Set the CSV builder separator (default is ",") - # config.csv_column_separator = ',' + # + # Set the CSV builder separator + # config.csv_options = { :col_sep => ';' } + # + # Force the use of quotes + # config.csv_options = { :force_quotes => true } + + + # == Menu System + # + # You can add a navigation menu to be used in your application, or configure a provided menu + # + # To change the default utility navigation to show a link to your website & a logout btn + # + # config.namespace :admin do |admin| + # admin.build_menu :utility_navigation do |menu| + # menu.add label: "My Great Website", url: "http://www.mygreatwebsite.com", html_options: { target: :blank } + # admin.add_logout_button_to_menu menu + # end + # end + # + # If you wanted to add a static menu item to the default menu provided: + # + # config.namespace :admin do |admin| + # admin.build_menu :default do |menu| + # menu.add label: "My Great Website", url: "http://www.mygreatwebsite.com", html_options: { target: :blank } + # end + # end + + + # == Download Links + # + # You can disable download links on resource listing pages, + # or customize the formats shown per namespace/globally + # + # To disable/customize for the :admin namespace: + # + # config.namespace :admin do |admin| + # + # # Disable the links entirely + # admin.download_links = false + # + # # Only show XML & PDF options + # admin.download_links = [:xml, :pdf] + # + # end + + + # == Pagination + # + # Pagination is enabled by default for all resources. + # You can control the default per page count for all resources here. + # + # config.default_per_page = 30 + + + # == Filters + # + # By default the index screen includes a “Filters” sidebar on the right + # hand side with a filter for each attribute of the registered model. + # You can enable or disable them for all resources here. + # + # config.filters = true + end From 868ce33cd12d7dd37c8498d16cf03a8512c76694 Mon Sep 17 00:00:00 2001 From: Sean Linsley Date: Tue, 3 Dec 2013 22:49:01 -0600 Subject: [PATCH 2/3] update JS & SVG assets --- .../active_admin/index_list_icons/block_icon.svg | 10 ++++++++++ .../active_admin/index_list_icons/blog_icon.svg | 4 ++++ .../active_admin/index_list_icons/grid_icon.svg | 13 +++++++++++++ .../active_admin/index_list_icons/table_icon.svg | 3 +++ public/javascripts/active_admin.js | 2 +- 5 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 public/images/active_admin/index_list_icons/block_icon.svg create mode 100644 public/images/active_admin/index_list_icons/blog_icon.svg create mode 100644 public/images/active_admin/index_list_icons/grid_icon.svg create mode 100644 public/images/active_admin/index_list_icons/table_icon.svg diff --git a/public/images/active_admin/index_list_icons/block_icon.svg b/public/images/active_admin/index_list_icons/block_icon.svg new file mode 100644 index 00000000..70bf534c --- /dev/null +++ b/public/images/active_admin/index_list_icons/block_icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/images/active_admin/index_list_icons/blog_icon.svg b/public/images/active_admin/index_list_icons/blog_icon.svg new file mode 100644 index 00000000..b9d3216d --- /dev/null +++ b/public/images/active_admin/index_list_icons/blog_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/active_admin/index_list_icons/grid_icon.svg b/public/images/active_admin/index_list_icons/grid_icon.svg new file mode 100644 index 00000000..b1645fad --- /dev/null +++ b/public/images/active_admin/index_list_icons/grid_icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/public/images/active_admin/index_list_icons/table_icon.svg b/public/images/active_admin/index_list_icons/table_icon.svg new file mode 100644 index 00000000..13b8068e --- /dev/null +++ b/public/images/active_admin/index_list_icons/table_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/javascripts/active_admin.js b/public/javascripts/active_admin.js index 469c7926..ee9f1640 100644 --- a/public/javascripts/active_admin.js +++ b/public/javascripts/active_admin.js @@ -1 +1 @@ -(function(){window.AA={}}).call(this),function(){window.AA.CheckboxToggler=AA.CheckboxToggler=function(){function a(a,b){var c;this.options=a,this.container=b,c={},this.options=$.extend({},c,a),this._init(),this._bind()}return a.name="CheckboxToggler",a.prototype._init=function(){if(!this.container)throw new Error("Container element not found");this.$container=$(this.container);if(!this.$container.find(".toggle_all").length)throw new Error("'toggle all' checkbox not found");return this.toggle_all_checkbox=this.$container.find(".toggle_all"),this.checkboxes=this.$container.find(":checkbox").not(this.toggle_all_checkbox)},a.prototype._bind=function(){var a=this;return this.checkboxes.bind("change",function(b){return a._didChangeCheckbox(b.target)}),this.toggle_all_checkbox.bind("change",function(b){return a._didChangeToggleAllCheckbox()})},a.prototype._didChangeCheckbox=function(a){if(this.checkboxes.filter(":checked").length===this.checkboxes.length-1)return this._uncheckToggleAllCheckbox();if(this.checkboxes.filter(":checked").length===this.checkboxes.length)return this._checkToggleAllCheckbox()},a.prototype._didChangeToggleAllCheckbox=function(){return this.toggle_all_checkbox.attr("checked")==="checked"?this._checkAllCheckboxes():this._uncheckAllCheckboxes()},a.prototype._uncheckToggleAllCheckbox=function(){return this.toggle_all_checkbox.removeAttr("checked")},a.prototype._checkToggleAllCheckbox=function(){return this.toggle_all_checkbox.attr("checked","checked")},a.prototype._uncheckAllCheckboxes=function(){var a=this;return this.checkboxes.each(function(b,c){return $(c).removeAttr("checked"),a._didChangeCheckbox(c)})},a.prototype._checkAllCheckboxes=function(){var a=this;return this.checkboxes.each(function(b,c){return $(c).attr("checked","checked"),a._didChangeCheckbox(c)})},a}(),function(a){return a.widget.bridge("checkboxToggler",AA.CheckboxToggler)}(jQuery)}.call(this),function(){window.AA.DropdownMenu=AA.DropdownMenu=function(){function a(a,b){var c;return this.options=a,this.element=b,this.$element=$(this.element),c={fadeInDuration:20,fadeOutDuration:100,onClickActionItemCallback:null},this.options=$.extend({},c,a),this.$menuButton=this.$element.find(".dropdown_menu_button"),this.$menuList=this.$element.find(".dropdown_menu_list_wrapper"),this.isOpen=!1,this._buildMenuList(),this._bind(),this}return a.name="DropdownMenu",a.prototype.open=function(){return this.isOpen=!0,this.$menuList.fadeIn(this.options.fadeInDuration),this._positionMenuList(),this._positionNipple(),this},a.prototype.close=function(){return this.isOpen=!1,this.$menuList.fadeOut(this.options.fadeOutDuration),this},a.prototype.destroy=function(){return this.$element.unbind(),this.$element=null,this},a.prototype.isDisabled=function(){return this.$menuButton.hasClass("disabled")},a.prototype.disable=function(){return this.$menuButton.addClass("disabled")},a.prototype.enable=function(){return this.$menuButton.removeClass("disabled")},a.prototype.option=function(a,b){return $.isPlainObject(a)?this.options=$.extend(!0,this.options,a):a!=null?this.options[a]:this.options[a]=b},a.prototype._buildMenuList=function(){return this.$menuList.prepend(''),this.$menuList.hide()},a.prototype._bind=function(){var a=this;return $("body").bind("click",function(){if(a.isOpen===!0)return a.close()}),this.$menuButton.bind("click",function(){return a.isDisabled()||(a.isOpen===!0?a.close():a.open()),!1})},a.prototype._positionMenuList=function(){var a,b,c;return a=this.$menuButton.offset().left+this.$menuButton.outerWidth()/2,b=this.$menuList.outerWidth()/2,c=a-b,this.$menuList.css("left",c)},a.prototype._positionNipple=function(){var a,b,c,d,e;return c=this.$menuList.outerWidth()/2,b=this.$menuButton.offset().top+this.$menuButton.outerHeight()+10,this.$menuList.css("top",b),a=this.$menuList.find(".dropdown_menu_nipple"),d=a.outerWidth()/2,e=c-d,a.css("left",e)},a}(),function(a){return a.widget.bridge("aaDropdownMenu",AA.DropdownMenu),a(function(){return a(".dropdown_menu").aaDropdownMenu()})}(jQuery)}.call(this),function(){window.AA.Popover=AA.Popover=function(){function a(a,b){var c;return this.options=a,this.element=b,this.$element=$(this.element),c={fadeInDuration:20,fadeOutDuration:100,autoOpen:!0,pageWrapperElement:"#wrapper",onClickActionItemCallback:null},this.options=$.extend({},c,a),this.$popover=null,this.isOpen=!1,$(this.$element.attr("href")).length>0?this.$popover=$(this.$element.attr("href")):this.$popover=this.$element.next(".popover"),this._buildPopover(),this._bind(),this}return a.name="Popover",a.prototype.open=function(){return this.isOpen=!0,this.$popover.fadeIn(this.options.fadeInDuration),this._positionPopover(),this._positionNipple(),this},a.prototype.close=function(){return this.isOpen=!1,this.$popover.fadeOut(this.options.fadeOutDuration),this},a.prototype.destroy=function(){return this.$element.removeData("popover"),this.$element.unbind(),this.$element=null,this},a.prototype.option=function(){},a.prototype._buildPopover=function(){return this.$popover.prepend('
'),this.$popover.hide(),this.$popover.addClass("popover")},a.prototype._bind=function(){var a=this;$(this.options.pageWrapperElement).bind("click",function(b){if(a.isOpen===!0)return a.close()});if(this.options.autoOpen===!0)return this.$element.bind("click",function(){return a.isOpen===!0?a.close():a.open(),!1})},a.prototype._positionPopover=function(){var a,b,c;return a=this.$element.offset().left+this.$element.outerWidth()/2,b=this.$popover.outerWidth()/2,c=a-b,this.$popover.css("left",c)},a.prototype._positionNipple=function(){var a,b,c,d,e;return c=this.$popover.outerWidth()/2,b=this.$element.offset().top+this.$element.outerHeight()+10,this.$popover.css("top",b),a=this.$popover.find(".popover_nipple"),d=a.outerWidth()/2,e=c-d,a.css("left",e)},a}(),function(a){return a.widget.bridge("popover",AA.Popover)}(jQuery)}.call(this),function(){var a={}.hasOwnProperty,b=function(b,c){function e(){this.constructor=b}for(var d in c)a.call(c,d)&&(b[d]=c[d]);return e.prototype=c.prototype,b.prototype=new e,b.__super__=c.prototype,b};window.AA.TableCheckboxToggler=AA.TableCheckboxToggler=function(a){function c(){return c.__super__.constructor.apply(this,arguments)}return b(c,a),c.name="TableCheckboxToggler",c.prototype._init=function(){return c.__super__._init.apply(this,arguments)},c.prototype._bind=function(){var a=this;return c.__super__._bind.apply(this,arguments),this.$container.find("tbody").find("td").bind("click",function(b){if(b.target.type!=="checkbox")return a._didClickCell(b.target)})},c.prototype._didChangeCheckbox=function(a){var b;return c.__super__._didChangeCheckbox.apply(this,arguments),b=$(a).parents("tr"),a.checked?b.addClass("selected"):b.removeClass("selected")},c.prototype._didClickCell=function(a){return $(a).parent("tr").find(":checkbox").click()},c}(AA.CheckboxToggler),function(a){return a.widget.bridge("tableCheckboxToggler",AA.TableCheckboxToggler)}(jQuery)}.call(this),function(){$(function(){return $(".datepicker").datepicker({dateFormat:"yy-mm-dd"}),$(".clear_filters_btn").click(function(){return window.location.search="",!1}),$(".dropdown_button").popover()})}.call(this),function(){jQuery(function(a){a(document).delegate("#batch_actions_selector li a","click.rails",function(){return a("#batch_action").val(a(this).attr("data-action")),a("#collection_selection").submit()});if(a("#batch_actions_selector").length&&a(":checkbox.toggle_all").length)return a(".paginated_collection").find("table.index_table").length?a(".paginated_collection table").tableCheckboxToggler():a(".paginated_collection").checkboxToggler(),a(".paginated_collection").find(":checkbox").bind("change",function(){return a(".paginated_collection").find(":checkbox").filter(":checked").length>0?a("#batch_actions_selector").aaDropdownMenu("enable"):a("#batch_actions_selector").aaDropdownMenu("disable")})})}.call(this); \ No newline at end of file +(function(){window.ActiveAdmin={},window.AA||(window.AA=window.ActiveAdmin)}).call(this),function(){window.ActiveAdmin.CheckboxToggler=ActiveAdmin.CheckboxToggler=function(){function t(t,e){var n;this.options=t,this.container=e,n={},this.options=$.extend({},n,t),this._init(),this._bind()}return t.prototype._init=function(){if(!this.container)throw new Error("Container element not found");if(this.$container=$(this.container),!this.$container.find(".toggle_all").length)throw new Error('"toggle all" checkbox not found');return this.toggle_all_checkbox=this.$container.find(".toggle_all"),this.checkboxes=this.$container.find(":checkbox").not(this.toggle_all_checkbox)},t.prototype._bind=function(){var t=this;return this.checkboxes.change(function(e){return t._didChangeCheckbox(e.target)}),this.toggle_all_checkbox.change(function(){return t._didChangeToggleAllCheckbox()})},t.prototype._didChangeCheckbox=function(){switch(this.checkboxes.filter(":checked").length){case this.checkboxes.length-1:return this.toggle_all_checkbox.prop({checked:null});case this.checkboxes.length:return this.toggle_all_checkbox.prop({checked:!0})}},t.prototype._didChangeToggleAllCheckbox=function(){var t,e=this;return t=this.toggle_all_checkbox.prop("checked")?!0:null,this.checkboxes.each(function(n,i){return $(i).prop({checked:t}),e._didChangeCheckbox(i)})},t}(),jQuery(function(t){return t.widget.bridge("checkboxToggler",ActiveAdmin.CheckboxToggler)})}.call(this),function(){window.ActiveAdmin.DropdownMenu=ActiveAdmin.DropdownMenu=function(){function t(t,e){var n;this.options=t,this.element=e,this.$element=$(this.element),n={fadeInDuration:20,fadeOutDuration:100,onClickActionItemCallback:null},this.options=$.extend({},n,t),this.$menuButton=this.$element.find(".dropdown_menu_button"),this.$menuList=this.$element.find(".dropdown_menu_list_wrapper"),this.isOpen=!1,this._buildMenuList(),this._bind()}return t.prototype.open=function(){return this.isOpen=!0,this.$menuList.fadeIn(this.options.fadeInDuration),this._positionMenuList(),this._positionNipple(),this},t.prototype.close=function(){return this.isOpen=!1,this.$menuList.fadeOut(this.options.fadeOutDuration),this},t.prototype.destroy=function(){return this.$element.unbind(),this.$element=null,this},t.prototype.isDisabled=function(){return this.$menuButton.hasClass("disabled")},t.prototype.disable=function(){return this.$menuButton.addClass("disabled")},t.prototype.enable=function(){return this.$menuButton.removeClass("disabled")},t.prototype.option=function(t,e){return $.isPlainObject(t)?this.options=$.extend(!0,this.options,t):null!=t?this.options[t]:this.options[t]=e},t.prototype._buildMenuList=function(){return this.$menuList.prepend(''),this.$menuList.hide()},t.prototype._bind=function(){var t=this;return $("body").bind("click",function(){return t.isOpen===!0?t.close():void 0}),this.$menuButton.bind("click",function(){return t.isDisabled()||(t.isOpen===!0?t.close():t.open()),!1})},t.prototype._positionMenuList=function(){var t,e,n;return t=this.$menuButton.position().left+this.$menuButton.outerWidth()/2,e=this.$menuList.outerWidth()/2,n=t-e,this.$menuList.css("left",n)},t.prototype._positionNipple=function(){var t,e,n,i,o;return n=this.$menuList.outerWidth()/2,e=this.$menuButton.position().top+this.$menuButton.outerHeight()+10,this.$menuList.css("top",e),t=this.$menuList.find(".dropdown_menu_nipple"),i=t.outerWidth()/2,o=n-i,t.css("left",o)},t}(),function(t){return t.widget.bridge("aaDropdownMenu",ActiveAdmin.DropdownMenu),t(function(){return t(".dropdown_menu").aaDropdownMenu()})}(jQuery)}.call(this),function(){window.ActiveAdmin.Popover=ActiveAdmin.Popover=function(){function t(t,e){var n;this.options=t,this.element=e,this.$element=$(this.element),n={fadeInDuration:20,fadeOutDuration:100,autoOpen:!0,pageWrapperElement:"#wrapper",onClickActionItemCallback:null},this.options=$.extend({},n,t),this.$popover=null,this.isOpen=!1,this.$popover=$(this.$element.attr("href")).length>0?$(this.$element.attr("href")):this.$element.next(".popover"),this._buildPopover(),this._bind()}return t.prototype.open=function(){return this.isOpen=!0,this.$popover.fadeIn(this.options.fadeInDuration),this._positionPopover(),this._positionNipple(),this},t.prototype.close=function(){return this.isOpen=!1,this.$popover.fadeOut(this.options.fadeOutDuration),this},t.prototype.destroy=function(){return this.$element.removeData("popover"),this.$element.unbind(),this.$element=null,this},t.prototype.option=function(){},t.prototype._buildPopover=function(){return this.$popover.prepend('
'),this.$popover.hide(),this.$popover.addClass("popover")},t.prototype._bind=function(){var t=this;return $(this.options.pageWrapperElement).bind("click",function(){return t.isOpen===!0?t.close():void 0}),this.options.autoOpen===!0?this.$element.bind("click",function(){return t.isOpen===!0?t.close():t.open(),!1}):void 0},t.prototype._positionPopover=function(){var t,e,n;return t=this.$element.offset().left+this.$element.outerWidth()/2,e=this.$popover.outerWidth()/2,n=t-e,this.$popover.css("left",n)},t.prototype._positionNipple=function(){var t,e,n,i,o;return n=this.$popover.outerWidth()/2,e=this.$element.offset().top+this.$element.outerHeight()+10,this.$popover.css("top",e),t=this.$popover.find(".popover_nipple"),i=t.outerWidth()/2,o=n-i,t.css("left",o)},t}(),function(t){return t.widget.bridge("popover",ActiveAdmin.Popover)}(jQuery)}.call(this),function(){var t,e={}.hasOwnProperty,n=function(t,n){function i(){this.constructor=t}for(var o in n)e.call(n,o)&&(t[o]=n[o]);return i.prototype=n.prototype,t.prototype=new i,t.__super__=n.prototype,t};window.ActiveAdmin.TableCheckboxToggler=ActiveAdmin.TableCheckboxToggler=function(e){function i(){return t=i.__super__.constructor.apply(this,arguments)}return n(i,e),i.prototype._init=function(){return i.__super__._init.apply(this,arguments)},i.prototype._bind=function(){var t=this;return i.__super__._bind.apply(this,arguments),this.$container.find("tbody td").click(function(e){return"checkbox"!==e.target.type?t._didClickCell(e.target):void 0})},i.prototype._didChangeCheckbox=function(t){var e;return i.__super__._didChangeCheckbox.apply(this,arguments),e=$(t).parents("tr"),t.checked?e.addClass("selected"):e.removeClass("selected")},i.prototype._didClickCell=function(t){return $(t).parent("tr").find(":checkbox").click()},i}(ActiveAdmin.CheckboxToggler),jQuery(function(t){return t.widget.bridge("tableCheckboxToggler",ActiveAdmin.TableCheckboxToggler)})}.call(this),function(){$(function(){return $(document).on("focus",".datepicker:not(.hasDatepicker)",function(){return $(this).datepicker({dateFormat:"yy-mm-dd"})}),$(".clear_filters_btn").click(function(){return window.location.search=""}),$(".dropdown_button").popover(),$(".filter_form").submit(function(){return $(this).find(":input").filter(function(){return""===this.value}).prop("disabled",!0)}),$(".filter_form_field.select_and_search select").change(function(){return $(this).siblings("input").prop({name:"q["+this.value+"]"})})})}.call(this),function(){jQuery(function(t){return t(document).delegate("#batch_actions_selector li a","click.rails",function(){return t("#batch_action").val(t(this).attr("data-action")),t("#collection_selection").submit()}),t("#batch_actions_selector").length&&t(":checkbox.toggle_all").length?(t(".paginated_collection table.index_table").length?t(".paginated_collection table.index_table").tableCheckboxToggler():t(".paginated_collection").checkboxToggler(),t(".paginated_collection").find(":checkbox").bind("change",function(){return t(".paginated_collection").find(":checkbox").filter(":checked").length>0?t("#batch_actions_selector").aaDropdownMenu("enable"):t("#batch_actions_selector").aaDropdownMenu("disable")})):void 0})}.call(this); \ No newline at end of file From 193a9283e2869371a0e0cfc280d7753a1d1134e7 Mon Sep 17 00:00:00 2001 From: Sean Linsley Date: Tue, 3 Dec 2013 22:49:08 -0600 Subject: [PATCH 3/3] update products --- db/seeds/products.yml | 285 ++++++++---------- ...ssional-expert-s-voice-in-open-source-.jpg | Bin 0 -> 4246 bytes ...ter-science-programming-basics-in-ruby.jpg | Bin 0 -> 3944 bytes ...dison-wesley-professional-ruby-series-.jpg | Bin 0 -> 5342 bytes ...-programmers-guide-the-facets-of-ruby-.jpg | Bin 0 -> 3815 bytes ...an-illustrated-guide-to-ruby-internals.jpg | Bin 0 -> 5674 bytes 6 files changed, 121 insertions(+), 164 deletions(-) create mode 100644 public/images/products/beginning-ruby-from-novice-to-professional-expert-s-voice-in-open-source-.jpg create mode 100644 public/images/products/computer-science-programming-basics-in-ruby.jpg create mode 100644 public/images/products/practical-object-oriented-design-in-ruby-an-agile-primer-addison-wesley-professional-ruby-series-.jpg create mode 100644 public/images/products/programming-ruby-1-9-2-0-the-pragmatic-programmers-guide-the-facets-of-ruby-.jpg create mode 100644 public/images/products/ruby-under-a-microscope-an-illustrated-guide-to-ruby-internals.jpg diff --git a/db/seeds/products.yml b/db/seeds/products.yml index 9562cfa6..df26b872 100644 --- a/db/seeds/products.yml +++ b/db/seeds/products.yml @@ -1,170 +1,127 @@ ---- -- :price: "23.75" - :author: "David Flanagan and Yukihiro Matsumoto " - :title: The Ruby Programming Language +--- +- :title: The Ruby Programming Language + :author: 'David Flanagan and Yukihiro Matsumoto ' + :price: '27.13' :image_file_name: the-ruby-programming-language.jpg - :featured: true - :available_on: 2011-02-16 -- :price: "28.20" - :author: "Dave Thomas, Chad Fowler, and Andy Hunt " - :title: "Programming Ruby 1.9: The Pragmatic Programmers' Guide (Facets of Ruby)" - :image_file_name: programming-ruby-1-9-the-pragmatic-programmers-guide-facets-of-ruby-.jpg - :featured: true - :available_on: 2011-02-16 -- :price: "22.61" - :author: "Peter Cooper " - :title: "Beginning Ruby: From Novice to Professional" - :image_file_name: beginning-ruby-from-novice-to-professional.jpg - :available_on: 2011-02-16 -- :price: "20.50" - :author: "Paolo Perrotta " - :title: "Metaprogramming Ruby: Program Like the Ruby Pros" - :image_file_name: metaprogramming-ruby-program-like-the-ruby-pros.jpg - :available_on: 2011-02-16 -- :price: "27.99" - :author: "David A. Black " - :title: The Well-Grounded Rubyist - :image_file_name: the-well-grounded-rubyist.jpg - :available_on: 2011-02-16 -- :price: "31.17" - :author: "Lucas Carlson and Leonard Richardson " - :title: Ruby Cookbook (Cookbooks (O'Reilly)) - :image_file_name: ruby-cookbook-cookbooks-o-reilly-.jpg - :available_on: 2011-02-16 -- :price: "13.92" - :author: "Chris Pine " - :title: Learn to Program, Second Edition (The Facets of Ruby Series) - :image_file_name: learn-to-program-second-edition-the-facets-of-ruby-series-.jpg - :available_on: 2011-02-16 -- :price: "22.85" - :author: "Michael James Fitzgerald " - :title: Learning Ruby - :image_file_name: learning-ruby.jpg - :available_on: 2011-02-16 -- :price: "23.07" - :author: "Bruce Tate " - :title: "Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages (Pragmatic Programmers)" - :image_file_name: seven-languages-in-seven-weeks-a-pragmatic-guide-to-learning-programming-languages-pragmatic-programmers-.jpg - :featured: true - :available_on: 2011-02-16 -- :price: "9.99" - :author: "Neil Smyth " - :title: Ruby Programming Essentials - :image_file_name: ruby-programming-essentials.jpg - :available_on: 2011-02-16 -- :price: "28.21" - :author: "Russ Olsen " - :title: Eloquent Ruby (Addison-Wesley Professional Ruby Series) + :available_on: 2013-12-02 +- :title: 'Programming Ruby 1.9 & 2.0: The Pragmatic Programmers'' Guide (The Facets + of Ruby)' + :author: 'Dave Thomas, Andy Hunt and Chad Fowler ' + :price: '37.65' + :image_file_name: programming-ruby-1-9-2-0-the-pragmatic-programmers-guide-the-facets-of-ruby-.jpg + :available_on: 2013-12-02 +- :title: Eloquent Ruby (Addison-Wesley Professional Ruby Series) + :author: 'Russ Olsen ' + :price: '32.13' :image_file_name: eloquent-ruby-addison-wesley-professional-ruby-series-.jpg - :available_on: 2011-02-16 -- :price: "23.75" - :author: "David Flanagan and Yukihiro Matsumoto " - :title: The Ruby Programming Language - :image_file_name: the-ruby-programming-language.jpg - :available_on: 2011-02-16 -- :price: "28.20" - :author: "Dave Thomas, Chad Fowler, and Andy Hunt " - :title: "Programming Ruby 1.9: The Pragmatic Programmers' Guide (Facets of Ruby)" - :image_file_name: programming-ruby-1-9-the-pragmatic-programmers-guide-facets-of-ruby-.jpg - :available_on: 2011-02-16 -- :price: "22.61" - :author: "Peter Cooper " - :title: "Beginning Ruby: From Novice to Professional" - :image_file_name: beginning-ruby-from-novice-to-professional.jpg - :available_on: 2011-02-16 -- :price: "20.50" - :author: "Paolo Perrotta " - :title: "Metaprogramming Ruby: Program Like the Ruby Pros" - :image_file_name: metaprogramming-ruby-program-like-the-ruby-pros.jpg - :available_on: 2011-02-16 -- :price: "27.99" - :author: "David A. Black " - :title: The Well-Grounded Rubyist - :image_file_name: the-well-grounded-rubyist.jpg - :featured: true - :available_on: 2011-02-16 -- :price: "31.17" - :author: "Lucas Carlson and Leonard Richardson " - :title: Ruby Cookbook (Cookbooks (O'Reilly)) - :image_file_name: ruby-cookbook-cookbooks-o-reilly-.jpg - :available_on: 2011-02-16 -- :price: "13.92" - :author: "Chris Pine " - :title: Learn to Program, Second Edition (The Facets of Ruby Series) + :available_on: 2013-12-02 +- :title: 'Ruby Under a Microscope: An Illustrated Guide to Ruby Internals' + :author: 'Pat Shaughnessy ' + :price: '28.96' + :image_file_name: ruby-under-a-microscope-an-illustrated-guide-to-ruby-internals.jpg + :available_on: 2013-12-02 +- :title: Computer Science Programming Basics in Ruby + :author: 'Ophir Frieder, Gideon Frieder and David Grossman ' + :price: '22.49' + :image_file_name: computer-science-programming-basics-in-ruby.jpg + :available_on: 2013-12-02 +- :title: 'Practical Object-Oriented Design in Ruby: An Agile Primer (Addison-Wesley + Professional Ruby Series)' + :author: 'Sandi Metz ' + :price: '29.96' + :image_file_name: practical-object-oriented-design-in-ruby-an-agile-primer-addison-wesley-professional-ruby-series-.jpg + :available_on: 2013-12-02 +- :title: 'Beginning Ruby: From Novice to Professional (Expert''s Voice in Open Source)' + :author: 'Peter Cooper ' + :price: '26.05' + :image_file_name: beginning-ruby-from-novice-to-professional-expert-s-voice-in-open-source-.jpg + :available_on: 2013-12-02 +- :title: Learn to Program, Second Edition (The Facets of Ruby Series) + :author: 'Chris Pine ' + :price: '17.88' :image_file_name: learn-to-program-second-edition-the-facets-of-ruby-series-.jpg - :available_on: 2011-02-16 -- :price: "22.85" - :author: "Michael James Fitzgerald " - :title: Learning Ruby - :image_file_name: learning-ruby.jpg - :available_on: 2011-02-16 -- :price: "23.07" - :author: "Bruce Tate " - :title: "Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages (Pragmatic Programmers)" - :image_file_name: seven-languages-in-seven-weeks-a-pragmatic-guide-to-learning-programming-languages-pragmatic-programmers-.jpg - :available_on: 2011-02-16 -- :price: "9.99" - :author: "Neil Smyth " - :title: Ruby Programming Essentials - :image_file_name: ruby-programming-essentials.jpg - :available_on: 2011-02-16 -- :price: "28.21" - :author: "Russ Olsen " - :title: Eloquent Ruby (Addison-Wesley Professional Ruby Series) - :image_file_name: eloquent-ruby-addison-wesley-professional-ruby-series-.jpg - :available_on: 2011-02-16 -- :price: "23.75" - :author: "David Flanagan and Yukihiro Matsumoto " - :title: The Ruby Programming Language + :available_on: 2013-12-02 +- :title: The Ruby Programming Language + :author: 'David Flanagan and Yukihiro Matsumoto ' + :price: '27.13' :image_file_name: the-ruby-programming-language.jpg - :available_on: 2011-02-16 -- :price: "28.20" - :author: "Dave Thomas, Chad Fowler, and Andy Hunt " - :title: "Programming Ruby 1.9: The Pragmatic Programmers' Guide (Facets of Ruby)" - :image_file_name: programming-ruby-1-9-the-pragmatic-programmers-guide-facets-of-ruby-.jpg - :available_on: 2011-02-16 -- :price: "22.61" - :author: "Peter Cooper " - :title: "Beginning Ruby: From Novice to Professional" - :image_file_name: beginning-ruby-from-novice-to-professional.jpg - :available_on: 2011-02-16 -- :price: "20.50" - :author: "Paolo Perrotta " - :title: "Metaprogramming Ruby: Program Like the Ruby Pros" - :image_file_name: metaprogramming-ruby-program-like-the-ruby-pros.jpg - :available_on: 2011-02-16 -- :price: "27.99" - :author: "David A. Black " - :title: The Well-Grounded Rubyist - :image_file_name: the-well-grounded-rubyist.jpg - :available_on: 2011-02-16 -- :price: "31.17" - :author: "Lucas Carlson and Leonard Richardson " - :title: Ruby Cookbook (Cookbooks (O'Reilly)) - :image_file_name: ruby-cookbook-cookbooks-o-reilly-.jpg - :available_on: 2011-02-16 -- :price: "13.92" - :author: "Chris Pine " - :title: Learn to Program, Second Edition (The Facets of Ruby Series) + :available_on: 2013-12-02 +- :title: 'Programming Ruby 1.9 & 2.0: The Pragmatic Programmers'' Guide (The Facets + of Ruby)' + :author: 'Dave Thomas, Andy Hunt and Chad Fowler ' + :price: '37.65' + :image_file_name: programming-ruby-1-9-2-0-the-pragmatic-programmers-guide-the-facets-of-ruby-.jpg + :available_on: 2013-12-02 +- :title: Eloquent Ruby (Addison-Wesley Professional Ruby Series) + :author: 'Russ Olsen ' + :price: '32.13' + :image_file_name: eloquent-ruby-addison-wesley-professional-ruby-series-.jpg + :available_on: 2013-12-02 +- :title: 'Ruby Under a Microscope: An Illustrated Guide to Ruby Internals' + :author: 'Pat Shaughnessy ' + :price: '28.96' + :image_file_name: ruby-under-a-microscope-an-illustrated-guide-to-ruby-internals.jpg + :available_on: 2013-12-02 +- :title: Computer Science Programming Basics in Ruby + :author: 'Ophir Frieder, Gideon Frieder and David Grossman ' + :price: '22.49' + :image_file_name: computer-science-programming-basics-in-ruby.jpg + :available_on: 2013-12-02 +- :title: 'Practical Object-Oriented Design in Ruby: An Agile Primer (Addison-Wesley + Professional Ruby Series)' + :author: 'Sandi Metz ' + :price: '29.96' + :image_file_name: practical-object-oriented-design-in-ruby-an-agile-primer-addison-wesley-professional-ruby-series-.jpg + :available_on: 2013-12-02 +- :title: 'Beginning Ruby: From Novice to Professional (Expert''s Voice in Open Source)' + :author: 'Peter Cooper ' + :price: '26.05' + :image_file_name: beginning-ruby-from-novice-to-professional-expert-s-voice-in-open-source-.jpg + :available_on: 2013-12-02 +- :title: Learn to Program, Second Edition (The Facets of Ruby Series) + :author: 'Chris Pine ' + :price: '17.88' :image_file_name: learn-to-program-second-edition-the-facets-of-ruby-series-.jpg - :available_on: 2011-02-16 -- :price: "22.85" - :author: "Michael James Fitzgerald " - :title: Learning Ruby - :image_file_name: learning-ruby.jpg - :available_on: 2011-02-16 -- :price: "23.07" - :author: "Bruce Tate " - :title: "Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages (Pragmatic Programmers)" - :image_file_name: seven-languages-in-seven-weeks-a-pragmatic-guide-to-learning-programming-languages-pragmatic-programmers-.jpg - :available_on: 2011-02-16 -- :price: "9.99" - :author: "Neil Smyth " - :title: Ruby Programming Essentials - :image_file_name: ruby-programming-essentials.jpg - :available_on: 2011-02-16 -- :price: "28.21" - :author: "Russ Olsen " - :title: Eloquent Ruby (Addison-Wesley Professional Ruby Series) + :available_on: 2013-12-02 +- :title: The Ruby Programming Language + :author: 'David Flanagan and Yukihiro Matsumoto ' + :price: '27.13' + :image_file_name: the-ruby-programming-language.jpg + :available_on: 2013-12-02 +- :title: 'Programming Ruby 1.9 & 2.0: The Pragmatic Programmers'' Guide (The Facets + of Ruby)' + :author: 'Dave Thomas, Andy Hunt and Chad Fowler ' + :price: '37.65' + :image_file_name: programming-ruby-1-9-2-0-the-pragmatic-programmers-guide-the-facets-of-ruby-.jpg + :available_on: 2013-12-02 +- :title: Eloquent Ruby (Addison-Wesley Professional Ruby Series) + :author: 'Russ Olsen ' + :price: '32.13' :image_file_name: eloquent-ruby-addison-wesley-professional-ruby-series-.jpg - :available_on: 2011-02-16 + :available_on: 2013-12-02 +- :title: 'Ruby Under a Microscope: An Illustrated Guide to Ruby Internals' + :author: 'Pat Shaughnessy ' + :price: '28.96' + :image_file_name: ruby-under-a-microscope-an-illustrated-guide-to-ruby-internals.jpg + :available_on: 2013-12-02 +- :title: Computer Science Programming Basics in Ruby + :author: 'Ophir Frieder, Gideon Frieder and David Grossman ' + :price: '22.49' + :image_file_name: computer-science-programming-basics-in-ruby.jpg + :available_on: 2013-12-02 +- :title: 'Practical Object-Oriented Design in Ruby: An Agile Primer (Addison-Wesley + Professional Ruby Series)' + :author: 'Sandi Metz ' + :price: '29.96' + :image_file_name: practical-object-oriented-design-in-ruby-an-agile-primer-addison-wesley-professional-ruby-series-.jpg + :available_on: 2013-12-02 +- :title: 'Beginning Ruby: From Novice to Professional (Expert''s Voice in Open Source)' + :author: 'Peter Cooper ' + :price: '26.05' + :image_file_name: beginning-ruby-from-novice-to-professional-expert-s-voice-in-open-source-.jpg + :available_on: 2013-12-02 +- :title: Learn to Program, Second Edition (The Facets of Ruby Series) + :author: 'Chris Pine ' + :price: '17.88' + :image_file_name: learn-to-program-second-edition-the-facets-of-ruby-series-.jpg + :available_on: 2013-12-02 diff --git a/public/images/products/beginning-ruby-from-novice-to-professional-expert-s-voice-in-open-source-.jpg b/public/images/products/beginning-ruby-from-novice-to-professional-expert-s-voice-in-open-source-.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8c3fb9612173f1afeb4220eac662563c4f700c42 GIT binary patch literal 4246 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 literal 0 HcmV?d00001 diff --git a/public/images/products/computer-science-programming-basics-in-ruby.jpg b/public/images/products/computer-science-programming-basics-in-ruby.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d8c0927fdde1c36b122f376a6087b9cb34c967ba GIT binary patch literal 3944 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 A#Q*>R literal 0 HcmV?d00001 diff --git a/public/images/products/practical-object-oriented-design-in-ruby-an-agile-primer-addison-wesley-professional-ruby-series-.jpg b/public/images/products/practical-object-oriented-design-in-ruby-an-agile-primer-addison-wesley-professional-ruby-series-.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9e82315de8a4c4ea562a750cc705624318b18ec0 GIT binary patch literal 5342 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 Y`lI6u-*y(sE$>}RG|_^_+g?om7pS(_)c^nh literal 0 HcmV?d00001 diff --git a/public/images/products/programming-ruby-1-9-2-0-the-pragmatic-programmers-guide-the-facets-of-ruby-.jpg b/public/images/products/programming-ruby-1-9-2-0-the-pragmatic-programmers-guide-the-facets-of-ruby-.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bc13ca8dae39969ae14fed0ebc7215325a5b4679 GIT binary patch literal 3815 zcmb7Gc{J2*|NhQ~nQX%-%h(4EDN7h3OOhG;7(5IqAv;4NOEgK@CNlgKnMgR1Avhr2okj44v7D; z2?PD{`!6^kP#7l{2o64=4fz2O1Ofp=!JJTzLw`H`263W9LJ4!C1T01N^{p&TIC zzwCiN5-K3ADu_~}!_*CJh=mjmql<2>`)q(40y;1bK?3@~V#7a>tTk%v=K4n$y;VNP z6T>Bo9+{;(XA~W{2oi0br(*+TS1O&JH^{R`vb{oH6POvflum{iuYXTk4mfWIb}9Cn z?#z>hn*Kw4HlgYc-){|1!PcfrRgK+?eW)ZBOuQv$^XUf2=1#MT5{eYpF?=e4c`FcZ zlnn_(&j|mPWLesNTL^zGWP58nrWFYNT zRe*@)Z`5qmGnd=DPX4C@S7&TDpXIZQb8_;nA_^70HkFkuZREO?yRw6Ijo43H(C(3- zEyTR-#A&VDyL}7UvIWCT#|Ayt6ibJ&wA5wYxvaBo7c=BpCj7ugIN+GcCAHZ2ECYYI zIMtv<$i8wDk=CcB@a=~x3DfO!>iuoVeOG`5J5!IIsf*d(wu>m(F-gw8nxq z$Yd4?dO?wMGgOsx;?3I*^x|hCFz#Y6Vq%|Ox3>IkmnK9#3wwsjWB~;%7{CgDLZX5b z@o40@eesRQHM%bPfrFL?nc;QP2>}z${lv~#F&iFix{{ki4nI+Adk)tYJNCRB`i>9HrMXck&)9-{*v9x(@+D&N@JE+Ft`FfxHTlWI_tIbR?DDA=FA8NA2$|wYW^c5 zvrUY7uk0v}%ZB0zC*Ht9*I`mT6@(k(4av%3T<;$ZD-`Pf?&?SN-+M(X>58iEY2z;< zz}a|Q$0AR=63X8NpB{2miE@&;*c&|AE7$E;w)W)nu?C@AXbdw4$%u}fj~yXZ1$?oa z*#QR}^M07!e@L@)ozoFPRH)SK7);+?`UX%9gcbCjdFwyuQx8^7IvG!gg=v0yLL5t^ zP(;qu`}ZNGwF#}=_&(X*#?gC7)1ZxD538pep zoHUFw!cY-(h7)>oi#Bw_g!V)h-^eod)+e1p*tcf=vVqQ~%tf{+yhjH|zrDO*;4AT* zTdj4v{bh+}nBWzmTAll<&*pm`m+oo^t3z)F!yD%%_#aH)z>Jl26@c}I$P72GO_ZSKAh(>f80-7!jbzC-mE|4hsi99Kx5do^xdJ? zT}Pem5MVSM`=WQb>D#=#tl6j1SM|o3G9-IfWrA_9bBCkZ0~rFDNKK0?_c%}5yff+Y z_4{3`fOvr`bJ^B9wZU1*C00TF_ZLNc)8}JOiw>}kmTywmfz$$@Vs7t|YGONvV5V<5YX#aIl3?r;zYLZG~aG($aN~#~k^^iwGKabr2i^`DM)nn~&UR*C-RL;Nr zM@!csu0;aDS?rDjgvO&(y?4&?_Z71GVzi?kh4{ujgIwROIEq@PG50>CBm!l^^G}J- zhvVro=ABnoe+70iHW>oH3%{g}nDt0$KQAf7;>S{P;IfYy<5xc@mu8b6k`)Qow{_Ku zOjLxnoA0uW@7)g9@_MuD674CL5?ja9FLz9^wNH-Ff)1PAyMPxR%!)iWAwsLSIpL*T zSZ{fK*ym8C3W@BF6Us<*hM)flU!lMI=YE}qe;~WkQe}2KuJrIekRbBnq0@NcL_2tR zbu$A@9Yj@1YU+So8%ww{>L2x7{}S$GH^*gOBM|a6)l$79WMgQLp2q8$pQH#G$fJG3 zn=wdcNwdj}$hFC}4%OF|9@)yPN=m(1Y!N47x^d$FrxJY77D{2njOCl+mN`?h3PQ*b zM>S0NvB$4nwf&^hDfw0bN8x!eTscF-*A?pivP6rSE~gWV+ktmiUdr069p)I~FODlO ziH(6Q8D6?zS2Ymj>!;DfoIK;bi(ivGl_Gvw$b8w~zcTI%kmti!{#aeZe@eyr=Ura? z6F4DiT)yAluhz~wg*iuxFiq5kRvjs8DaqIVl2u~A*mu_Rd{bjZFr&1Rl6gBQW~>~& zab~;uSH5e59;I3!l^It8Z~};r!@D+t&r~Ib1XPm5OZ(zAl>$Jm+N<5V4+rxseL@2m z2^9V<6e^vYs`!;SRpl}^p0ygz=yz16QwYSSJ`jNzYfYra64O1REc)#$z&(p5Kg85p znYXY-j|~bKynKGN(RX}45Xr|9WKmDslrKSsx?xMsk-kX619+Vj(x3 zqH7kf47DBVF77htq9Ay(2SV@f5Yy-8CvaXwdwweG@-axPAex1EoEHOgg)Z(07FBiORUU;AzN!l=9t z>AXAc`@-=@;38c!9ZOzPs!@=7PIAQM;i6pkVOyJu$xqTfW*3#N#XFIGN1mtL|J{Ly zg4J8~ntaTMBTU3oI~$!Di&aSzZ%7rELJxJ)s5%VO<-}wmI61}kfved_rGMykp40bs zn?tl%Tj`ps$8`h_mp_@+uTe7nMG_Ms(mv$-UDZno{b-4xWhR>4YG;CP@tfGv_%vD? zB6{}9@4Q-5YV;vED;YZ;CCI5ipXB3@o-|yQ;?UNJvB591{JVQ!%h;yZCc z9>r2BgJB6ELjvMYR8m%@pLX{sf?<_Vc$E<`)}v_kkUywaq2>$vpBgNW`3W5;Wl+U>IzxR6e%ImwJ@ zTxH0sx98c9J^kb5vp+fR1DqNf;z_S-GHXtung0X;?Op@cscb_LMV;UxgBFM|=jZ3H zHcm4&Rr4*$wNtHUCNu3(Pl)FxCcgw&Qu5Sq=GcE2*5my)6xTStkohAS6hBd`G_7-0 zhZwe3UKOVKG4h$2v+qlhpDvO=N~&u!^yRqs?7lu2yzA&JYFAWjWzuAhf%dxX-BB&s zaVP1$;8mmY7f~1>@ZXtNjFBI4lZLUaJ46TK) z6rU>1^A0w!^~JX_&J{wDMpKry3l4I>%dOab7BMN6`ETX(ef2c&CSecY-zmQf{QKylc;AM>^+R0(~BX8O(xL&#P z{JVm+x7%1Z`B^|5=PMO==mW1Z z5>hUjsL6I3rH#)jB!?-iYHZ)FYOwvekS$|D;}}1gCSCge92$d;YP>v`G*& zt4v{%(U((sdDYZF9crLSqkW((TI?5MuX$iB(a7rl-v-(ed9!;pp@%A(l;Zks^4TwZ zeVdk>q8pdIJ?Q|S`+o3xD{t%kn!K!iK+I7;%ff7FWyb1;M3ln&9Y*qnqSp{5I?ECydMA2`vO3X4 zbfQQ60>UTy zCjz{iLjo|zeOC~*f}S~zh-lzGA#GfC#mH?=Mfeh=4XUJX5tMUqJp&*I-spmXV1PVe zyNOYpp+T_V>zA_0Hl3Y2^Gf2+)v_oHwaE_Ff+JTL+Pas@Nj}v*`%K3K;>ktayHK0} zUIW}dUIQZ8E*Rx^$c(N5LI1TY|5KuI`A2QL+@Bn!^Q#$kS+a%PVO_B=5n$F|=(IFh zk6saTD~cyp>K`NbTjbXB@go}Mky0$Vcw};?&~|x7Lu;c?eRr|)8X$;R^>;0*lW}NL zC$=Yh>wh?({rp^SE27-)(J4ju{#v14|DqvEsOp14z~0wRR~FBW1JZ8=b;w>r9Z27% zAxm&Eg1y{`R9uaQO(!ve$mwu}ey!E#;{0jJDM5<8xog_GKo_q*ALiD%fCPRkm4`6# zbC$McDhp3!@AB1<)?rSg*EK-k%J2`O{=gaH@IKylZ~hu^e4p(P%8;>Z?$*lNXQ_5$ z#oZB~m?+CVqI+Hx${b&kKjh=_5j?;w9Mev`oW+Vcc;vrC!~YB^jts0Bj}?sa68`Qv z?)t)i?A2R#Te?YwWd@^JlDIf)A73DmAF@@zCv0`mf)@E$acxmhXcW6QRLwJ@ zP0!fXPFdUutIbp)w@4&N^wIGe@J#ZU(SJMM6nJAa}6f1i_JckiYn+#M003ukNJKJ!T@%?hhi?&<&^F9&39{0 z#y#Vt5W=NtkoU@u2H4dr$yZsQxELM*;nnjiHRj1-{o0u!G+;&gXQs~$**%HQP5r9E4W{?YzknJJi+A4q=S)aetW?ZdB&FTvvR z(>|hGEY--7HdLP{#h%FIQ9sFwZ0fkl1ySJ6Fq$QQ1ni;t4vYiD1(WMC z6oAz_%hJ*&M&W7UApvyIa-nE4F9WrZ#OnU}*U^1Wa5dB8!u)Lu^~vD=yX!^)?8S$8 zjh8FPla;(6Tyr_v*aL?&z!FRNDnDjqJCge~2C5px zr~!pN<9j7IpH*q_>g|}|e*#@&PU@cd0aKC5!BQtWyp-;Tvs)gmn~uhiHSjKNKL_y0 ziCKQ(_;4&Htid7_lf2|}!j$h(kt&7wTnW;28AVtfv|i@sY!Z)qL?~^xD1B`X_DY*_%FwQpnFb%2 zyG39t{qoUbQCe!hTMDPW=d<9W@?G+B8LxekP;8X^0tC_Hh7s1@EYp_hY%h4Zy5&n4 z*2dtXF*RGW8mv51s7o(b0g5_%xG31#=zJ9nEmN>mR3N2%1g&d>610miES?k#>`04= z=uE`*Q*V2}X_MTo?RH)(>c_gPXp5r|bA5uaVIlAtrPiyr8$ZPI( z)|oauKczq*g{O8e?brK&O|mjb;qg+NI^L=`BKWfUJS5`$Wr4xxa=FpCejA zCouI;Q>W~-vXg$Y2^lfh)R(qVZ{uD+5x!qdCwBztW>+nHo;zM~^Ajc8rpvggiRMyq zl2a<+9QS($bC{O`T`JBvNu`Rcrvxo6O)EaUdlyM1=o5mg7qcC)?;pukjpB;SFNZYK zISo(q$ti87{3p!0c3EgYokficKA$N#Nu)Ev3Xk=ZgMC$=Brp)CnyIQE%I-^V9E{P- zN~j1hCr{>7;NbB1$bp?PN^5J@Q|>kc3*SXEvyECD$`Glo<=6Zu^^l9%Cvf9;&t!+G zX60v;F6L*OX3dM94PZ-FoD@O$su&sDGnj4Wtxb{z+wNpZ^UfC;Eg{x=^AafKLzs@; zXRhSQxJ;SK_Ze&C(hSl`p35?4hmyZlKkMyk&P*9F$)>IrWW;4_P%;#RHGa#{luFh}-vrTn=gyEOrF)^>iBq z_Pj_*Mpu;h7S;ns8!(lyv5u})JSIK}?^ewH`FFGM7Zfz_X!cw9N~^Wgr{|$RG8!k+ zD?PEkQ|p8#7a$s!Pt~}CwB#x;CC{1tQIh&^Gf8Wiv_)~#3@m<&nn99xw?`l=@g!Bv z;pmCa&M=CW60V9)Tn1g-Luq9Lcu3+Y91(;#W#}%5$2J@;E#K*G+GSd%a(w6d)Pce0 zP)YO>L9Pqly&GV7cu z?j|vDPsMC;ebhGuD1-dbf}wh6gWU%n`&1_XN1n2FR)1~4S_ z+K7&g^=fNvg5;mD^07-ssU?WrFVVvIZEnW4u2M^H-Q9R&h^2*(X>&!GYMH7lWgTM1 zxgPKOn(IBu(zaFdsD{^%jB*xn-Xq}$t0(oW!k8KHL>toTyx(q-z<7Tdjcv z+b|GNmlC(ZW!i{pq2sJ8$e8d;!PXbaJ0MFmCfUrAveX>yxRP?~rDc*M8#H)!;OG4O zgESb@R2-H0X?$vH30)(u9H6Z|qHC4={&W?I=RGUg3XXjHnDnyH&PjTlNpr)n+QE8y z)P%dV78jPOZb`iUa3vvo2pJP;^PQJ8EnMcH?1Gf1vf!ZQaORXvX{!j);NZ|904fY) z5OQEz`m^XFBTz=f6^Nc2KWVR8AVij$3mU+T@;2bhgk>a0y*_uTLRu+pK z)tf|Pb+{vGdb~~_yOB)zK8=$29yal2`t}7zgGGx*R?M1T=3`FRnlu1n z85btIV%Y5|#j$|?v*g5l#{PJS1Dq676M1idWf}ig%(3Uh9>07I+ww=BW97To$9K znb^X7wjIe)$+{`}|0h1iwYXA7s-scIq7ky#{J+%38 z;c)6WYBy&IMrJUopdlF~M_o)_X1+ee%|$K&qt+ds= zGBXk7rC>TR0GbfXtiCqK3+^Y99nM;t%gt|)eT5VkZH?s$skaS;1-+qm&4TB7T{hS4 z@EGZXSoo8WBE(CPR_{-{Pmbi1bA7iTp~5?gO~I;Uu)JFQGc!9ZAH@R;`Ge^HRI&If4jp*SVM-;Y)(YMtW6#W8l=TvQGuk?sdweW zS1gjrX6dD*ZQ5Ked}C~}H|#oMSTNnBH|m;GqKE$|h7k`O+skyTq)o0DqknwZle^dBx zF_vf50S<#h``wv*@YDAgG*e#K6SPxDQsC`FQ{-QKmxkZ8q@x;)PY;Zj(A!t>RjYET z9$%Jg+IOZexovu0i#%Q$fl-CcE3T}pdmhz#cv`DP1?T2MEX`LHSlWIc|2ofL9GZb? zw=XbHG~TW?ffUN}Fq(Z1EY3HukWEGgvc(NIM$s1CUnPLi@6FMCf0~@pZ!;rZFzh=& zW{R;zCB4(vgUCP5C&N^=<`Hv}Ua6=u=dr|Qz&4%Tr!aSleZOXXbeLfc(H2lVEUZ1aQ)A_iBy{si zgL4eHupr`VRoNFDE<*$JbLSn4tYQ`Bu6KJ-erl4EGBoyc=8=S>(f9|&S;Bo|a%pMj z4&NxPuCn+;+>r;q6nF%T2a+?cSx`{>EWbY1z<4R-SmKNKc3mZG~|B zL!1SYg3iby>7B5Jg$kb99f_!xO)~3GGaF5_4~~z}8oF~1LP@V}!TSSn;f3LLv1i&{ z;;jrkbzBMT&S6GMfp!(}sHMV)gq)5)BJ*O1uylB4BtZ=QHkH8|2k^q?Z~|A@N*3i9 zJ6vC`ufwm?`;4?x%{+$3yEym51<94nP|3yx()qFz>Ay6X>kySA8{9Q^z?MqGBlM$X z47sp$z_-cJ!0jRddR?DhvBJWbPyERL2&88IyH_gwsGH5F)gG}wGOoSUW%`lZgjL$x zwd#a$v=TAHRjF%g(emgJ1BuA-=GG_C8%L+M0p)e)E|C>kHH=FJp|kBV4Y6jBGu#`wy`t~AaN8d9DMKB@cMplf zKhD*Bm6xt&9(&fhlPHD3zJc*0`6cLp>)|IV`o+bVqC0k!0)hb*xtw)?^&UZvT_u}W;rYy=~ti>Kx96bCBP^?seFn)s6KP1!j#NZh|U!z ZcsM&rvr4*~8s0?1TB`R?!uelM{|ix7sPF&) literal 0 HcmV?d00001