#+TITLE: *Iron Brush Tattoo* /Case Jewelry/ #+DATE: Tue May 3 10:45:24 CDT 2016 #+AUTHOR: AnderSon #+OPTIONS: tags:nil /Rails 4.2.6/ https://github.com/IronBrushTattoo/cj_rails.git [[../../Retail_Jewelry]] [[Config]] [[Views]] [[Labelsheets]] * Config ** Gemfile [[./Gemfile]] #+NAME: Gemfile #+begin_src ruby :tangle Gemfile :padline no source 'https://rubygems.org' ruby '2.3.1' gem 'rails', '4.2.6' gem 'dotenv-rails', :groups => [:development, :test], :require => 'dotenv/rails-now' gem 'pg', '~> 0.15' gem 'sass-rails', '~> 5.0' gem "pure-css-rails" gem 'uglifier', '>= 1.3.0' gem 'coffee-rails', '~> 4.1.0' gem 'jquery-rails' gem 'turbolinks' gem 'jquery-turbolinks' gem 'jbuilder', '~> 2.0' gem 'sdoc', '~> 0.4.0', group: :doc gem 'dragonfly', '~> 1.0.12' gem 'dragonfly-s3_data_store' gem 'rack-cache', :require => 'rack/cache' gem "memcachier" gem 'dalli' gem 'kgio' gem 'prawn' gem 'prawn-table', '~> 0.2.2' gem 'roo', '~> 2.3.2' gem 'roo-xls' gem 'chronic', '~> 0.10.2' gem 'omniauth', '~> 1.3.1' gem 'omniauth-auth0', '~> 1.4.1' # gem 'dotenv-rails', :require => 'dotenv/rails-now' group :development, :test do gem 'byebug' end group :development do gem 'web-console', '~> 2.0' gem 'spring' end group :production do gem 'rails_12factor' end #+end_src [[./app/assets/javascripts/application.js]] #+NAME: application.js #+begin_src js :tangle app/assets/javascripts/application.js :padline no // This is a manifest file that'll be compiled into application.js, which will include all the files // listed below. // // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. // // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. // // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. // //= require jquery //= require jquery.turbolinks //= require jquery_ujs //= require turbolinks //= require_tree . #+end_src ** Gems [[Dragonfly]] [[Prawn]] ** Application [[./config/application.rb]] #+NAME: application.rb #+begin_src ruby :tangle config/application.rb :padline no require File.expand_path('../boot', __FILE__) require 'rails/all' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) #Dotenv::Railtie.load HOSTNAME = ENV['HOSTNAME'] module CaseJewelryRails class Application < Rails::Application # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. # config.time_zone = 'Central Time (US & Canada)' # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # config.i18n.default_locale = :de # Do not swallow errors in after_commit/after_rollback callbacks. config.active_record.raise_in_transactional_callbacks = true config.cache_store = :dalli_store end end #+end_src ** Environments *** Development [[./config/environments/development.rb]] #+NAME: development.rb #+begin_src ruby :tangle config/environments/development.rb :padline no Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. config.cache_classes = false config.cachestore = :memorystore # Do not eager load code on boot. config.eager_load = false # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = true # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. config.assets.debug = true # Asset digests allow you to set far-future HTTP expiration dates on all assets, # yet still be able to expire them through the digest params. config.assets.digest = true # Adds additional error checking when serving assets at runtime. # Checks for improperly declared sprockets dependencies. # Raises helpful error messages. config.assets.raise_runtime_errors = true # Raises error for missing translations # config.action_view.raise_on_missing_translations = true # OmniAuth.config.on_failure = Proc.new { |env| # message_key = env['omniauth.error.type'] # error_description = Rack::Utils.escape(env['omniauth.error'].error_reason) # new_path = "#{env['SCRIPT_NAME']}#{OmniAuth.config.path_prefix}/failure?message=#{message_key}&error_description=#{error_description}" # Rack::Response.new(['302 Moved'], 302, 'Location' => new_path).finish # } end #+end_src *** Production [[./config/environments/production.rb]] #+NAME: ENV-PRODUCTION #+begin_src ruby :tangle config/environments/production.rb :padline no Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # Code is not reloaded between requests. config.cache_classes = true # Eager load code on boot. This eager loads most of Rails and # your application in memory, allowing both threaded web servers # and those relying on copy on write to perform better. # Rake tasks automatically ignore this option for performance. config.eager_load = true # Full error reports are disabled and caching is turned on. config.consider_all_requests_local = false config.action_controller.perform_caching = true # Enable Rack::Cache to put a simple HTTP cache in front of your application # Add `rack-cache` to your Gemfile before enabling this. # For large-scale production use, consider using a caching reverse proxy like # NGINX, varnish or squid. config.action_dispatch.rack_cache = true # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? config.serve_static_assets = true # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier # config.assets.css_compressor = :sass # Do not fallback to assets pipeline if a precompiled asset is missed. config.assets.compile = false # Asset digests allow you to set far-future HTTP expiration dates on all assets, # yet still be able to expire them through the digest params. config.assets.digest = true # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb # Specifies the header that your server uses for sending files. # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true # Use the lowest log level to ensure availability of diagnostic information # when problems arise. config.log_level = :debug # Prepend all log lines with the following tags. # config.log_tags = [ :subdomain, :uuid ] # Use a different logger for distributed setups. # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) # Use a different cache store in production. # config.cache_store = :mem_cache_store # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.action_controller.asset_host = 'http://assets.example.com' # Ignore bad email addresses and do not raise email delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation cannot be found). config.i18n.fallbacks = true # Send deprecation notices to registered listeners. config.active_support.deprecation = :notify # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false OmniAuth.config.on_failure = Proc.new { |env| message_key = env['omniauth.error.type'] error_description = Rack::Utils.escape(env['omniauth.error'].error_reason) new_path = "#{env['SCRIPT_NAME']}#{OmniAuth.config.path_prefix}/failure?message=#{message_key}&error_description=#{error_description}" Rack::Response.new(['302 Moved'], 302, 'Location' => new_path).finish } client = Dalli::Client.new((ENV["MEMCACHIER_SERVERS"] || "").split(","), :username => ENV["MEMCACHIER_USERNAME"], :password => ENV["MEMCACHIER_PASSWORD"], :failover => true, :socket_timeout => 1.5, :socket_failure_delay => 0.2, :value_max_bytes => 10485760) config.action_dispatch.rack_cache = { :metastore => client, :entitystore => client } config.static_cache_control = "public, max-age=2592000" end #+end_src : `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb [[./config/initializers/assets.rb]] #+NAME: assets.rb #+begin_src ruby :tangle config/initializers/assets.rb :padline no # Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. Rails.application.config.assets.version = '1.0' # Add additional assets to the asset load path # Rails.application.config.assets.paths << Emoji.images_path # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. Rails.application.config.assets.precompile += %w( home.js.erb ) #+end_src [[AuthO]] * First steps :rails_template:rails:rake: : rake db:migrate : rake db:setup * Project The purpose of this application is to produce several pdf files from an xlsx file, as a re-implementation of https://github.com/IronBrushTattoo/cj as a web application. ** User Story - user logs in ([[Authentication]]) - chooses xlsx file for upload [[File Upload]] - selects number of days back to make labels from - submits - BACKGROUND - cj-parser.rb does what it does... - [ ] rewrite in rails? - downloads sheets(pdf files) ** File Upload - possible gems https://www.ruby-toolbox.com/categories/rails_file_uploads - paperclip - nb - used paperclip before - seemed to be designed specifically for image files - always worked well - carrierwave - nb - used before, but not thoroughly - i kind of remember having issues with it - dragonfly https://github.com/markevans/dragonfly http://markevans.github.io/dragonfly/ http://markevans.github.io/dragonfly/rails/ Dragonfly is a highly customizable ruby gem for handling images and other attachments and is already in use on thousands of websites [[Dragonfly]] - nb - used briefly before - i remember it being an easy configuration - attachment fu https://github.com/technoweenie/attachment_fu Treat an ActiveRecord model as a file attachment, storing its patch, size, content type, etc. http://weblog.technoweenie.net - nb - has not been maintained since Apr 25, 2009 - refile - nb - was my next choice when previously working with file uploads - jquery.fileupload-rails - imagery - attached - papermill - fileuploader-rails - filecip - simple-image-uploader *** Dragonfly http://markevans.github.io/dragonfly/rails/ **** Setup - [X] gem 'dragonfly', '~> 1.0.12' - [X] modify [[Gemfile]] - [X] bundle install - [X] rails g dragonfly generates config/initializers/dragonfly.rb [[./config/initializers/dragonfly.rb]] #+NAME: dragonfly initializer #+begin_src ruby :tangle config/initializers/dragonfly.rb :padline no require 'dragonfly' # Configure Dragonfly.app.configure do plugin :imagemagick secret "<%= Rails.application.secrets.dragonfly_secret %>" url_format "/media/:job/:name" if Rails.env.development? || Rails.env.test? datastore :file, root_path: Rails.root.join('public/system/dragonfly', Rails.env), server_root: Rails.root.join('public') else datastore :s3, bucket_name: ENV['AWS_BUCKET'], access_key_id: ENV['AWS_ACCESS_KEY_ID'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], region: ENV['AWS_REGION'] #url_scheme: 'https' end # Logger Dragonfly.logger = Rails.logger # Mount as middleware Rails.application.middleware.use Dragonfly::Middleware # Add model functionality if defined?(ActiveRecord::Base) ActiveRecord::Base.extend Dragonfly::Model ActiveRecord::Base.extend Dragonfly::Model::Validations end end #+end_src - [X] MOVE SECRET to ENV - [-] Production - [-] AWS S3 Data Store https://github.com/markevans/dragonfly-s3_data_store - [X] [[Gemfile]] : gem 'dragonfly-s3_data_store' - [ ] [[./config/initializers/dragonfly.rb]] : Dragonfly.app.configure do : : datastore :s3, : bucket_name: 'my-bucket' : access_key_id: 'blahblahblah', : secret_access_key: 'blublublublu' : region: 'us-west-1' or whatever... : end - [ ] need region? **** Handling attachments - Labelsheet model Model: /Labelsheet/ [[Labelsheet]] [[./db/migrate]] - [-] create Labelsheet : rails g scaffold Labelsheet days:integer file_uid:string file_name:string : rake db:migrate - [-] check for coffee and scaffold files - [X] coffee - [X] rm - [X] scaffold.scss - [X] rm - [ ] look into scaffold configuration - [X] add /file/ attribute to Labelsheet [[Labelsheet]] [[./app/models/labelsheet.rb]] : class Labelsheet < ActiveRecord::Base : dragonfly_accessor :file # defines a reader/writer for file : # ... : end - [X] update [[Routes]] : resources :labelsheets : get "labelsheets" => "labelsheets#new" - [ ] update [[Auth0]] for Labelsheet references - [X] view for uploading [[Views]] [[./app/views/labelsheets/_form.html.erb]] : <% form_for @labelsheet do |f| %> : ... : <%= f.file_field :file %> : ... : <% end %> - [X] Remodel SpreadsheetPdf to LabelsheetPdf [[LabelsheetPdf]] - [X] allow parameter /file/ to be accepted by the controller [[./app/controllers/labelsheets_controller.rb]] [[Labelsheets]] - nb [[Prawn]] [[Creating PDF Using Prawn in Ruby on Rails]] - [X] view for displaying [[Views]] [[./app/views/labelsheets/show.html.erb]] [[./app/views/labelsheets/index.html.erb]] : <%= @labelsheet.file_name if @labelsheet.file_stored? %> - more can be done with [[http://markevans.github.io/dragonfly/models][models]] **** Caching - [X] [[Gemfile]] : gem 'rack-cache', :require => 'rack/cache' - [X] bundle install - [X] uncomment in [[Production]] : config.action_dispatch.rack_cache = true **** Custom Endpoints [[Routes]] - [ ] text generation example : get "text/:text" => Dragonfly.app.endpoint { |params, app| : app.generate(:text, params[:text], 'font-size' => 42) : } - [ ] endpoint callable from javascript (e.g. /image?file=egg.png&size=30x30) : get "image" => Dragonfly.app.endpoint { |params, app| : app.fetch_file("some/dir/#{params[:file]}").thumb(params[:size]) : } **** Using Another Data Store http://www.sitepoint.com/file-uploads-dragonfly/ - [ ] add [[./public/system/dragonfly]] to [[./.gitignore]] #+NAME: gitignore #+begin_src text :tangle .gitignore :padline no # See https://help.github.com/articles/ignoring-files for more about ignoring files. # # If you find yourself ignoring temporary files generated by your text editor # or operating system, you probably want to add a global ignore instead: # git config --global core.excludesfile '~/.gitignore_global' # Ignore bundler config. /.bundle # Ignore all logfiles and tempfiles. /log/* !/log/.keep /tmp /public/system/dragonfly #+end_src **** DEPRECATIONS :noexport: - example (replace Photo model with Spreadsheet) Model: /Photo/ - Sun May 8 11:00:11 CDT 2016 REMODELING Spreadsheet into Labelsheet - add /image/ attribute to Photo : class Photo < ActiveRecord::Base : dragonfly_accessor :image # defines a reader/writer for image : # ... : end - needs /image_uid/ column, create migration with : rails g migration : add_column :photos, :image_uid, :string : add_column :photos, :image_name, :string # Optional - if you want : # urls to end with the : # original filename - view for uploading : app/views/photos/... : <% form_for @photo do |f| %> : ... : <%= f.file_field :image %> : ... : <% end %> - allow parameter /image/ to be accepted by the controller : app/controllers/photos_controller.rb : params.require(:photo).permit(:image) - view for displaying : <%= image_tag @photo.image.thumb('400x200#').url if @photo.image_stored? %> - more can be done with [[http://markevans.github.io/dragonfly/models][models]] - DEPRECATED::REMODEL::Labelsheet = Spreadsheet model sketch based on above example Model: /Spreadsheet/ [[Spreadsheet]] - [X] add /file/ attribute to Spreadsheet : class Spreadsheet < ActiveRecord::Base : dragonfly_accessor :file # defines a reader/writer for file : # ... : end - [X] needs /file_uid/ column, create migration with : rails g migration AddFileUidToSpreadsheets file_uid:string : rails g migration AddFileNameToSpreadsheets file_name:string [[./db/migrate/20160504011342_add_file_uid_to_spreadsheets.rb]] [[./db/migrate/20160504011542_add_file_name_to_spreadsheets.rb]] : add_column :spreadsheets, :file_uid, :string : add_column :spreadsheets, :file_name, :string # Optional - if you want : # urls to end with the : # original filename : rake db:migrate - [X] view for uploading [[./app/views/spreadsheets/]] : <% form_for @spreadsheet do |f| %> : ... : <%= f.file_field :file %> : ... : <% end %> - [X] allow parameter /file/ to be accepted by the controller [[./app/controllers/spreadsheets_controller.rb]] : params.require(:spreadsheet).permit(:file) [[SpreadsheetPdf]] #+NAME: DEPRECATED spreadsheets controller #+begin_src ruby class SpreadsheetsController < SecuredController before_action :set_spreadsheet, only: [:show, :edit, :update, :destroy] before_action :logged_in_using_omniauth?, only: [:new, :edit, :update, :destroy] def index @spreadsheets = Spreadsheet.all end def show @spreadsheet = Spreadsheet.find(params[:id]) respond_to do |format| format.html format.pdf do pdf = SpreadsheetPdf.new(@spreadsheet, view_context) send_data pdf.render, filename: "spreadsheet_#{@spreadsheet.created_at.strftime("%d/%m/%Y")}.pdf", type: "application/pdf", disposition: "inline" end end end def new @spreadsheet = Spreadsheet.new end def edit end def create @spreadsheet = Spreadsheet.new(spreadsheet_params) respond_to do |format| if @spreadsheet.save format.html { redirect_to @spreadsheet, notice: 'Spreadsheet was successfully created.' } format.json { render :show, status: :created, location: @spreadsheet } else format.html { render :new } format.json { render json: @spreadsheet.errors, status: :unprocessable_entity } end end end def update respond_to do |format| if @spreadsheet.update(spreadsheet_params) format.html { redirect_to @spreadsheet, notice: 'Spreadsheet was successfully updated.' } format.json { render :show, status: :ok, location: @spreadsheet } else format.html { render :edit } format.json { render json: @spreadsheet.errors, status: :unprocessable_entity } end end end def destroy @spreadsheet.destroy respond_to do |format| format.html { redirect_to spreadsheets_url, notice: 'Spreadsheet was successfully destroyed.' } format.json { head :no_content } end end private def set_spreadsheet @spreadsheet = Spreadsheet.find(params[:id]) end def spreadsheet_params params.require(:spreadsheet).permit(:index, :file, :days) end end #+end_src - nb [[Prawn]] [[Creating PDF Using Prawn in Ruby on Rails]] - [X] view for displaying [[./app/views/spreadsheets/show.html.erb]] [[./app/views/spreadsheets/index.html.erb]] : <%= @spreadsheet.file_name if @spreadsheet.file_stored? %> ** File Conversion *** xlsx processing **** Roo https://github.com/roo-rb/roo https://github.com/roo-rb/roo-xls - [X] [[Gemfile]] : gem 'roo', '~> 2.3.2' : gem 'roo-xls' - [X] bundle install - [ ] examine code from native application [[~/IBT/jewelry/Retail_Jewelry/cj-parser.rb]] #+NAME: cj-parser-scratch #+begin_src text : require 'roo' : : def get_labels(file) : puts "getting labels" : : labels = [] : : xls_file = Roo::Spreadsheet.open(file) : : xls_file.sheets.each do |sheet| : : sheet = xls_file.sheet(sheet) : : sheet.parse[4..-1].each do |row| : : zero,one,two,four,five,ten = nil_convert(row[0]), : nil_convert(row[1]), : nil_convert(row[2]), : nil_convert(row[4]), : nil_convert(row[5]), : nil_convert(row[10]) : : sizes = strip(five.to_s) : gauge = "#{sizes[0]}g" : size = "#{sizes[1]}\"" : desc = two.gsub("&", "and") : id = one.to_s.split(/-/)[0] : price = "$#{four.to_s.split(".")[0]}" : supply = five : updated = Chronic.parse(ten).to_f : : label = Label.new(gauge, : size, : desc, : id, : price, : supply, : updated : ) : : seconds = 60*60*24*$days : : if (Time.now.to_f - updated.to_f) < seconds : puts label.id : $labelID = label.id : labels.push label : end : : end : end : : return labels : : end #+end_src *** pdf processing **** Prawn https://github.com/prawnpdf/prawn ***** Setup - [X] [[Gemfile]] : #gem 'prawn', '~> 2.1' : gem 'prawn' - [X] bundle install ****** Manual http://prawnpdf.org/manual.pdf - [X] clone repository : git clone https://github.com/prawnpdf/prawn - [ ] switch to the stable branch : git branch stable - [X] bundle install - [ ] bundle exec rake manual generates /manual.pdf/ in the project root ***** Tutorials ****** Creating PDF Using Prawn in Ruby on Rails http://www.idyllic-software.com/blog/creating-pdf-using-prawn-in-ruby-on-rails/ - [X] [[Gemfile]] : gem 'prawn' : bundle install - [X] [[./config/initializers/mime_types.rb]] create a PDF Mime::Type inside mime_types.rb #+NAME: mime_types.rb #+begin_src ruby :tangle config/initializers/mime_types.rb # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: # Mime::Type.register "text/richtext", :rtf # Mime::Type.register "application/pdf", :pdf #+end_src - [X] [[./app/controllers/spreadsheets_controller.rb]] [[Spreadsheets]] http://www.idyllic-software.com/blog/creating-pdf-using-prawn-in-ruby-on-rails/ : class InvoicesController < ApplicationController : : before_filter :authenticate_customer!, :only => [:index, :show] : : def index : @invoices = Invoice.all_invoices(current_customer) : end : : def show : @invoice = Invoice.find(params[:id]) : respond_to do |format| : format.html : format.pdf do : pdf = InvoicePdf.new(@invoice, view_context) : send_data pdf.render, filename: : "invoice_#{@invoice.created_at.strftime("%d/%m/%Y")}.pdf", : type: "application/pdf" : end : end : end : : end - [X] open pdf in browser instead of download add /disposition: "inline"/ after type - [X] create a new class *app/pdfs/spreadsheet_pdf* [[SpreadsheetPdf]] [[Spreadsheets]] - [X] restart server - [X] [[SpreadsheetPdf]] set the /@spreadsheet/ and /view_context/ : def initialize(spreadsheet, view) : super() : @spreadsheet = spreadsheet : @view = view : text "Spreadsheet #{@spreadsheet.id}" : end - [ ] create different methods inside [[SpreadsheetPdf]] as per what you want to show on the pdf - example : def logo : logopath = "#{Rails.root}/app/assets/images/logo.png" : image logopath, :width => 197, :height => 91 : end ******* Issues - [ ] NameError (uninitialized constant SpreadsheetsController::SpreadsheetPdf) **** nb https://rubygems.org/search?utf8=%E2%9C%93&query=latex http://www.sitepoint.com/hackable-pdf-typesetting-in-ruby-with-prawn/ https://github.com/prawnpdf/prawn [[Prawn]] is active and looks rad! - outdated but possibly useful https://github.com/baierjan/rails-latex https://github.com/bruce/rtex ** Authentication :BLOG:troubleshooting:rails:dotenv:load_order:issues: *** AuthO https://manage.auth0.com/#/ https://manage.auth0.com/#/applications/eD2I5SEBmvgx3tEzeFd35mJfvW5HkasK/quickstart - [X] 1. Add dependencies [[Gemfile]] : gem 'omniauth', '~> 1.3.1' : gem 'omniauth-auth0', '~> 1.4.1' - [X] bundle install - [X] 2. Initialize Omniauth AuthO [[./config/initializers/auth0.rb]] #+NAME: auth0.rb #+begin_src ruby :tangle config/initializers/auth0.rb :padline no Rails.application.config.middleware.use OmniAuth::Builder do provider( :auth0, ENV["AUTH0_CLIENT_ID"], ENV["AUTH0_CLIENT_SECRET"], ENV["AUTH0_DOMAIN"], callback_path: "/auth/auth0/callback" ) end #+end_src - [X] add to gitignore? [[./.gitignore]] - [X] dotenv https://github.com/bkeepers/dotenv [[Gemfile]] : gem 'dotenv-rails', :groups => [:development, :test] - # Note on load order dotenv is intialized in your Rails app during the /befor_configuration/ callback, which is fired when the /Application/ constant is defined in /config/application.rb/ with /class Application < Rails::Application/. If you need it to be initialized sooner, you can manually call /Dotenv::Railtie.load/. NB: This resolved an issue I had with the correct environment variables being loaded in a js.erb file... (BLOG THIS!) [[application.rb]] : # config/application.rb : Bundler.require(*Rails.groups) : : Dotenv::Railtie.load : : HOSTNAME = ENV['HOSTNAME'] If you use gems that require environment variables to be set before they are loaded, then list /dotenv-rails/ in the /Gemfile/ before those other gems and require /dotenv/rails-now/. [[Gemfile]] : gem 'dotenv-rails', :require => 'dotenv/rails-now' : gem 'gem-that-requires-env-variables' - [ ] PRODUCTION ISSUE : /app/config/application.rb uninitialized constant Dotenv (NameError) : /app/config/application.rb:9 in `': uninitialized constant Dotenv (NameError) [[application.rb]] - [ ] dotenv gem is in development and test groups - [ ] remove Dotenv refrence from application.rb? - [X] 3. Add the AuthO callback handler : rails g controller auth0 callback failure --skip-template-engine --skip-assets [[./app/controllers/auth0_controller.rb]] #+NAME: auth0_controller.rb #+begin_src ruby :tangle app/controllers/auth0_controller.rb :padline no class Auth0Controller < ApplicationController def callback # This stores all the user information that came from Auth0 and the IdP session[:userinfo] = request.env['omniauth.auth'] # Redirect to the URL you want after successful auth redirect_to '/labelsheets/new' end def failure # show a failure page or redirect to an error page @error_msg = request.params['message'] end end #+end_src - [X] replace the generated routes in [[./config/routes.rb]] [[Routes]] : get "/auth/auth0/callback" => "auth0#callback" : get "/auth/failure" => "auth0#failure" - [X] 4. Specify the callback on AuthO Dashboard For security purposes, register callback URL of the application at https://manage.auth0.com/#/applications : http://yourUrl/auth/auth0/callback - [-] 5. Triggering login manually or integrating the AuthOLock - [ ] modal all (see auth0 dashboard apps quickstart) - [X] passwordless - Email Code [[./app/assets/javascripts/home.js.erb]] #+NAME: HOMEJS #+begin_src js :tangle app/assets/javascripts/home.js.erb :padline no /*var lock = new Auth0Lock("<%= Rails.application.secrets.auth0_client_id %>", "<%= Rails.application.secrets.auth0_domain %>"); var callback = "<%= Rails.application.secrets.auth0_callback_url %>"; function signin() { lock.show({ callbackURL: "<%= Rails.application.secrets.auth0_callback_url %>", //callbackURL: callback, responseType: 'code', authParams: { scope: 'openid name email picture' } }); }*/ // temporarily moving code to view level #+end_src [[./config/secrets.yml]] #+NAME: secrets.yml #+begin_src yaml :tangle config/secrets.yml :padline no # Be sure to restart your server when you modify this file. # Your secret key is used for verifying the integrity of signed cookies. # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. # You can use `rake secret` to generate a secure secret key. # Make sure the secrets in this file are kept private # if you're sharing your code publicly. development: secret_key_base: bea023fad0c0803893cde72b419aa08fc9d7456bedeaf9b5490c4c2ef34de64bd1eee9ca4583a19f5f206a36b750bd41a85dcf95567718099ae827ee1d1fcc18 auth0_client_id: <%= ENV["AUTH0_CLIENT_ID"] %> auth0_client_secret: <%= ENV["AUTH0_CLIENT_SECRET"] %> auth0_domain: <%= ENV["AUTH0_DOMAIN"] %> auth0_callback_url: <%= ENV["AUTH0_CALLBACK_URL"] %> test: secret_key_base: 932c75a9b0d799c43e825634b7c2a94fc48ca57bc02db62353a6a51211f9818c4b84105cb15e815de487c59106cc25982c31f95238fd184af8a97003a55c08b4 auth0_client_id: <%= ENV["AUTH0_CLIENT_ID"] %> auth0_client_secret: <%= ENV["AUTH0_CLIENT_SECRET"] %> auth0_domain: <%= ENV["AUTH0_DOMAIN"] %> auth0_callback_url: <%= ENV["AUTH0_CALLBACK_URL"] %> # Do not keep production secrets in the repository, # instead read values from the environment. production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> auth0_client_id: <%= ENV["AUTH0_CLIENT_ID"] %> auth0_client_secret: <%= ENV["AUTH0_CLIENT_SECRET"] %> auth0_domain: <%= ENV["AUTH0_DOMAIN"] %> auth0_callback_url: <%= ENV["AUTH0_CALLBACK_URL"] %> #+end_src update [[Routes]] - [ ] 6. Accessing user information [[./app/controllers/secured_controller.rb]] #+NAME: secured controller #+begin_src ruby :tangle app/controllers/secured_controller.rb :padline no class SecuredController < ApplicationController before_action :logged_in_using_omniauth? private def logged_in_using_omniauth? unless session[:userinfo].present? redirect_to '/' end end end #+end_src via /userinfo/ stored in the session on step 3 : class DashboardController < SecuredController : def show : @user = session[:userinfo] : end : end :
: :

