Rails 5 project from API mode to non api mode - ruby-on-rails

A while ago I started a Rails 5 project in API mode, but I would like now for the app to also start rendering html and serving assets.
This is what my application.rb looks like now:
require_relative 'boot'
require 'rails/all'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module AppName
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.
end
end
Notice there's no mention anymore of api_mode.
However, when I try to run the server, I'm getting the following error:
/home/username/Sites/oneroster/app/controllers/application_controller.rb:8:in `<class:ApplicationController>': undefined method `helper_method' for ApplicationController:Class (NoMethodError)
from /home/username/Sites/oneroster/app/controllers/application_controller.rb:1:in `<top (required)>'
What else should I do to make the app work again?

In application_controller.rb I had
class ApplicationController < ActionController::API
That had to be changed to:
class ApplicationController < ActionController::Base

Related

How to autoload classes to use in controller

I have a class in libs and try to use it in a controller. However I cannot access it. I tried to use the autoload function, but that doesn't work, and it shouldn't work in rails 5 in production mode, so I guess I don't need to try this one.. I also tried to require it in my controller, but I don't get the syntax correct I guess. I'm also wondering where to put my class, since I have read several different opinions..
config/application.rb
require_relative 'boot'
require 'rails/all'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module Qipmatedevel
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.1
config.active_job.queue_adapter = :sidekiq
config.autoload_paths += %W(#{config.root}/lib)
# 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.
end
end
app/controller/imports_controller
class ImportsController < ApplicationController
require 'lib/class_qip'
adding
require './lib/class_qip.rb'
fixed it
Put your classes in lib directory only & load as,
config.eager_load_paths << Rails.root.join('lib')
It works on both development and production environment.

Messenger bot using Rails: setup for multiple pages

I want to create a Messenger Bot used by different users for their Facebook pages. I created a rails app and use the facebook-messenger gem.
I successfully created the bot and it works when I do the set up for one page. Now, I follow the instructions to make my bot live on multiple Facebook Pages (see "Make a configuration provider" section).
I'm new to rails and I'm not sure where to put the class ExampleProvider? I put it in my config/application.rb file:
require_relative 'boot'
require 'rails/all'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module BotletterApp
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.
config.paths.add File.join('app', 'bot'), glob: File.join('**', '*.rb')
config.autoload_paths += Dir[Rails.root.join('app', 'bot', '*')]
end
class BotProvider < Facebook::Messenger::Configuration::Providers::Base
def valid_verify_token?(verify_token)
bot.exists?(verify_token: verify_token)
end
def app_secret_for()
ENV['APP_SECRET']
end
def access_token_for(page_id)
bot.find_by(user_id: page_id).page_access_token
end
private
def bot
MyApp::Bot
end
end
Facebook::Messenger.configure do |config|
config.provider = BotProvider.new
end
end
Then I have my app/bot/setup.rb file to create the bot. I don't know how to use the provider I created in place of the ENV variables?
require "facebook/messenger"
include Facebook::Messenger
Facebook::Messenger::Subscriptions.subscribe(access_token: ENV["ACCESS_TOKEN"])
Facebook::Messenger::Profile.set({
get_started: {
payload: 'GET_STARTED_PAYLOAD'
}
}, access_token: ENV['ACCESS_TOKEN'])
I searched in the Rails documentation how to make it work but unfortunately could not find anything.
UPDATE:
Now I'm able to set up the bots for different pages. Unfortunately, the following line of my ConfigProvider is getting an error:
config/initializers/config_provider.rb
def bot
Rails.application.class.parent::Bot
end
I'm getting the following error:
NameError (uninitialized constant BotletterApp::Bot):
config/initializers/config_provider.rb:17:in bot'
config/initializers/config_provider.rb:7:inapp_secret_for'
Do you know how should I name my app?
My BotModule:
module BotletterApp
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.
config.paths.add File.join('app', 'listen'), glob: File.join('**', '*.rb')
config.autoload_paths += Dir[Rails.root.join('app', 'listen', '*')]
end
end
UPDATE, it works with ::Application, here is the new file:
class ConfigProvider < Facebook::Messenger::Configuration::Providers::Base
def valid_verify_token?(verify_token)
ENV['VERIFY_TOKEN']
end
def app_secret_for(page_id)
ENV['APP_SECRET']
end
def access_token_for(page_id)
CoreBot.find_by_page_id(page_id).page_access_token
end
private
def bot
BotletterApp::Application
end
end
Facebook::Messenger.configure do |config|
config.provider = ConfigProvider.new
end
The problem is I get the following error unless my db query seems working (it works in the rails console):
ActiveRecord::StatementInvalid (SQLite3::SQLException: no such column:
page_id.id: SELECT "core_bots".* FROM "core_bots" WHERE
"page_id"."id" = ? LIMIT ?):
Moving to an answer for improved readability ;)
Regarding 'plain'... Instead of
def bot
BotletterApp::Application
end
use
def bot
Bot
end
or (it looks like you named your model containing all pages CoreBot(?) (assuming you have a typical ActiveRecord model in /app/models/core_bot.rb, I was assuming Bot)
def bot
CoreBot
end
Then you should be able to use the template code from the README.md
As for your latest problem: it seems like the access_token_for-method gets called with a hash, searching with something like {id: 1}. You might want to check where that value is coming from. I would suggest to take a few steps back, and stay closer to the template code.

Rails 5 API - error autoloading helper when using the api_only flag

I'm trying to use a module from the folder 'app/helpers/transaction_helper.rb'. (It's important to note that the application is using the api_only flag, and helpers aren't being generated or loaded by default.)
module TransactionHelper
module Generator
def self.code_alphanumeric(params)
end
end
end
I got this error:
NameError: uninitialized constant TransactionHelper
I tried to add the following line to the application.rb
config.autoload_paths += %W(#{config.root}/app/helpers)
require_relative 'boot'
require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "action_cable/engine"
# require "sprockets/railtie"
require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module SistemaControleContasApi
class Application < Rails::Application
config.autoload_paths += %W(#{config.root}/app/helpers)
# 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.
# Only loads a smaller set of middleware suitable for API only apps.
# Middleware like session, flash, cookies can be added back manually.
# Skip views, helpers and assets when generating a new resource.
config.api_only = true
end
end
But this until not work. If I try to put this file in the app/models directory, this work. However, this is not the right local to place a helper.
Could someone help, please?
Normally everything under app is autoloaded by default if you follow the Rails™ naming conventions. See here Docs.
set_autoload_paths: This initializer runs before bootstrap_hook. Adds
all sub-directories of app and paths specified by
config.autoload_paths, config.eager_load_paths and
config.autoload_once_paths to
ActiveSupport::Dependencies.autoload_paths.
So in the first step you should remove config.autoload_paths += %W(#{config.root}/app/helpers) from your config.
Then for every module you should create a subfolder.
So for your problem you should put your module under app/modules/transaction_helper/generator.rb
Also you don't need self in a module scope.
Personally I would create the helper as follows:
module TransactionHelper
def generate_alphanumeric_code
# params are automatically available in helpers.
end
end
And put it under app/modules/transaction_helper.rb.

Rails engine extends config/application.rb

I am in the process of writing a Rails engine but i am not sure how to extend my the config/application.rb
I guess i have to get to the application name somehow
any ideas?
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(:default, Rails.env)
module application_name
class Application < Rails::Application
end
end
For a --full and --mountable engine
This will be generated for you.
module engine_name
class Engine < ::Rails::Engine
end
end
In you main applications gemfile add
gem 'engine_name', path: "/path/to/engine_name"
And in your applications config/routes.rb file
mount engine_name::Engine, at: "/<mount_point_you_choose>"
http://guides.rubyonrails.org/engines.html
Taken from the link above...
The --mountable option tells the generator that you want to create a "mountable" and namespace-isolated engine. This generator will provide the same skeleton structure as would the --full option, and will add:
Asset manifest files (application.js and application.css)
A namespaced ApplicationController stub
A namespaced ApplicationHelper stub
A layout view template for the engine
Namespace isolation to config/routes.rb:

uninitialized constant after capistrano delpoy:cold - nginx, unicorn

I have setup capistrano for deployment with the exact same config/setup as found in the railscasts Pro episode http://railscasts.com/episodes/335-deploying-to-a-vps?view=asciicast.
All of the deploy:check, status and cold tasks run and complete successfully (after some tinkering). However, the app not running and shows the classic "something went wrong" error page. When I check my unicorn.log it shows the error below:
I have tried requiring the module before including it to address threadsafe issues and also autoloading the absolute path in application.rb. Note this all works in development environment.
How can I amend my code to fix this NameError issue?
unicorn.log
E, [2013-10-16T04:15:00.313177 #12996] ERROR -- : uninitialized constant AnswersController::Teebox (NameError)
/home/andrew/rails/teebox/releases/20131016032538/app/controllers/answers_controller.rb:5:in `<class:AnswersController>'
/home/andrew/rails/teebox/releases/20131016032538/app/controllers/answers_controller.rb:1:in `<top (required)>'
answers_controller.rb
class AnswersController < ApplicationController
before_filter :authenticate_user!, except: [:index, :show]
load_and_authorize_resource
require 'teebox/commentable'
include Teebox::Commentable # Offending line
...
end
lib/teebox/commentable.rb
require 'active_support/concern'
module Teebox::Commentable
extend ActiveSupport::Concern
included do
before_filter :comments
end
def comments
#comment = Comment.new
end
end
application.rb
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/decorators)
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += %W(#{config.root}/lib/teebox/commentable.rb)
specs:
capistrano 2.15.5
rails 3.2.14
ruby 1.9.3-p488
ubuntu 12.04
If anyone needs more code just shout.
I had an naming convention which wasn't an issue on Mac but was an issue on a case sensitive Linux box.
I had a lib/Teebox/commentable.rb folder structure and was then calling:
include Teebox::Commentable.
So I switched this to lib/teebox/commentable.rb (Lowercase teebox) and this solved the error.

Resources