It seams like the environment is not loaded when I try to execute a shell command inside rails project.
I fix it like this:
rcmd = 'rake'
rcmd = '/opt/ruby-enterprise-1.8.7-2010.02/bin/rake' if Rails.env.to_s == 'production'
rcmd = '/usr/local/bin/rake' if Rails.env.to_s == 'staging'
`cd #{Rails.root}; #{rcmd} RAILS_ENV=#{Rails.env} ts:in:delta`
Is there a better way?
Why are you trying to shell out and invoke Rake from within the Rails project? Just make a class that does all the work.
# lib/ts_in_delta.rb
class TsInDelta
def run
# code that does all the work here
end
end
You can use this from Rake quite easily:
# lib/tasks/ts_in_delta.rake
namespace :ts do
namespace :in do
task :delta => [:environment] do
TsInDelta.new.run
end
end
end
# shell
$ rake ts:in:delta
You can also use this from anywhere else in your Rails project quite easily, such as from a controller.
# app/controllers/posts_controller.rb (snippet)
class PostsController < ApplicationController
def ts_in_delta
TsInDelta.new.run
render :json => true
end
end
# config/routes.rb (snippet)
MyApp::Application.routes.draw do
resources :posts do
collection do
post 'ts_in_delta'
end
end
end
Related
I'm trying to create the below route but I am running into a "routing error" of "uninitialized constant Foo::Bar::Biz"
/foo/bar/biz/<biz_id>/custom
My routes file is as follows:
namespace(:foo) do
namespace(:bar) do
resources(:biz, only: []) do
get('/custom' => 'foo/bar/biz/custom#index') # I have also tried just custom#index
end
end
end
When I run rake routes I see the route and the controller.
/foo/bar/biz/:biz_id/custom(.:format) foo/bar/biz/custom#index
My controllers file structure is this:
controllers/foo/bar/biz/custom_controller.rb
I don't currently have a controller for biz, but I have tested with one present.
My custom_controller is as follows:
module Foo
module Bar
module Biz
class CustomController < FooController
def index
// do something
end
end
end
end
end
I suspect my routes are setup correctly and my error is in my controller or module setup. Is there something I am missing?
Change your path
'foo/bar/biz/custom#index'
to path starting with root (/)
namespace(:foo) do
namespace(:bar) do
resources(:biz, only: []) do
get('/custom' => '/foo/bar/biz/custom#index')
end
end
end
Following this tutorial, I created the API of my existing blog web application on Rails. I am getting the error:
uninitialized constant API
This is my code:
lib/api/v1/articles.rb:
module API
module V1
class Articles < Grape::API
version 'v1'
format :json
resource :articles do
desc "Return list of recent posts"
get do
Article.recent.all
end
end
end
end
end
lib/api/v1/root/rb
module API
module V1
class Root < Grape::API
mount API::V1::Articles
end
end
end
lib/api/root.rb
module API
class Root < Grape::API
prefix 'api'
mount API::V1::Root
end
end
lib/tasks/routes.rake
namespace :api do
desc "API Routes"
task :routes => :environment do
API::Root.routes.each do |api|
method = api.route_method.ljust(10)
path = api.route_path.gsub(":version", api.route_version)
puts " #{method} #{path}"
end
end
end
config/routes.rb
Rails.application.routes.draw do
mount API::Root => '/'
get 'welcome/index'
root 'welcome#index'
resources :articles
end
This is the existing web application code:
app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def new
end
def create
# render plain: params[:article].inspect
#article = Article.new(article_params)
#article.save
redirect_to #article
end
def show
#article = Article.find(params[:id])
end
private
def article_params
params.require(:article).permit(:title,:text)
end
end
Now I'm in the Accessing API routes part of this article. When I run rake routes it gives the error, uninitialized constant API.. What I'm doing wrong.
Edit: As per the comment, giving the detailed error
rake aborted!
NameError: Uninitialized constant API
F:/blog/config/routes.rb:2:in 'block in <top (required)>'
F:/blog/config/routes.rb:1:in '<top (required)>'
C:in 'execute_if_updated'
F:/blog/config/environment.rb:5:in '<top (required)>'
Tasks: TOP =>routes =>environment
Contents of environment.rb
# Load the Rails application.
require File.expand_path('../application', __FILE__)
# Initialize the Rails application.
Rails.application.initialize!
When I insert config.autoload_paths += Dir["#{config.root}/lib/**/"] in your config/application.rb, and run rake routes, it gives the error can't convert Symbol into String
Upgrading the grape version, I got this error:
As per the discussion, you need to update your grape gem's version to 0.9.0 and then you need to add this line in your Gemfile:
gem 'grape', '0.9.0'
and then:
$ bundle install
As of version 0.11.0, the documentation says
Rails
Place API files into app/api. Rails expects a subdirectory that
matches the name of the Ruby module and a file name that matches the
name of the class. In our example, the file name location and
directory for Twitter::API should be app/api/twitter/api.rb.
Simple solution would be creating another api folder and moving entire files & dirs into app/api/api folder
I try to test my controller concerns using minitest-rails and combining this techniques:
http://ridingtheclutch.com/post/55701769414/testing-controller-concerns-in-rails.
Anonymous controller in Minitest w/ Rails
And i get "no route matches error":
ActionController::UrlGenerationError: No route matches {:action=>"index", :controller=>"fake"}
require "test_helper"
require "warden_mock"
class FakeController < ApplicationController
attr_accessor :request
def initialize(method_name=nil, &method_body)
include MyConcern # method redirect_to_404 placed here
#request = OpenStruct.new # mockup request
#request.env = {}
#request.env['warden'] = WardenMock.new # mockup warden
if method_name and block_given? # dynamically define action for concern methods testing
self.class.send(:define_method, method_name, method_body)
test_routes = Proc.new do
resources :fake
end
Rails.application.routes.eval_block(test_routes)
end
end
end
describe FakeController do # just very simple test
context "just redirect_to_404" do
it "it must redirect to /404" do
#controller = FakeController.new(:index) { redirect_to_404 }
get :index
assert_redirected_to '/404'
end
end
end
I have rails 4.1.5 and minitest 5.4.0
Probably too late for the OP, but I've done it in this way:
require 'test_helper'
class SolrSearchParamsFakeController < ApplicationController
include SolrSearchParams # this is my controller's concern to test
def index
# The concern modify some of the parameters, so I'm saving them in a
# variable for future test inspection, so YMMV here.
#params = params
render nothing: true
end
end
Rails.application.routes.draw do
# Adding a route to the fake controller manually
get 'index' => 'solr_search_params_fake#index'
end
class SolrSearchParamsFakeControllerTest < ActionController::TestCase
def test_index
get :index, search: 'asdf wert'
# finally checking if the parameters were modified as I expect
params = assigns(:params)
assert_equal params[:original_search], 'asdf wert'
end
end
Update
Sorry, but actually this is messing up all my tests that involve route access in some way, as with Rails.application.routes.draw I'm rewriting all the routes for tests and leaving just that solr_search_params_fake#index route.
Not sure how to add instead of rewriting.... a fix would be adding directly to config/routes.rb my test routes with an if Rails.env.test? condition? (yeah, it's a crappy solution, but I'll leave this here in case someone find a better way to do this).
In Rails, is it possible to namespace models in modules and still get correct behavior from url_for?
For instance, here, url_for works as expected:
# app/models/user.rb
class User < ActiveRecord::Base
end
# config/routes.rb
resources :users
# app/views/users/index.html.haml
= url_for(#user) # /users/1
Whereas after putting the User model into a module, url_for complains about an undefined method m_user_path:
# app/models/m/user.rb
module M
class User < ActiveRecord::Base
end
end
# config/routes.rb
resources :users
# app/views/users/index.html.haml
= url_for(#user) # undefined method 'm_users_path'
Is it possible to have url_for ignore the module in M::User and return user_path for url_for(#user) instead of m_user_path?
UPDATE
So, after almost 5 years, here's the solution, thanks to esad. This has been tested in Rails 4.2.
# app/models/m/user.rb
module M
class User < ActiveRecord::Base
end
end
# app/models/m.rb
module M
def self.use_relative_model_naming?
true
end
def self.table_name_prefix
'm_'
end
end
# config/routes.rb
resources :users
# app/views/users/index.html.haml
= url_for(#user) # /users/1
Note: when generating model, view and controller with bin/rails g scaffold m/user, the views and the controller will be namespaced, too. You need to move app/views/m/users to app/views/users and app/controllers/m/users_controller.rb to app/controllers/users_controller.rb; you also need to remove references to the module M everywhere except in the model M::User.
Finally, the goal here was to namespace models but not views and controllers. With esads solution, the module M (containing User) is explicitly told to not appear in routes. Thus, effectifely, the M is stripped of and only User remains.
The user model can now reside in app/views/models/m/user.rb, the users controller lives in app/views/controllers/users_controller.rb and the views can be found in app/views/users.
Just define use_relative_model_naming? in the containing module to avoid prefixing the generated route names:
module M
def self.use_relative_model_naming?
true
end
end
Use
namespace "blah" do
resources :thing
end
Then routes will be named appropiately.
rake routes
To view all routes
Specify the module on the route
resources :users, :module => "m"
or use scope to do it
scope :module => "m" do
resources :users
end
In my case I overridden the url_for method on my application_helper.rb file to add the :network param on all routes from my namespace :mkp.
module ApplicationHelper
def url_for(options = {})
if options.is_a?(Hash) && options.has_key?(:controller)
if options[:network].nil? && options[:controller].match(/^mkp\//).present?
options[:network] = #network.downcase
end
end
super(options)
end
end
I'm trying to create a dynamic interface. Where my model classes exist and my controllers are dynamically created when launching the application.
Everything happens in my routes file where the resources are created!
ActionController::Routing::Routes.draw do |map|
map.namespace :admin do |admin|
TestAdmin.models.each do |m|
admin.resources m.to_s.tableize.to_sym
end
end
end
And then there is my BeAdmin class, this does the following:
module TestAdmin
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def beadmin(options = {})
namespace_name = "Admin"
class_name = "#{self.to_s.pluralize.capitalize}Controller"
klass = namespace_name.constantize.const_set(class_name, Class.new(ApplicationController))
klass.module_eval do
def index
render :text => "test"
end
end
end
end
def self.models
all_models = []
Dir.chdir(File.join(Rails.root, "app/models")) do
Dir["**/*.rb"].each do |m|
class_name = m.sub(/\.rb$/,"").camelize
klass = class_name.split("::").inject(Object){ |klass,part| klass.const_get(part) }
all_models << "#{class_name}" if klass < ActiveRecord::Base && !klass.abstract_class?
end
end
all_models
end
end
And when you now browse to the /admin/users (from the User model) then you get to see "test". so it works great!
But then I just do a simple refresh of the browser and The controller that is called becomes UsersController#index instead of Admin::UsersController#index... He loses it's namespace for some reason...
Maybe another important aspect here is that I added all this as a plugin and user Rails Engines so I can make a plug-able interface...
But so far no luck because my routes seem to get lost somewhere!
Thanks in advance for your help!
Jelle