Welcom <%= @user[:info][:name] %>

:
[[./config/initializers/session_store.rb]] #+NAME: session_store.rb #+begin_src ruby :tangle config/initializers/session_store.rb :padline no # Be sure to restart your server when you modify this file. #Rails.application.config.session_store :cookie_store, key: '_CaseJewelryRails_session' Rails.application.config.session_store :cache_store #+end_src [[./config/environments/development.rb]] : config.cachestore = :memorystore [[./app/views/dashboard/show.html.erb]] #+NAME: dashboard show view #+begin_src html :tangle app/views/dashboard/show.html.erb :padline no
#+end_src [[./app/views/home/show.html.erb]] #+NAME: home show view #+begin_src html :tangle app/views/home/show.html.erb :padline no
#+end_src [[Dashboard]] [[Pages]] - [ ] add rules https://manage.auth0.com/#/rules - [ ] allow only piercing@ironbrush.com google auth - [ ] include ande, tony, ethan, and tyson @ironbrush.com - [ ] if logged_in? - [ ] how to check user session - [ ] Troubleshooting - [ ] "We're sorry, we can't send you the email... [[https://www.google.com/search?q=auth0+in+development&oq=auth0+in+development&aqs=chrome..69i57.6898j0j7&sourceid=chrome&es_sm=122&ie=UTF-8][auth0 in development]] https://auth0.com/docs/lifecycle https://auth0.com/docs/local-testing-and-development If you need to develop an application locally, it's possible to use localhost or other domains which Auth0 cannot access (e.g. intranets) as callback URLs. Since Auth0 uses OpenID Connect as its main identity protocol, it never makes a call directly to your application's server. Instead, it redirects users in a browser to an endpoint of your application (which must be listed in the "Allowed Callback URLs" list) with specific information in the query string or hash fragment, depending on the type of application. https://auth0.com/docs/protocols [[~/IBT/jewelry/rails/docs/omniauth-auth0-sample/]] - [ ] get error description on failure [[./config/environments/production.rb]] : OmniAuth.config.on_failure = Proc.new { |env| : message_key = env['omniauth.error.type'] : error_description = Rack::Utils.escape(env['omniauth.error'].error_reason) : new_path = "#{env['SCRIPT_NAME']}#{OmniAuth.config.path_prefix}/failure?message=#{message_key}&error_description=#{error_description}" : Rack::Response.new(['302 Moved'], 302, 'Location' => new_path).finish : } [[Config]] [[Environments]] [[Production]] *** nb - oauth? - login with familiar accounts - google, fb, twitter, etc ** Views *** Routes [[./config/routes.rb]] #+NAME: routes.rb #+begin_src ruby :tangle config/routes.rb :padline no Rails.application.routes.draw do resources :labelsheets, :except => [:show] resources :labelsheets, :only => [:show], :defaults => { :format => 'pdf' } get "labelsheets" => "labelsheets#new" get "labelsheets/:id", to: "labelsheets#show", defaults: { format: 'pdf' } constraints format: 'pdf' do resources :labelsheets, only: [:show] end get 'dashboard/show' get "/" => "home#show" get "/dashboard" => "dashboard#show" get "/callback" => "auth0#callback" get "/auth/auth0/callback" => "auth0#callback" get "/auth/failure" => "auth0#failure" end #+end_src [[Pages]] [[AuthO]] [[Custom Endpoints]] *** Static Pages : root 'pages#home' [[Pages]] **** Home [[./app/views/pages/home.html.erb]] *** Labelsheets [[./app/views/labelsheets/]] **** New [[./app/views/labelsheets/new.html.erb]] #+NAME: LabelsheetNew #+begin_src web :tangle app/views/labelsheets/new.html.erb :padline no <%= render 'form' %>
<%#= link_to 'Sheets', labelsheets_path, class: 'pure-button pure-button-primary' %> #+end_src **** Form [[./app/views/labelsheets/_form.html.erb]] #+NAME: labelsheets/_form.html.erb #+begin_src html :tangle app/views/labelsheets/_form.html.erb :padline no <%= form_for(@labelsheet, :html => {:target => '_blank'}) do |f| %> <% if @labelsheet.errors.any? %>

