#StackBounty: #ruby-on-rails #amazon-web-services #bundle #amazon-elastic-beanstalk Bundler error when deploying Rails 6 App to Elastic…

Bounty: 50

I’ve been struggling getting around the well known bundler 2.0.x error when deploying to both Heroku and AWS Elastic Beanstalk. After trying many of the suggested remedies like updating gems and installing bundler 2.0.x or bundler update --system. None of this has worked so far. I found a solution to create a file in .ebextensions like so:

files:

# Runs before ./10_bundle_install.sh`:`

"/opt/elasticbeanstalk/hooks/appdeploy/pre/09_gem_install_bundler.sh" :

mode: "000775"

owner: root

group: users

content: |

#!/usr/bin/env bash



EB_APP_STAGING_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)

EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)

# Source the application's ruby, i.e. 2.6. Otherwise it will be 2.3, which will give this error: bundler requires Ruby version >= 2.3.0``

. $EB_SCRIPT_DIR/use-app-ruby.sh



cd $EB_APP_STAGING_DIR

echo "Installing compatible bundler"

gem install bundler -v 2.1.0.pre.2

This is the error I’m still getting on eb deploy staging-1:

Creating application version archive "app-7b50-191111_122622".
Uploading: [##################################################] 100% Done...
2019-11-11 17:28:21    INFO    Environment update is starting.      
2019-11-11 17:28:28    INFO    Deploying new version to instance(s).
2019-11-11 17:31:36    ERROR   [Instance: i-0ba40e32901557bee] Command failed on instance. Return code: 1 Output: (TRUNCATED)...ystem, run `bundle update --bundler`.
To install the missing version, run `gem install bundler:2.1.0.pre.2`
        from /opt/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems.rb:303:in `activate_bin_path'
        from /opt/rubies/ruby-2.6.5/bin/bundle:23:in `<main>'. 
Hook /opt/elasticbeanstalk/hooks/appdeploy/pre/10_bundle_install.sh failed. For more detail, check /var/log/eb-activity.log using console or EB CLI.
2019-11-11 17:31:36    INFO    Command execution completed on all instances. Summary: [Successful: 0, Failed: 1].
2019-11-11 17:31:36    ERROR   Unsuccessful command execution on instance id(s) 'i-0ba40e32901557bee'. Aborting the operation.
2019-11-11 17:31:37    ERROR   Failed to deploy application.        

ERROR: ServiceError - Failed to deploy application.
[12:31:40] (master) tml_portal
// ♥ eb deploy staging-1
Creating application version archive "app-7b50-191111_123229".
Uploading: [##################################################] 100% Done...
2019-11-11 17:34:45    INFO    Environment update is starting.      
2019-11-11 17:34:53    INFO    Deploying new version to instance(s).
2019-11-11 17:37:47    ERROR   [Instance: i-0ba40e32901557bee] Command failed on instance. Return code: 1 Output: (TRUNCATED)...ystem, run `bundle update --bundler`.
To install the missing version, run `gem install bundler:2.1.0.pre.2`
        from /opt/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems.rb:303:in `activate_bin_path'
        from /opt/rubies/ruby-2.6.5/bin/bundle:23:in `<main>'. 
Hook /opt/elasticbeanstalk/hooks/appdeploy/pre/10_bundle_install.sh failed. For more detail, check /var/log/eb-activity.log using console or EB CLI.
2019-11-11 17:37:47    INFO    Command execution completed on all instances. Summary: [Successful: 0, Failed: 1].
2019-11-11 17:37:47    ERROR   Unsuccessful command execution on instance id(s) 'i-0ba40e32901557bee'. Aborting the operation.
2019-11-11 17:37:48    ERROR   Failed to deploy application.        

ERROR: ServiceError - Failed to deploy application.

Any ideas on how to get around this dreaded Bundler issue for deployment?


Get this bounty!!!

#StackBounty: #sql #ruby-on-rails SQL query rails, how to filter our current reservation

Bounty: 50

For an hotel app, I’m trying to filter out all available accommodations for a given arrival and departure date, so a user only sees these as options.

The way I currently go about it, is by identifying all unavailable accommodations first and then deducting them from all accommodations.

Question

When I want to edit a reservation, I would like to:

  • exclude the current reservation when evaluating available accommodations

==> so in @unavailable_accommodations, the reservation and its accommodation for the reservation.arrival and reservation.departure are not evaluated in the query statement

Is this possible, or how else can I achieve to only get available accommodations for a giver arrival and departure without taking the current reservation.accommodation into account?

Example desired outcome

  • Say reservation_1 books accommodation_1 from Jan 1 to Jan 2.
  • Then there is reservation_2 which books accommodation_1 from Jan 5 to Jan 6.
  • When I subsequently edit reservation_1 and alter the departure to Jan 6, accommodation_1 should not be marked as available as reservation_2 already booked this accommodation

Code

models

class Reservation < ApplicationRecord
  belongs_to :hotel
  belongs_to :accommodation
end

class Accommodation < ApplicationRecord
  belongs_to :accommodation_category
  has_many :reservations, dependent: :destroy
  accepts_nested_attributes_for :accommodation_category
end

class Hotel < ApplicationRecord
  has_many :accommodation_categories, dependent: :destroy
  has_many :accommodations, through: :accommodation_categories
  has_many :reservations, dependent: :destroy
end

Query

@unavailable_accommodations = Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival <= ? AND ? <= reservations.departure", arrival, departure)
.or(Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival >= ? AND ? >= reservations.departure", arrival, departure)).distinct

controller action


def accommodations_availability
#check if there was an accommodation for this reservation
    if !params[:reservation].nil?
      reservation = Reservation.find(params[:reservation])
      @prev_accommodation = reservation.accommodation
      @previous_cat = @prev_accommodation.accommodation_category
    end
    hotel = Hotel.includes(:accommodations).find(params[:id])
    arrival = Date.parse(accommodation_params[:arrival])
    departure = Date.parse(accommodation_params[:departure])
    time_span = arrival..departure

    #SQL statement
    @unavailable_accommodations = Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival <= ? AND ? <= reservations.departure", arrival, departure)
    .or(Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival >= ? AND ? >= reservations.departure", arrival, departure)).distinct


    @hotel_cats = hotel.accommodation_categories
    @hotel_accos = Accommodation.where(accommodation_category: @hotel_cats)
    @accommodations = @hotel_accos - @unavailable_accommodations
    @available_cats = []
    @accommodations.each do |acco|
      if !@available_cats.include? acco.accommodation_category
        @available_cats << acco.accommodation_category
      end
    end

    respond_to do |format|
      format.js
    end
  end


Get this bounty!!!

#StackBounty: #ruby-on-rails Passing Gibbon (Mailchimp) error from service to controller

Bounty: 50

I am using Mailchimp (via the Gibbon gem) to add email addresses to my Mailchimp mailing list, and I want to handle any errors that are returned by Mailchimp and display them in my view.

Here is my Pages controller:

class PagesController < ApplicationController

    def subscribe
        email = subscriber_params[:email]
        if email.empty?
            flash[:error] = 'Please provide an email.'
            redirect_to root_path
        else
            subscriber = Mailchimp.new.upsert(email)
            if subscriber
                flash[:success] = 'You're in!'
                redirect_to root_path(subscribed: :true)
            else
                # Return error coming from Mailchimp (i.e. Gibbon::MailChimpError)
            end
        end
    end
end

And here is the app > services > mailchimp.rb file I set up to separate out the Mailchimp logic:

class Mailchimp

  def initialize
    @gibbon = Gibbon::Request.new(api_key: Rails.application.credentials.mailchimp[:api_key])
    @list_id = Rails.application.credentials.mailchimp[:list_id]
  end

  def upsert(email)
    begin
      @gibbon.lists(@list_id).members.create(
      body: {
        email_address: email,
        status: "subscribed"
      }
    )
    rescue Gibbon::MailChimpError => e #This is at the bottom of the Gibbon README
      raise e.detail
    end
  end

end

What I’m trying to figure out is how to return/send Gibbon::MailChimpError back to my Pages#subscribe action. I see it being outputted as a RuntimeError in my console, but I’m not sure the right way to access/pass it along.

And please let me know if there’s a better practice for this kind of implementation.


Get this bounty!!!

#StackBounty: #ruby-on-rails #ruby #rspec #minitest Error when migrating for MiniTest to RSpec

Bounty: 100

I’m trying to migrate my rails application to RSpec. But I’m getting the error uninitialized constant ActiveRecord::Relation when running the specs. It says it’s on line 10 of application.rb which is Bundler.require(:default, Rails.env) if defined?(Bundler)

error message

An error occurred while loading ./spec/requests/teams_spec.rb.
Failure/Error: require File.expand_path('../config/environment', __dir__)

NameError:
  uninitialized constant ActiveRecord::Relation
# ./config/application.rb:10:in `<top (required)>'
# ./config/environment.rb:2:in `require'
# ./config/environment.rb:2:in `<top (required)>'
# ./spec/rails_helper.rb:5:in `require'
# ./spec/rails_helper.rb:5:in `<top (required)>'
# ./spec/swagger_helper.rb:2:in `require'
# ./spec/swagger_helper.rb:2:in `<top (required)>'
# ./spec/requests/teams_spec.rb:1:in `require'
# ./spec/requests/teams_spec.rb:1:in `<top (required)>'
# ------------------
# --- Caused by: ---
# NameError:
#   uninitialized constant ActiveRecord::Relation
#   ./config/application.rb:10:in `<top (required)>'

Spec

require 'rails_helper'

RSpec.describe Api::V1::CertificateRequestsController, type: :controller do
  describe '#create_v1_4' do
    it 'worked' do
        expect(true).to eq(true)
    end
  end
end

spec_helper.rb

# frozen_string_literal: true

RSpec.configure do |config|
  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  # rspec-mocks config goes here. You can use an alternate test double
  # library (such as bogus or mocha) by changing the `mock_with` option here.
  config.mock_with :rspec do |mocks|
    # Prevents you from mocking or stubbing a method that does not exist on
    # a real object. This is generally recommended, and will default to
    # `true` in RSpec 4.
    mocks.verify_partial_doubles = true
  end

  # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
  # have no way to turn it off -- the option exists only for backwards
  # compatibility in RSpec 3). It causes shared context metadata to be
  # inherited by the metadata hash of host groups and examples, rather than
  # triggering implicit auto-inclusion in groups with matching metadata.
  config.shared_context_metadata_behavior = :apply_to_host_groups
end

rails_helper.rb

# frozen_string_literal: true

# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'

ENV['RAILS_ENV'] ||= 'test'

require File.expand_path('../config/environment', __dir__)

# Prevent database truncation if the environment is production
if Rails.env.production?
  abort('The Rails environment is running in production mode!')
end
require 'rspec/rails'
require 'database_cleaner'
require 'factory_bot_rails'

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories.
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }

# Checks for pending migrations and applies them before tests are run.
# If you are not using ActiveRecord, you can remove these lines.
begin
  ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
  puts e.to_s.strip
  exit 1
end
RSpec.configure do |config|
  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = true

  # RSpec Rails can automatically mix in different behaviours to your tests
  # based on their file location, for example enabling you to call `get` and
  # `post` in specs under `spec/controllers`.
  config.infer_spec_type_from_file_location!

  # Filter lines from Rails gems in backtraces.
  config.filter_rails_from_backtrace!
  # arbitrary gems may also be filtered via:
  # config.filter_gems_from_backtrace("gem name")

  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.around(:each) do |example|
    DatabaseCleaner.cleaning do
      example.run
    end
  end
end

test.rb

SslCom::Application.configure do
  MIGRATING_FROM_LEGACY = false
  # Settings specified here will take precedence over those in config/environment.rb

  # The test environment is used exclusively to run your application's
  # test suite.  You never need to work with it otherwise.  Remember that
  # your test database is "scratch space" for the test suite and is wiped
  # and recreated between test runs.  Don't rely on the data there!
  config.cache_classes = true

  # Log error messages when you accidentally call methods on nil.
  config.whiny_nils = true

  # Show full error reports and disable caching
  config.consider_all_requests_local       = true
  config.action_controller.perform_caching = false

  # Raise exceptions instead of rendering exception templates
  config.action_dispatch.show_exceptions = false

  # Disable request forgery protection in test environment
  config.action_controller.allow_forgery_protection    = false

  # Tell Action Mailer not to deliver emails to the real world.
  # The :test delivery method accumulates sent emails in the
  # ActionMailer::Base.deliveries array.
  config.action_mailer.delivery_method = :test
  config.action_mailer.perform_deliveries = true
  config.action_mailer.default_url_options = {host: 'localhost:3000'}

  config.after_initialize do
    Rails.application.routes.default_url_options = {host: 'localhost:3000'}
  end

  config.force_ssl = false

  # Use SQL instead of Active Record's schema dumper when creating the test database.
  # This is necessary if your schema can't be completely dumped by the schema dumper,
  # like if you have constraints or database-specific column types
  # config.active_record.schema_format = :sql

  # Sort the order test cases are executed.
  config.active_support.test_order = :sorted

  # Print deprecation notices to the stderr
  config.active_support.deprecation = :stderr

  ActiveMerchant::Billing::Base.mode = :test

  config.eager_load=false

  config.serve_static_assets = true
  config.static_cache_control = "public, max-age=3600"

  #config.log_level = Logger::INFO

  GATEWAY_TEST_CODE=1.0
  # END ActiveMerchant configuration
end

#require "#{Rails.root}/lib/firewatir_url.rb"

application.rb

# frozen_string_literal: true

require File.expand_path('boot', __dir__)
require 'oauth/rack/oauth_filter'
require 'rack/ssl-enforcer'
require 'rails/all'
require './lib/middleware/catch_json_parse_errors'

Bundler.setup
# If you have a Gemfile, require the gems listed there, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

CLIENT_OPTIONS = ['aswesome.com', 'aswementer'].freeze
DEPLOYMENT_CLIENT = CLIENT_OPTIONS[0]

Struct.new('Expiring', :before, :after, :cert)
Struct.new('Notification', :before, :after, :domain, :expire, :reminder_type, :scanned_certificate_id)
Struct.new('Reminding', :year, :cert)

module AwesomeApp
  class Application < Rails::Application
    # set environment variables
    config.before_configuration do
      env_file = File.join(Rails.root, 'config', 'local_env.yml')
      YAML.safe_load(File.open(env_file)).each do |key, value|
        ENV[key.to_s] = value
      end
    end

    # 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.

    # Custom directories with classes and modules you want to be autoloadable.
    config.autoload_paths += %W[#{config.root}/lib]

    Bundler.require(*Rails.groups)
    # Config::Integration::Rails::Railtie.preload

    # Add additional load paths for your own custom dirs
    %w[observers mailers middleware serializers].each do |dir|
      config.autoload_paths << "#{config.root}/app/#{dir}"
    end

    # Only load the plugins named here, in the order given (default is alphabetical).
    # :all can be used as a placeholder for all plugins not explicitly named.
    # config.plugins = [ :exception_notification, :ssl_requirement, :all ]

    # Activate observers that should always be running.
    # config.active_record.observers = :cacher, :garbage_collector, :forum_observer

    # 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

    # Configure the default encoding used in templates for Ruby 1.9.
    config.encoding = 'utf-8'

    # Configure sensitive parameters which will be filtered from the log file.
    config.filter_parameters += %i[password password_confirmation]
    # config.action_mailer.default_url_options = { :host => Settings.actionmailer_host }

    # machinist generator
    # config.generators do |g|
    #   g.fixture_replacement :machinist
    # end

    # Rails Api
    config.api_only = false

    # turn off strong parameters
    config.action_controller.permit_all_parameters = true

    config.generators do |g|
      g.test_framework :minitest, spec: true, fixture: false
      g.jbuilder false
    end

    # config.middleware.use OAuth::Rack::OAuthFilter
    config.middleware.insert_before ActionDispatch::ParamsParser, 'CatchJsonParseErrors'

    # Delayed Job
    config.active_job.queue_adapter = :delayed_job

    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins '*'
        resource '/certificate/*',
                 headers: :any,
                 methods: %i[get post delete put options head],
                 max_age: 0
      end
    end

    # Enable the asset pipeline
    config.assets.enabled = true

    config.sass.preferred_syntax = :sass
    config.sass.line_comments = false
    config.sass.cache = false
    config.action_mailer.default_url_options = { host: 'secure.ssl.com', protocol: 'https' }
    if DEPLOYMENT_CLIENT =~ /certassure/i && Rails.root.to_s =~ /Development/
      paths['config/database'] = 'config/client/certassure/database.yml'
    end
  end
end

require "#{Rails.root}/lib/base.rb"
require "#{Rails.root}/lib/asset_tag_helper.rb"
require "#{Rails.root}/lib/array.rb"
require "#{Rails.root}/lib/range.rb"
require "#{Rails.root}/lib/in_words.rb"
require "#{Rails.root}/lib/kernel.rb"
require "#{Rails.root}/lib/money.rb"
# require "#{Rails.root}/lib/subdomain-fu.rb"
require "#{Rails.root}/lib/domain_constraint.rb"
require "#{Rails.root}/lib/preferences.rb"
require "#{Rails.root}/lib/active_record.rb"
require "#{Rails.root}/lib/active_record_base.rb"
require "#{Rails.root}/lib/hash.rb"
require 'will_paginate'

# try to figure this out for heroku and rails 3
# class Fixnum; include InWords; end
# class Bignum; include InWords; end
DB_STRING_MAX_LENGTH = 255
DB_TEXT_MAX_LENGTH = 40_000
HTML_TEXT_FIELD_SIZE = 20
AMOUNT_FIELD_SIZE = 10
ADDRESS_FIELD_SIZE = 30
SERVER_SIDE_CART = false
# SQL_LIKE = Rails.configuration.database_configuration[Rails.env]['adapter'].
#   downcase=='postgresql' ? 'ilike' : 'like'
db_env = Rails.configuration.database_configuration[Rails.env]
db_adapter = db_env['adapter'].downcase if db_env.present?
SQL_LIKE = db_adapter == 'postgresql' ? 'ilike' : 'like'

# uncomment to track down bugs on heroku production
# ApplicationRecord.logger.level = 0 # at any time
ActiveMerchant::Billing::CreditCard.require_verification_value = false
PublicSuffix::List.default =
  PublicSuffix::List.parse(File.read(PublicSuffix::List::DEFAULT_LIST_PATH), private_domains: false)


Get this bounty!!!

#StackBounty: #ruby-on-rails #forms #validation #activerecord #simple-form Rails custom validation that limits the number of has_many :…

Bounty: 50

I have a Rails project with a “Product Variant” form. The Product variant model is called Variant, and on the Variant form users should be able to select one choice for each option available. For instance a T-Shirt might have an “Option” called “Size” with the “Choices” small, medium, or large, and another “Option” called one “Color” with the “Choices” red, green, blue. Thus, the Variant created is a unique SKU such as a “T-shirt — Size: Small, Color: Green.” Or if it were a product that had 3 options instead of 2, the variant would require 3 choices per option, such as “Guitar Strap – Size: Long, Fabric Color: Red, Leather Color: Brown”.

I can’t figure out how to write a custom validation that only allows the user to save one choice per option. Each option should only have one choice selected for each variant. Here’s an illustration.

need a validation that prevents this

correct outcome

Here are my models with the relevant associations…

models/variant.rb

class Variant < ApplicationRecord    
  has_many :selections
  has_many :choices, through: :selections

  validate :one_choice_per_option

  private
    def one_choice_per_option
      # can't figure out how to do this custom validation here
    end

end

models/choice.rb

class Choice < ApplicationRecord
  has_many :variants, through: :selections

  belongs_to :option
end

models/selection.rb

class Selection < ApplicationRecord
  belongs_to :choice
  belongs_to :variant
end

models/option.rb

class Option < ApplicationRecord
  has_many :choices, dependent: :destroy

  accepts_nested_attributes_for :choices, allow_destroy: true
end

The best I’ve managed to do is get this custom validation working on in models/variant.rb

def one_choice_per_option
  self.product.options.each do |option|
    if option.choices.count > 1
      errors.add(:choice, 'Error: select one choice for each option')
    end
  end
end

But that only allows one Choice total through the variant form. What I want to do is allow one choice for each set of options.

I know that this could be done with Javascript in the UI, but this is essential to keeping the database clean and preventing a user error, so I believe it should be a Rails validation at the model level.

What is a “Railsy” way to do this type of custom validation? Should I be trying to do a custom validation on the Selection model? If so, how?


UPDATE

Based on the discussion in the comments. It seems that I need to do some combination of Active Record querying to make this work. @sevensidedmarble’s “EDIT 2” below is closer but that is giving me this error: Type Error compared with non class/module

If I save the wrong behavior to the database and then call Variant.last.choices in the console it feels like I’m getting closer:

illustrating the form behavior I need to prevent with a validation

showing the console response

So essentially, what I need to do is not allow the Variant form to save if there is more than one Selection with the same option_id. A selection shouldn’t save unless the option_id is unique to the associated Variant.

Something like this is what I’m trying to do:

validate :selections_must_have_unique_option

  private

    def selections_must_have_unique_option
      unless self.choices.distinct(:option_id)
        errors.add(:options, 'can only have one choice per option')
      end
    end

But that code doesn’t work. It just saves the form as if the validation weren’t there.


Get this bounty!!!

#StackBounty: #ruby-on-rails #ruby-on-rails-3 #logging #actioncontroller Rails 3.2.x: how to filter long parameters from getting logged…

Bounty: 100

There are similar questions like this, this, and this.

None help because the goal is to prevent logging of long parameters within a specific action instead of using config.filter_parameters. Also the answer must work for Rails 3.2.x while many answers are based on Rails 5.

One answer suggests calling request.filtered_parameters inside the controller method, but calling request.filtered_parameters.delete :long_param did not stop :long_param from getting logged.


Get this bounty!!!

#StackBounty: #ruby-on-rails #json #postgresql #jsonb How to update different json (jsonb) attributes asynchronously with rails and pos…

Bounty: 50

I have a large json object stored in a postgres table column, an example of the schema is like this:

create_table “document” do |t|
    t.jsonb “data”, default: []
end

At the moment I’m updating json in the column like so:

# find document in rails then…
doucment.data[‘some_attribute’][2][‘another_attribute’] = 100
doucment.save

However I write this json attribute many times and sometimes data becomes lost because if two calls are writing it at the same time, then the whole object will be saved or over written with the current objects old data.

For example if there’s two different saves going through at the same with the following

Save 1:

doucment.data[‘some_attribute’][2][‘another_attribute’] = 100
doucment.save

Save 2:

doucment.data[‘some_attribute’][2][‘different_attribute’] = 200
doucment.save

then either one of the attributes data will be lost because the other one will save it’s json but with old data that hasn’t been refreshed yet.

What is the best way to go about making both calls save the new data correctly.

Is there any json method that can just go in and update one attribute, like update_attribute but for a jsonb attribute?


Get this bounty!!!

#StackBounty: #ruby #ruby-on-rails #join #active-record Update join table using list of checkboxes in Rails

Bounty: 50

I have Gig and Singer Active Record models (standard–no customization just yet) with a many-to-many relationship through a generic join table which holds nothing but the respective ids of Gig and Singer. My form sends a given gig id and all the singers who will be attending, denoted with check boxes. I need to have the ability to check or uncheck singers. The following code works, but it does so by removing all the singers from a gig and re-adding them. This feels hacky… is there a better way? (I think this is all the code necessary but let me know if you need me to add anything)

class GigSingersController < ApplicationController

    def create
        gig = Gig.find(params[:gig_id])
        singer_ids = params[:singer_ids] # [1, 4, 5,]
        gig.singers = []
        singer_ids.each do |id|
            singer = Singer.find(id)
            gig.singers << singer
        end
        redirect_to gigs_path
    end
end

EDIT:

As requested in the comments, here are the schema and relevant models, although as I said, they are completely generic. Perhaps I didn’t do a good job of making my question clear: Is the best way to create these relationships when using a checkbox to remove all existing ones and recreate them from the boxes currently checked, thereby removing any that the user unchecked on an edit?

ActiveRecord::Schema.define(version: 2019_07_19_195106) do

  create_table "gig_singers", force: :cascade do |t|
    t.integer "gig_id"
    t.integer "singer_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "gigs", force: :cascade do |t|
    t.string "name"
    t.text "notes"
    t.datetime "datetime"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "singers", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.boolean "active"
  end

class Gig < ApplicationRecord
    has_many :gig_singers
    has_many :singers, through: :gig_singers
end

class GigSinger < ApplicationRecord
    belongs_to :gig
    belongs_to :singer
end

class Singer < ApplicationRecord
    has_many :gig_singers
    has_many :gigs, through: :gig_singers

end


Get this bounty!!!

#StackBounty: #ruby-on-rails #cors #ruby-on-rails-5 Rails Font CORS policy

Bounty: 50

I can’t load this font for a CORS Policy.

Folder: app/assets/fonts/Inter-UI.var.woff2

<%=preload_link_tag("Inter-UI.var.woff2", as:'font', crossorigin: "anonymous")%>

Error:

Access to font at
http://localhost:3000/assets/Inter-UI.var-e2e323d19d24946c4d481135af27ba00f3266aa9d4abe4262e97088feccb6ca4.woff2
from origin ‘http://0.0.0.0:3000‘ has been blocked by CORS policy: No
‘Access-Control-Allow-Origin’ header is present on the requested
resource.

Response HTTP status code

enter image description here

If I go directly to http://localhost:3000/assets/Inter-UI.var-e2e323d19d24946c4d481135af27ba00f3266aa9d4abe4262e97088feccb6ca4.woff2 I can download the file successfully.

I have already tried with rack-cors gem, but it’s not working

config/environments/developement.rb

Rails.application.configure do

  config.middleware.insert_before 0, Rack::Cors do
    allow do
      origins '*'
      resource '*', :headers => :any, :methods => :any
    end
  end


Get this bounty!!!

#StackBounty: #ruby-on-rails #postgresql #activerecord Is it OK to specify a schema in `table_name_prefix`?

Bounty: 50

TL;DR: Is it OK to specify a schema in table_name_prefix?

We have a large Rails application that is not quite a traditional multi-tenant app. We have a hundred clients, all supported by one app, and that number will never grow more than 1-2 per year. Currently, every client has their own Postgresql database.

We are addressing some infrastructure concerns of having so many distinct databases…most urgently, a high number of simultaneous database connections when processing many clients’ data at the same time.

The app is not visible, even to clients, so a lot of traditional multi-tenant web site philosophies don’t apply here neatly.

  • Each tenant has a distinct Postgres database, managed in
    database.yml.
  • Each database has a schema, named for the tenant.
  • We have a model specific to each tenant with notably different code.
  • Each model uses establish_connection to select a different database and schema.
  • Each model uses a distinct table_name_prefix with the client’s unique name.

The tables vary extensively for each tenant. There is no hope or desire to normalize the clients together. Clients are not provisioned dynamically — it is always a new code release with migrations.

We intend to move each of the client schemas into one database, so fewer distinct connection pools are required. The unique names we currently have at the database, schema, and table names mean there is no possibility of name collisions.

We’ve looked at the Apartment gem, and decided it is not a good fit for what we’re doing.

We could add all hundred schemas to schema_search_path, so all clients could share the same connection pool and still find their schema. We believe this would reduce our db connection count one-hundred-fold. But we’re a bit uneasy about that. I’ve found no discussions of how many are too many. Perhaps that would work, and perhaps there would not have a performance penalty finding tables.

We’ve found a very simple solution that seems promising, by adding the schema in the table_name_prefix. We’re already setting this like:

def self.table_name_prefix
  'client99_'
end

Through experimenting and looking within Rails 4 (our current version) and Rails 5 source code, this works to specify the schema (‘tenant_99’) as well as the traditional table prefix (‘client99’) :

def self.table_name_prefix
  'tenant_99.client99_'
end

Before that change, queries looked like this:

SELECT COUNT(*) FROM "client99_products"

After, they include the schema, as desired:

SELECT COUNT(*) FROM "tenant_99.client99_products"

This seems to answer our needs, with no downsides. I’ve searched the Interwebs for people encouraging or discouraging this practice, and found no mention of it either way.

So through all this, here are the questions I haven’t found definitive answers for:

  • Is there a concern of having too many schemas listed in schema_search_path?
  • Is putting a schema name in table_name_prefix okay?


Get this bounty!!!