In my rails application I add an "api" area with controllers
In the route.rb file
I add the area
namespace :api do
#get "dashboard/sales_rate"
end
The controllers Class:
class Api::DashboardController < Api::ApplicationController
before_filter :authenticate_user!
def user_service
render :json => {"user_id" => current_user.id}
end
The Path is:
app/controllers/api/dashboard_controller
My question is if I can that the route take all action
for example /api/dashboard/user_service
and I will not add for each route row on the route.rb page
/api/{controller_under_api_namespace}/{action}
You can do with some meta programming sprinkle!
Api.constants.each |c|
c.action_methods.each do |action|
get [c.controller_name, action].join('/')
end
end
This method limits only to GET request. You can overcome it with RESTful routing.
Api.constants.each |c|
resources c.controller_name.to_sym
end
Hope, that helps. :)
I try add the code on the route.rb file
and I got this error
This is my file
But before trying to fix this part of code, I want to know if it's can change the performance or the calls to those pages?
If it not good for the performance I leave this option.
Related
I am trying to embed a downloadable file in rails. But getting the below error:
ActionView::Template::Error (undefined local variable or method `home_download_pdf_url' for #<#:0x007fd9f1a2eea0>):
home_controller.rb
def download_pdf
send_file(
"#{Rails.root}/public/Brochure.pdf",
filename: "Brochure.pdf",
type: "application/pdf"
)
end
routes.rb
get 'home/download_pdf'
view.html
<%= link_to 'Download Brochure', home_download_pdf_url>
I am new to Ruby. Please help.
Your using action as
download_pdf
so link to can be changed to
link_to "Download Brochure", controller: "home", action: "download_pdf"
If you're using an older Rails, make sure you restart the server after changing the routes. You might also try alternative route syntax get 'home/download_pdf' => 'home#download_pdf', run rake routes to make sure, you should see a line like home_download_pdf GET /home/download_pdf(.:format) home#download_pdf. You can probably also link directly to the file since it's in the public dir link_to 'Download Brochure', 'Brochure.pdf', and it's suspicious that your inspection of the view is #<#:0x007fd9f1a2eea0>, been a while since I looked at rails, but I'd expect it to have a class name there. Usually view files are view.html.erb, not view.html, and that file name name is a bit suspicious, what's the full path to the file from the rails root? I'm expecting something like app/views/home/index.html.erb usually the filename will be in a dir named after the controller (hence home), and the file will be named after the action (controller method that rendered it). There are deviations from these conventions, but I can't tell if yours is one of them.
The error is simple, it means you don't have a route defined with the "name" that you're referencing:
#config/routes.rb
get "home/download_pdf", to: "home#download_pdf", as: :home_download_pdf
#app/controllers/home_controller.rb
class HomeController < ApplicationController
def download_pdf
# ...
end
end
#app/views/home/download_pdf.html.erb
<%= 'Download Brochure', home_download_pdf_path %>
As a tip, we always put "misc" actions in our ApplicationController:
#config/routes.rb
get "download_pdf", to: "application#download_pdf", as: :home_download_pdf
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def download_pdf
# ...
end
end
--
If you have to use a home controller etc, you'll mostly want to embed any extra routes into a resources directive:
#config/routes.rb
resources :home, only: [] do
get :home_download_pdf, on: :collection #-> url.com/home/home_download_pdf
end
I have such method controller:
class Admin::CarManufacturersController < ApplicationController
def edit
#man = Manufacturer.find(params[:id])
render :layout => 'admin'
end
def update
#man = Manufacturer.find(params[:id])
if #man.update_attributes(params[:car_manufacturer])
****
else
render :action => :edit, :layout => 'admin'
end
end
end
and i have such route:
namespace :admin do
resources :car_manufacturers do
###
end
end
and such form partial:
= form_for [:admin, #man] do |f|
###
but when i call this form to edit my data i get:
undefined method `admin_manufacturer_path'
but i need admin_car_manufacturer_path i thing it's becouse i use other model name in controller, but i can't change it... how can i use right pass? i try to write admin_car_manufacturer_path in form, but i think this is bad idea. How to solve my problem?
I would think about renaming your controller/your model to match. Both should either be just manufacturer or car manufacturer. Having the same names for a resource's controller and model will spare you problems like the one you're having right now.
In any case, if you just need a quick fix, you can get around this by specifying the as option for your nested routes like this:
namespace :admin do
resources :manufacturers, as: :car_manufacturers do
###
end
end
Source: Rails Routing from the Outside In - Ruby on Rails Guides - 3.6: Naming Routes
That will turn your path names into admin_car_manufacturer_path etc and should allow you to use your form the way you you intended to. But I really recommend renaming your model and controller so that they match.
I am making a login route and added this to the routes.rb resources :sign_in
I made a controller like this:
class Mobile::Sign_inController < ApplicationController
layout "mobile/application"
def get
respond_to do |format|
format.html
end
end
def index
respond_to do |format|
format.html
end
end
end
and it seems to get routed correctly, but my view file which is located here:
/app/views/mobile/sign_in.html.haml
which just has 1 line for test purposes:
%strong{:class => "code", :id => "message"} Hello Signin!
But when I go to the url: http://m.cmply.local:8800/signin in the browser, the screen is totally white with nothing rendered in the browser.
Any idea why this happens and how to fix it?
Thanks!
A few problems here:
Your controller name should be SignInsController, not Sign_inController. Consider changing your name to UserSessionsController or similar, since that better reflects the resource it represents. You can still specify an alternate name for the URL (such as sign_in).
Why is your controller namespaced under Mobile? Your routes given don't reflect that, but you don't seem to have provided them all. The route should probably be under a scope:
scope :module => "mobile" do
resource :sign_in
end
Since there is only "one" sign in, it should have its route declared resource :sign_in, and probably even resource :sign_in, :only => [:new, :create, :destroy], depending on what you want. This means that the index action no longer exists, and you probably want to replace it with the new action`.
There is no get action by default for RESTful resources, I'm not sure what you meant it to be, but it should be something else.
I am developing a app in ruby on rails for a local business. The pages are 'static', but changeable through a backend CMS I am building for them. Is there a best practice to creating a controller for static pages? Right now I have a sites controller with all static routes, like this.
routes.rb
get "site/home"
get "site/about_us"
get "site/faq"
get "site/discounts"
get "site/services"
get "site/contact_us"
get "site/admin"
get "site/posts"
or would I be better off creating member routes for the site controller like this without the crud, because a 'Site' will not need to have the CRUD.
resources :sites, :except => [:index, :new, :create, :update, :destroy]
member do
get :home
get :about_us
get :faq
get :discounts
get :services
get :contact_us
get :admin
get :posts
end
Or is there a best practice / better way? Any answers would be appreciated. Thanks
If the static pages list are not going to increase, then you can keep the list, but if you want a dynamic list like site/any_new_url , save the routes as
get 'site/:cms_page' => 'cms#show' # all requests matching site/any_page will go CmsController, show method
This will help reduce keep the routes from bloating, but the downside is you do not know what all routes are the valid ones. Your sample code can be
def show
#page_data = Page.find_by_page(:params[:cms_page])
end
show.html.erb
<%= #page_data.html_safe %>
Dunno yet if I consider this a best practice or an abomination but here is what I came up with when tackling the same problem.
My reasoning is that the site was providing some specified functionality (which doesn't really matter for this discussion) + a bunch of information about the organisation itself (about us, contact, FAQ, homepage blurb, whatever). Since all that data was really related to the organisation, an Organisation model seemed reasonable with each of those things as attributes. Here is the model:
class Organisation < ActiveRecord::Base
...validations stuff...
def self.attrs_regex
Regexp.new(self.attrs.join("|"))
end
def self.attrs
self.column_names.reject{|name| name =~ /id|created_at|updated_at/}
end
end
Then I use the attrs class method to generate routes based on the columns. This is in my routes.rb:
Organisation.attrs.each do |attr|
get "#{attr}" => "organisation##{attr}", :as => attr.to_sym
get "#{attr}/edit" => "organisation#edit", :as => "#{attr}_edit".to_sym, :defaults => { :attribute => attr }
post "#{attr}" => "organisation#update", :as => :organisation_update, :defaults => { :attribute => attr}, :constraints => Organisation.attrs_regex
end
The controller gets a little weird and I am not thrilled with the code here but here it is anyway. I need to make sure the attribute is set and available to the views so I can do the right thing there so I set it in the application controller:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :set_attribute
def set_attribute
#attribute = action_name.parameterize
end
end
For the organisation controller I just set the #organisation variable to be the first and only row in the database in the before_filter and then let Rails do its usual magic of calling the method, failing, and rendering a view of the same name. The edit action just uses one view file to edit all the different attributes:
class OrganisationController < ApplicationController
before_filter :set_organisation
def edit
authorize! :edit, #organisation
#attribute = params[:attribute].parameterize
end
def update
authorize! :update, #organisation
#attribute = params[:attribute]
respond_to do |format|
if #organisation.update_attributes(params[:organisation])
format.html do
redirect_to "/#{#attribute}", notice: t('successful_update')
end
format.json { head :ok }
else
format.html { render action: "edit" }
end
end
end
private
def set_organisation
#organisation = Organisation.first
end
end
So that is where I ended up. Like you I hit up SO to tap into the seething mass of genius here but ended up with disappointing results. If there is something better out there I am still hoping to find it.
What I like about what I did is that routes are automatically generated based on the structure of the organisation table.
What I don't like about what I did is that routes automatically generated based on the structure of the organisation table.
I know I will pay for that design decision when I have to deal with i18n routing and there are probably a thousand other reasons that this is a bad idea that I have yet to discover but for the moment I have a happy client.
In the end this is not a suggestion that you should do this, but I am hoping to give you more than I got so you can advance your thinking on this and hopefully end up a little closer to that best practice.
If you are going to construct a CMS, which likely connects to a database, and allow your customer to change the text on the pages of their site, I would not recommend using static pages. In Rails terms, a static page would refer to creating html files in your /views/pages directory. If you go this route, then you're walking outside of the way that Rails was designed.
I believe that what you want to do is create tables in the database that correspond to and store the data for your posts, etc. You can pull information into the controller from the model that it corresponds to and then user a view to display the data. You can create a layout for these pages and then create controllers for each of the pages that you add.
As far as routes, I would recommend using the following:
map.resource :controller_name
you then would add the code that displays the information from the CMS in the corresponding show controller action and view for each page.
In Ruby on Rails, is it possible to change a default action for a RESTful resource, so than when someone, for example, goes to /books it gets :new instead of the listing (I don't care if that means not being able to show the listing anymore)?
I'd point out that if you are pointing /books to /books/new, you are going to be confusing anyone who is expecting REST. If you aren't working alone, or if you are and have other come on board later, or if you expect to expose an API to the outside, the REST convention is that /books takes you to a listing, /books/new is where you create a new record.
Not sure why would you do such a thing, but just add this
map.connect "/books", :controller => "books", :action => "new", :conditions => { :method => :get}
to your config/routes.rb before the
map.resources :books
and it should work.
Yes. You should be able to replace your index method in your controller...
def index
#resource = Resource.new
# have your index template with they proper form
end
In the same vein, you can just do
def index
show
end
def index
redirect_to new_book_path
end
I think would be the simplest way.