<%= pluralize(@labelsheet.errors.count, "error") %> prohibited this labelsheet from being saved:

<% end %>
<%= f.file_field :file %>

<%= f.number_field :days %> <%= f.label "Number of Days" %>

<%= f.submit 'Make Sheet', class: 'pure-button pure-button-primary' %>
<% end %> #+end_src **** Show [[./app/views/labelsheets/show.html.erb]] #+NAME: labelsheets/show.html.erb #+begin_src html :tangle app/views/labelsheets/show.html.erb :padline no

<%= notice %>

Index: <%= @labelsheet.file_name if @labelsheet.file_stored? %> <%= link_to 'PDF', "#{@labelsheet.id}.pdf" %>

<%= link_to 'Edit', edit_labelsheet_path(@labelsheet) %> | <%= link_to 'Back', labelsheets_path %> #+end_src **** Index [[application.html.erb]] [[./app/views/labelsheets/index.html.erb]] #+NAME: labelsheets/index.html.erb #+begin_src html :tangle app/views/labelsheets/index.html.erb :padline no

<%= notice %>

Listing Labelsheets

<% @labelsheets.each do |labelsheet| %> <% end %>
Index
<%= link_to 'Show', labelsheet %> <%= link_to 'Edit', edit_labelsheet_path(labelsheet) %> <%= link_to 'Destroy', labelsheet, method: :delete, data: { confirm: 'Are you sure?' } %>

