Rails 3 - Restricting formats for action in resource routes - ruby

I have a resource defined in my routes.
resources :categories
And I have the following in my Category controller:
def show
#category = Category.find(params[:id])
respond_to do |format|
format.json { render :json => #category }
format.xml { render :xml => #category }
end
end
The controller action works fine for json and xml. However I do NOT want the controller to respond to html format requests. How can I only allow json and xml? This should only happen in the show action.
What is the best way to achieve this?
Also is there any good tips for DRYing up the respond_to block?
Thanks for your help.

I found that this seemed to work (thanks to #Pan for pointing me in the right direction):
resources :categories, :except => [:show]
resources :categories, :only => [:show], :defaults => { :format => 'json' }
The above seems to force the router into serving a format-less request, to the show action, as json by default.

You must wrap those routes in a scope if you want to restrict them to a specific format (e.g. html or json). Constraints unfortunately don't work as expected in this case.
This is an example of such a block...
scope :format => true, :constraints => { :format => 'json' } do
get '/bar' => "bar#index_with_json"
end
More information can be found here: https://github.com/rails/rails/issues/5548
This answer is copied from my previous answer here..
Rails Routes - Limiting the available formats for a resource

You could do the following in your routes.rb file to make sure that only the show action is constrained to json or xml:
resources :categories, :except => [:show]
resources :categories, :only => [:show], :constraints => {:format => /(json|xml)/}
If this doesn't work you could try explicitly matching the action:
resources :categories, :except => [:show]
match 'categories/:id.:format' => 'categories#show', :constraints => {:format => /(json|xml)/}

constraints was not working for POST requests and then I tried defaults it works for all.
namespace :api, :defaults => { :format => 'json' } do
namespace :v1 do
resources :users do
collection do
get 'profile'
end
end
post 'signup' => 'users#create'
post 'login' => 'user_sessions#create'
end
end
I was using Rails 4.2.7

Related

How to cache index page with pagination?

Suppose this my one of admin model
ActiveAdmin.register Theme do
menu :if => proc{ current_admin_user.super_admin?}
after_filter :only => [:create, :update, :destroy] do
expire_action :action => :show
expire_action :action => :index
end
controller do
caches_action :index, :show
end
end
with this code caching is done, but on index page with pagination i am facing issue, that is i am not able to visit another page of Theme.
How to implement something like this
https://github.com/amatsuda/kaminari#creating-friendly-urls-and-caching
this is what fixed the issue:
caches_action :index, :cache_path => Proc.new { |c| c.params }
This will generate new cache for specific paginate param's
Read More

Testing custom routes in rails 3.0.1 does not work, or is it me?

For some reason when I run this functional test
require 'test_helper'
class ListControllerTest < ActionController::TestCase
test "should get mylist" do
post :mylist, :format => :json
assert_response :success
end
end
routes.rb
SomeApplication::Application.routes.draw do
match "/mylist" => "list#mylist", :method => "POST"
end
list_controller.rb
class ListController < ApplicationController
def mylist
respond_to do |format|
format.json { render :json => []}
end
end
end
Sourcecode as a gist
I get this error:
1) Error:
test_should_get_mylist(ListControllerTest):
ActionController::RoutingError: No route matches {:controller=>"list", :format=>:json, :action=>"mylist"}
/test/functional/list_controller_test.rb:6:in `test_should_get_mylist'
Any ideas?
Regards,
Michal
OK. I got it. Those stupid errors are the most difficult to spot. Sometimes I cry for ruby to have strong typing ;)
the problem is in the routes.rb. Instead of:
match "/mylist" => "list#mylist", :method => "POST"
it should have been
match "/mylist" => "list#mylist", :via => :post
Thanks everyone who tried to help me.

error to customize error 404 rails 3.1 with hight_voltage gem

Hi guys I remove /page from high_voltage gem with this answer.
Remove page/ of High Voltage for statics page rails
I have in my routes for high_voltage this:
match '/:id' => 'high_voltage/pages#show', :as => :static, :via => :get
For maintenance page 404 in rails 3.1 I follow this fix http://techoctave.com/c7/posts/36-rails-3-0-rescue-from-routing-error-solution with errors_controller.rb with the next code:
def routing
render :file => "#{Rails.root}/public/404.html", :status => 404, :layout => false
end
Then I add to routes.rb the next code for maintenance page 404 in rails
match '*a', :to => 'errors#routing'
The problem is that if I put in browser www.mydomain.com/sdfs dont working 404 system error and show No such page: sdfs
but however if I put www.mydomain.com/a_controller/action/sdfs yes working fine the fix for error 404 page.
I think that problem is my routes.rb
I solved this problem by extending the HighVoltage::PagesController and modifying the error catching:
class PagesController < HighVoltage::PagesController
rescue_from ActionView::MissingTemplate do |exception|
render_not_found
end
end
In my case though, my 404 function resides in my application controller so that it can easily be called from any location. If you make the same change, you will also need to update your route:
match '/:id' => 'pages#show', :as => :static, :via => :get
Thank you kevinthopson for mi this dont working fine :(.
I have in my routes.rb:
match '/:id' => 'pages#show', :as => :static, :via => :get
I have added this in pages_controller.rb
class PagesController < HighVoltage::PagesController
rescue_from ActionView::MissingTemplate do |exception|
render_not_found
end
end
I have added this code to aplication_controller.rb:
def render_not_found
render :file => "#{Rails.root}/public/404.html", :status => 404, :layout => false
end
Working fine if you put now:
localhost:3000/dfadsfadsf
The problem now is that if you put for example that routes in navigation bar:
localhost:3000/users_or_static_page/asdfadfadfa
Dont working for me :(.

Rails 3: update method redirection problem

Trying to build a CMS for a blog using rails 3.
In my routes.rb...
namespace :admin do
resources :posts
root :to => "home#index"
end
In Admin::PostsController...
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to(#post,
:notice => 'Post was successfully updated.')}
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #post.errors,
:status => :unprocessable_entity }
end
end
end
I had to change the first line of admin/_form.html.erb due to a previous 'undefined method' error that was driving me crazy. Was trying to point the browser to a nonexistent "post_path".
<%= form_for(#post, :url => admin_posts_path(#post)) do |f| %>
All other methods for posts are working as expected. Upon form submission (update) - the rails server...
Started POST "/admin/posts.1"
ActionController::RoutingError (No route matches "/admin/posts.1"):
First, curious as to why it is using POST instead of PUT for the update.
Second, I can't figure out why the URL is being interpreted as "/admin/posts.1" and how to fix it.
Has anyone else run into this problem? (and yes, I am following the rubyonrails.org guides closely to help me). Any help would be greatly appreciated.
EDIT:
Changed admin_posts_path(#post) to admin_post_path(#post) per theIV.
the rails server...
NoMethodError (undefined method 'post_url' for #<Admin::PostsController:0x00000102b26ff8>):
app/controllers/admin/posts_controller.rb:55:in 'block (2 levels) in update'
app/controllers/admin/posts_controller.rb:53:in 'update'
I believe you should be hitting admin_post_path(#post), not admin_posts_path(#post).
Look at the table that lists all of the helpers created for your routes on guides.rubyonrails.org.
EDIT: Also, have you tried the array style of urls? It's pretty convenient.
<%= form_for([:admin, #post]) do |f| %>
EDIT 2: My guess as to "undefined method post_url" is from your update action here:
format.html { redirect_to(#post,
:notice => 'Post was successfully updated.')}
It needs to be namespaced as well:
format.html { redirect_to([:admin, #post],
:notice => 'Post was successfully updated.')}

ActionMailer 3 without Rails

I'm writing a small Ruby program that will pull records from a database and send an HTML email daily. I'm attempting to use ActionMailer 3.0.3 for this, but I'm running in to issues. All the searching I've done so far on using ActionMailer outside of Rails applies to versions prior to version 3. Could someone point me in the right direction of where to find resources on how to do this? Here's where I am so far on my mailer file:
# lib/bug_mailer.rb
require 'action_mailer'
ActionMailer::Base.delivery_method = :file
class BugMailer < ActionMailer::Base
def daily_email
mail(
:to => "example#mail.com",
:from => "example#mail.com",
:subject => "testing mail"
)
end
end
BugMailer.daily_email.deliver
I'm definitely stuck on where to put my views. Every attempt I've made to tell ActionMailer where my templates are has failed.
I guess I should also ask if there's a different way to go about accomplishing this program. Basically, I'm doing everything from scratch at this point. Obviously what makes Rails awesome is it's convention, so is trying to use parts of Rails on their own a waste of time? Is there a way to get the Rails-like environment without creating a full-blown Rails app?
After some serious debugging, I found how to configure it.
file mailer.rb
require 'action_mailer'
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "domain.com.ar",
:authentication => :plain,
:user_name => "test#domain.com.ar",
:password => "passw0rd",
:enable_starttls_auto => true
}
ActionMailer::Base.view_paths= File.dirname(__FILE__)
class Mailer < ActionMailer::Base
def daily_email
#var = "var"
mail( :to => "myemail#gmail.com",
:from => "test#domain.com.ar",
:subject => "testing mail") do |format|
format.text
format.html
end
end
end
email = Mailer.daily_email
puts email
email.deliver
file mailer/daily_email.html.erb
<p>this is an html email</p>
<p> and this is a variable <%= #var %> </p>
file mailer/daily_email.text.erb
this is a text email
and this is a variable <%= #var %>
Nice question! It helped me to understand a bit more how Rails 3 works :)
It took me a while to get this to work in (non-)Rails 4. I suspect it's just because I have ':require => false' all over my Gemfile, but I needed to add the following to make it work:
require 'action_view/record_identifier'
require 'action_view/helpers'
require 'action_mailer'
Without the above code, I kept getting a NoMethodError with undefined method 'assign_controller'.
After that, I configured ActionMailer as follows:
ActionMailer::Base.smtp_settings = {
address: 'localhost', port: '25', authentication: :plain
}
ActionMailer::Base.default from: 'noreply#example.com'
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.logger = Logger.new(STDOUT)
ActionMailer::Base.logger.level = Logger::DEBUG
ActionMailer::Base.view_paths = [
File.join(File.expand_path("../../", __FILE__), 'views', 'mailers')
# Note that this is an Array
]
The templates go in lib/<GEM_NAME>/views/mailers/<MAILER_CLASS_NAME>/<MAILER_ACTION_NAME>.erb (MAILER_ACTION_NAME is the public instance method of your mailer class that you call to send the email).
Lastly, don't forget to put this in your spec_helper:
ActionMailer::Base.delivery_method = :test

Resources