<%= link_to 'New Labelsheet', new_labelsheet_path %> #+end_src *** Layouts [[application.html.erb]] #+NAME: application.html.erb #+begin_src web :tangle app/views/layouts/application.html.erb :padline no CaseJewelryRails <%= yield :cdn_code %> <%= stylesheet_link_tag '//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css' %> <%= stylesheet_link_tag '//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css' %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag '//cdn.auth0.com/js/lock-9.1.min.js' %> <%#= javascript_include_tag '//use.typekit.net/iws6ohy.js' %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> <%= render 'layouts/header' %>
<%= yield %>
#+end_src [[./app/views/layouts/_header.html.erb]] #+NAME: _header.html.erb #+begin_src web :tangle app/views/layouts/_header.html.erb :padline no
<%= image_tag 'logo.png', class: 'pure-img' %>

Case Jewelry Labeler

#+end_src *** Styles [[./app/assets/stylesheets/application.css.scss]] #+NAME: application.css.scss #+begin_src css :tangle app/assets/stylesheets/application.css.scss :padline no /* ,* This is a manifest file that'll be compiled into application.css, which will include all the files ,* listed below. ,* ,* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, ,* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. ,* ,* You're free to add application-wide styles to this file and they'll appear at the bottom of the ,* compiled file so the styles you add here take precedence over styles defined in any styles ,* defined in the other CSS/SCSS files in this directory. It is generally better to create a new ,* file per style scope. ,* ,*= require_tree . ,*= require_self ,*/ //= require pure //= require grids-responsive #+end_src **** Pure CSS https://github.com/bkutil/pure-css-rails [[Gemfile]] : gem "pure-css-rails" [[application.css.scss]] : //= require pure : //= require grids-responsive [[application.html.erb]] : ** Controllers *** Pages Static pages controller #+begin_src sh rails g controller pages --skip-assets #+end_src [[./app/controllers/pages_controller.rb]] #+NAME: pages_controller #+begin_src ruby :tangle app/controllers/pages_controller.rb class PagesController < ApplicationController end #+end_src - nb [[AuthO]] *** Dashboard : rails g controller Dashboard show [[./app/controllers/dashboard_controller.rb]] #+NAME: dashboard_controller #+begin_src ruby :tangle app/controllers/dashboard_controller.rb :padline no class DashboardController < SecuredController def show @user = session[:userinfo] end end #+end_src *** Labelsheets [[./app/controllers/labelsheets_controller.rb]] #+NAME: labelsheets controller #+begin_src ruby :tangle app/controllers/labelsheets_controller.rb :padline no class LabelsheetsController < SecuredController before_action :set_labelsheet, only: [:show, :edit, :update, :destroy] before_action :logged_in_using_omniauth?, only: [:new, :edit, :update, :destroy] def index @labelsheets = Labelsheet.all end def show @labelsheet = Labelsheet.find(params[:id]) respond_to do |format| format.html format.pdf do pdf = LabelsheetPdf.new(@labelsheet, view_context) send_data pdf.render, filename: "labelsheet_#{@labelsheet.created_at.strftime("%d/%m/%Y")}.pdf", type: "application/pdf", disposition: "inline" end end end def new @labelsheet = Labelsheet.new end def edit end def create @labelsheet = Labelsheet.new(labelsheet_params) respond_to do |format| if @labelsheet.save format.pdf { render :pdf => "show" } format.html { redirect_to @labelsheet, notice: 'Labelsheet was successfully created.' } format.json { render :show, status: :created, location: @labelsheet } else format.html { render :new } format.json { render json: @labelsheet.errors, status: :unprocessable_entity } end end end def update respond_to do |format| if @labelsheet.update(labelsheet_params) format.html { redirect_to @labelsheet, notice: 'Labelsheet was successfully updated.' } format.json { render :show, status: :ok, location: @labelsheet } else format.html { render :edit } format.json { render json: @labelsheet.errors, status: :unprocessable_entity } end end end def destroy @labelsheet.destroy respond_to do |format| format.html { redirect_to labelsheets_url, notice: 'Labelsheet was successfully destroyed.' } format.json { head :no_content } end end private def set_labelsheet @labelsheet = Labelsheet.find(params[:id]) end def labelsheet_params params.require(:labelsheet).permit(:index, :file, :days) end end #+end_src - [ ] redirect to pdf after creation - [ ] submit button open in new window [[./app/views/labelsheets/_form.html.erb]] [[Form]] ** Models [[Routes]] *** Page *** REMODEL::Labelsheet = Spreadsheet :noexport: [[./app/models/spreadsheet.rb]] #+NAME: DEPRECATED spreadsheet.rb #+begin_src ruby class Spreadsheet < ActiveRecord::Base dragonfly_accessor :file # defines a reader/writer for file end #+end_src - [ ] DEPRECATION - [ ] rm spreadsheet model *** Labelsheet Model [[./app/models/labelsheet.rb]] #+NAME: labelsheet.rb #+begin_src ruby :tangle app/models/labelsheet.rb :padline no class Labelsheet < ActiveRecord::Base dragonfly_accessor :file end #+end_src *** Label ** Classes *** LabelsheetPdf [[./app/pdfs/labelsheet_pdf.rb]] nb: possibly break this chunker down into other modules, classes, helpers, etc #+NAME: LabelsheetPdf #+begin_src ruby :tangle app/pdfs/labelsheet_pdf.rb :padline no class LabelsheetPdf < Prawn::Document def initialize(labelsheet, view) super() @labelsheet = labelsheet if Rails.env.development? || Rails.env.test? file_path = "public/system/dragonfly/development/#{@labelsheet.file_uid}" else file_path = Dragonfly.app.remote_url_for(@labelsheet.file_uid) end xls_file = get_labels(file_path) @view = view make_labels(xls_file) end def desc_box(desc) formatted_text_box [ { text: "#{desc}", color: "ffffff", styles: [:italic], size: 11 } ], at: [$padding,$top], width: $text_width end def size_box(gauge,size) #transparent(0.1) do # stroke_rectangle [0, $box_height+$padding], $box_width, $box_height*0.75 #end transparent(0.6) do formatted_text_box [ { text: "#{gauge} #{size}", color: "ffffff", size: 15, styles: [:normal], character_spacing: 0.5 } ], at: [($box_width/2)-$padding,$mid], width: $text_width end end def id_box(id) formatted_text_box [ { text: "#{id}", color: "ffffff", align: :left } ], at: [$padding,$low], width: $text_width end def price_box(price) formatted_text_box [ { text: "#{price}", color: "ffffff", align: :right, styles: [:italic] } ], at: [$box_width-($padding*3),$low], width: $text_width end def make_labels(file) define_grid(:columns => 4, :rows => 8, :row_gutter => 10, :column_gutter => 0) margin = 14 count = 1 row = 0 column = 0 start_new_page(:margin => margin) file.each do |label| grid(row, column).bounding_box do #stroke_axis fill_color "000000" stroke_color "ffffff" $box_width = 144 $box_height = 81 $padding = 12 $text_width = 90 $top = $box_height-$padding $mid = $top - 30 $low = $mid - 20 transparent(0.9) do fill_rectangle [0, $box_height], $box_width, $box_height font "Times-Roman", :size => 10 desc_box(label.desc) size_box(label.gauge, label.size) id_box(label.id) price_box(label.price) end end if count%4 == 0 row+=1 column = 0 else column+=1 end if count%32 == 0 start_new_page(:margin => margin) row = 0 column = 0 end count+=1 end end def logo logopath = "#{Rails.root}/app/assets/images/logo.png" image logopath, :width => 197, :height => 197 end def get_labels(file) labels = [] xls_file = Roo::Spreadsheet.open(file, extension: :xls) xls_file.sheets.each do |sheet| sheet = xls_file.sheet(sheet) #sheet.parse[0..-1].each do |row| sheet.each do |row| # sheet.each( # sizes: 'Size', # desc: 'Description', # id: 'Product ID', # price: 'Retail', # updated: 'Last Edit Date') do |row| #sheet.parse.each do |row| #sheet.parse( header_search: [/Size/,/Description/,/Product ID/,/Retail/,/Last Edit Date/], # sheet.parse(header_search: [/Size/,/Description/,/Product ID/,/Retail/,/Last Edit Date/]).each( # sizes: 'Size', # desc: 'Description', # id: 'Product ID', # price: 'Retail', # updated: 'Last Edit Date' # ) do |row| #).each do |row| id, desc, price, sizes, updated = row[6], row[2], row[3], row[4], row[12] sizes = strip(nil_convert(sizes).to_s) gauge = "#{sizes[0]}g" unless sizes[0].nil? # : "" size = "#{sizes[1]}\"" unless sizes[1].nil? desc = nil_convert(desc).gsub("&", "and") id = nil_convert(id).to_s.split(/-/)[0] price = "$#{nil_convert(price).to_s.split(".")[0]}" updated = Chronic.parse(nil_convert(updated)).to_f label = Label.new(gauge, size, desc, id, price, updated ) seconds = 60*60*24*@labelsheet.days.to_f if (Time.now.to_f - updated.to_f) < seconds #puts label.id $labelID = label.id labels.push label end end end return labels end def nil_convert(c) if c.nil? "" else c end end def strip(s) s.gsub(/"/, ''). gsub(/g/, ''). gsub(/G/, ''). gsub(/,/, ''). split(' ') end end #+end_src - [X] change file for amazon aws s3 path : file_path = "public/system/dragonfly/development" to : if Rails.env.development? || Rails.env.test? : file_path = "public/system/dragonfly/development/#{@labelsheet.file_uid}" : else : file_path = Dragonfly.app.remote_url_for(@labelsheet.file_uid) : end : : xls_file = get_labels(file_path) - nb [[Prawn]] [[Labelsheets]] *** Label [[./app/pdfs/label.rb]] #+NAME: Label #+begin_src ruby :tangle app/pdfs/label.rb :padline no class Label def initialize(gauge, size, desc, id, price, updated) @gauge = gauge @size = size @desc = desc @id = id @price = price @updated = updated end attr_reader :gauge, :size, :desc, :id, :price, :supply, :updated end #+end_src ** DEPRECATIONS http://stackoverflow.com/questions/30470333/remove-tables-from-schema [[./db/migrate]] : bundle exec rails g migration remove_spreadsheets : def up : drop_table :spreadsheets : end : rake db:migrate ** TODO - [ ] user authentication - [ ] narrow users field - [ ] production - [ ] [[Heroku]] - [ ] fork to alpha * Production ** Heroku https://onemonth.com/courses/one-month-rails/steps/going-online-with-heroku : heroku keys:add : heroku create [[Gemfile]] : gem 'rails_12factor' : bundle install --without production : git add * : git commit -m "..." : git push heroku master : heroku run rake db:migrate : heroku config:set SECRET_KEY_BASE=$(rake secret) - [ ] rack cache https://devcenter.heroku.com/articles/rack-cache-memcached-rails31 - [ ] install memcached - [ ] [[Gemfile]] : gem 'rack-cache' : gem 'dalli' : gem 'kgio' - [ ] [[./config/application.rb]] [[Config]] [[Application]] : config.cache_store = :dalli_store - [ ] configure Rack::Cache - [ ] [[./config/environments/production.rb]] [[Production]] : client = Dalli::Client.new((ENV["MEMCACHIER_SERVERS"] || "").split(","), : :username => ENV["MEMCACHIER_USERNAME"], : :password => ENV["MEMCACHIER_PASSWORD"], : :failover => true, : :socket_timeout => 1.5, : :socket_failure_delay => 0.2, : :value_max_bytes => 10485760) : config.action_dispatch.rack_cache = { : :metastore => client, : :entitystore => client : } : config.static_cache_control = "public, max-age=2592000" - [ ] Serve static assets [[./config/environments/production.rb]] [[Production]] : config.serve_static_assets = true : config.assets.digest = true : config.action_controller.perform_caching = true : heroku addons:create memcachier:dev [[Gemfile]] : gem "memcachier" - [ ] caching in production : git push heroku master : heroku logs --ps web -t - [ ] auth0 https://elements.heroku.com/addons/auth0 : heroku addons:create auth0:free --subdomain=sonarch : heroku addons:remove auth0 && heroku addons:add auth0 --subdomain= - [ ] setup local env : heroku config -s | grep 'AUTH0_CLIENT_ID\|AUTH0_CLIENT_SECRET\|AUTH0_DOMAIN' | tee -a .env #+NAME: local environment setup :results silent #+begin_src sh heroku config -s | grep 'AUTH0_CLIENT_ID\|AUTH0_CLIENT_SECRET\|AUTH0_DOMAIN' | tee -a .env #+end_src *** FORK Alpha https://devcenter.heroku.com/articles/fork-app - [X] heroku fork : heroku fork --from radiant-shore-29024 --to cjlabeler-alpha - [X] deploy - [X] add git remote named /alpha/ : git remote add alpha git@heroku.com:cjlabeler-alpha.git : git push alpa master - [X] optional: make new app default deployment target : git remote rename heroku old : git remote rename alpha heroku * Issues ** Assets - [ ] callbackURL not updating (defined by Rails.secrets expression) /Tue May 10 09:33:19 CDT 2016/ [[./app/assets/javascripts/home.js.erb]] [[HOMEJS]] : callbackURL: "<%= Rails.application.secrets.auth0_callback_url %>", - [ ] TRY::compile_assets(alias.zsh) : RAILS_ENV=production bundle exec rake assets:precompile --trace - [ ] env variables now return nothing(nil or ""?) auth0 - [ ] TRY::modify config..serve_static.. [[./config/environments/production.rb]] [[ENV-PRODUCTION]] - [ ] TRY::use ENV calls in home.js.erb instead of secrets [[./app/assets/javascripts/home.js.erb]] [[HOMEJS]] : callbackURL: "<%= ENV['AUTH0_CALLBACK_URL' %>", - [ ] compile_assets - [ ] TRY::rename application.js application.js.erb http://stackoverflow.com/questions/10440853/how-to-get-environment-in-javascript-file-in-rails-app