Wrong naming convention? - ruby-on-rails

I've never used Unit Test before but only Rspec. So maybe here's some silly mistake.
I have CountriesController:
class CountriesController < ApplicationController
def create
#country = Country.new(params[:country])
respond_to do |format|
if #country.save
format.html { redirect_to(#country, :notice => 'Country was successfully created.') }
format.xml { render :xml => #country, :status => :created, :location => #country }
else
format.html { render :action => "new" }
format.xml { render :xml => #country.errors, :status => :unprocessable_entity }
end
end
end
end
and test countries_controller_test.rb for it :
class CountriesControllerTest < ActionController::TestCase
should_not_respond_to_actions :new => :get, :destroy => :get
setup do
#country = countries(:one)
end
test "should create country" do
assert_difference('Country.count') do
post :create, :country => #country.attributes.merge({ :code => Time.now.to_s })
end
assert_redirected_to country_path(assigns(:country))
end
...
end
As far as I know the name convention, everything looks ok for me but I got an error:
1) Error:
test_should_create_country(CountriesControllerTest):
RuntimeError: #controller is nil: make sure you set it in your test's setup method.
What might be a problem here? Thanks

Where is the test's #controller supposed to come from ? If it's created by ActionController::TestCase, then you might want to call the superclass's setup in your own setup function ?

Related

Elasticsearch::Transport::Transport::Errors on Heroku with ActiveAdmin, SearchKick and SearchBox

I have a Rails App with a Post Model and Controller and I'm using ActiveAdmin for CMS. I have implemented ElasticSearch and SearchKick and am now attempting to deploy to Heroku using SearchBox.
The app runs on local no issues and the majority of the functionality works on Heroku but I am getting a very annoying error when I Update or Create Post in Active Admin.
Elasticsearch::Transport::Transport::Errors::NotFound in
Admin::PostsController#update [404]
{"error":{"root_cause":[{"type":"document_missing_exception","reason":"[post][11]:
document
missing","index":"posts","shard":"0"}],"type":"document_missing_exception","reason":"[post][11]:
document missing","index":"posts","shard":"0"},"status":404}
Even though it is throwing this error the Post is still either Updating or Creating fine. If I refresh the page it resolves to the view all posts screen in ActiveAdmin as expected. The search functionality is fully operational on the front end.
In SearchBox the ElasticSearch index is named posts_production_20160220081603930. Can't work out how to make ActiveAdmin see it. The Post Model sees it and I am able to search as expected.
Post Controller...
class PostsController < ApplicationController
before_filter :find_post, :only => [:show, :edit, :update, :destroy]
def index
#post = Post.all
if params[:q].present?
#postsearch = Post.search params[:q], fields: [:title, :body], operator: "or", suggest: true
end
end
def show
if params[:q].present?
#postsearch = Post.search params[:q], fields: [:title, :body], operator: "or", suggest: true
else
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #post }
end
end
end
def create
#post = Post.new(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to(#post, :notice => 'Post was successfully created.') }
format.json { render :json => #post, :status => :created, :location => #post }
else
format.html { render :action => "new" }
format.json { render :json => #post.errors, :status => :unprocessable_entity }
end
end
end
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #post }
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
flash[:notice] = 'Post was successfully updated.'
format.html { redirect_to(#post) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #post.errors,
:status => :unprocessable_entity }
end
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to(posts_url) }
format.xml { head :ok }
end
end
private
def find_post
#post = Post.find(params[:id])
end
end
Post Model
require 'elasticsearch/model'
class Post < ActiveRecord::Base
searchkick suggest: [:title]
#add attachement declaration to moidels for refile image uploading
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
validates_presence_of :title, :body
attachment :profile_image
attachment :image
end
ActiveAdmin Post
ActiveAdmin.register Post do
# See permitted parameters documentation:
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
permit_params :title, :body, :profile_image, :image
form do |f|
inputs 'Details' do
input :title
input :body, :input_html => {:class => "redactor"}
input :profile_image, :required => false, :as => :file, destroy: false, :direct => true
input :image, :required => false, :as => :file, destroy: false, :direct => true
actions
end
end
end
To create the original index I ran
heroku run rake searchkick:reindex CLASS=Post
In dev the index gets updated automatically but in prod I have to reindex manually. Haven't setup sidekiq yet.
Any help would be greatly appreciated.
Am going a bit mad.
Cheers
Dan
Solved issue...
I had used Searchkick to create and index however quirkily it would appear that an index also needs to be created using Post.elasticsearch.create_index! force: true ie the non Searchkick command.
So the indices in Searchbox are
posts
and
posts_production
All fully operational.

auto-increment text_field number rails 3.2.6

i'v been researching trying to find the answer for this, but am struggeling to work it out. i have a booking_no text_field which i want to be automatically set when a user make a new booking through booking/new. i would like it to be an autonumber which just counts up by 1 evertime starting with 100.
I know it is probably easiest to do this in the model but i'm not sure how.
my booking.rb:
(i havent set the validates yet)
class Booking < ActiveRecord::Base
attr_accessible :booking_no, :car_id, :date, :user_id
belongs_to :car
belongs_to :user
end
EDIT for comment:
#error ArgumentsError in booking_controller#create
wrong number of arguments (1 for 0)
my booking_controller#create
def create
#booking = Booking.new(params[:booking])
respond_to do |format|
if #booking.save
format.html { redirect_to #booking, :notice => 'Booking was successfully created.' }
format.json { render :json => #booking, :status => :created, :location => #booking }
else
format.html { render :action => "new" }
format.json { render :json => #booking.errors, :status => :unprocessable_entity }
end
end
end
It's probably best if you set the booking_no as auto-increment field in the Database table itself..
Otherwise to manage it in your model, you can proceed something like:
before_create :increment_booking_no
def increment_booking_no
self.booking_no = (self.class.last.nil?) ? "0" : ((self.class.last.booking_no.to_i) + 1).to_s
end

Having problems creating a Renew action and view in Rails3

please can somebody help me with this .i want to create a renew link which will update some of the fields in a table called members,am using rails 3 and i have created my action and the corresponding view but i still have an error that states
"undefined method'renew_member_path' for #<#:0xb66bcae0>"
below is the action i created in the members_controller
Class MembersController
def renew
#member = Member.find(params[:id])
respond_to do |format|
if #member.renew_attributes(params[:member])
format.html { redirect_to(#member, :notice => 'Member was succesfully Renewed.'}
format.xml {head :ok }
else
format.html { render :action => 'renew'}
format.xml { render :xml => #member.errors, :status => :unprocessable_entity}
end
end
end
I created a view called renew.html.erb
Your route is not set. You need to update your routes.rb file to something like this:
match 'members/renew' => 'members#renew', :as => :renew_member

ActiveResource error handling

I have been searching for a while and yet I am not able to find a satisfactory answer as yet. I have two apps. FrontApp and BackApp. FrontApp has an active-resource which mimics a model in BackApp. All the model level validations live in BackApp and I need to handle those BackApp validations in FrontApp.
I have following active-resource code:
class RemoteUser < ActiveResource::Base
self.site = SITE
self.format = :json
self.element_name = "user"
end
This mimics a model which is as follows
class User < ActiveRecord::Base
attr_accessor :username, :password
validates_presence_of :username
validates_presence_of :password
end
Whenever I create a new RemoteUser in front app; I call .save on it. for example:
user = RemoteSession.new(:username => "user", :password => "")
user.save
However, since the password is blank, I need to pass back the errors to FrontApp from BackApp. This is not happening. I just don't understand how to do that successfully. This must be a common integration scenario; but there doesn't seem to be a good documentation for it?
My restful controller that acts as a proxy is as follows:
class UsersController < ActionController::Base
def create
respond_to do |format|
format.json do
user = User.new(:username => params[:username], :password => params[:password])
if user.save
render :json => user
else
render :json => user.errors, :status => :unprocessable_entity
end
end
end
end
end
What is it that I am missing? Any help will be much appreciated.
Cheers
From rails source code I figured out that the reason ActiveResource didn't get errors was because I wasn't assigning errors to "errors" tag in json. It's undocumented but required. :)
So my code should have been:
render :json => {:errors => user.errors}, :status => :unprocessable_entity
In the code:
class UsersController < ActionController::Base
def create
respond_to do |format|
format.json do
user = User.new(:username => params[:username], :password => params[:password])
if user.save
render :json => user
else
render :json => user.errors, :status => :unprocessable_entity
end
end
end
end
end
try to replace
user = User.new(:username => params[:username], :password => params[:password])
with
user = User.new(params[:user])
Your active-resource model pass the params like the hash above:
:user => { :username => "xpto", :password => "yst" }
This solution worked for me: https://stackoverflow.com/a/10051362/311744
update action:
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json {
render json: #user.errors, status: :unprocessable_entity }
end
end
end
Calling controller:
#remote_user = RemoteUser.find(params[:id])
if (#remote_user.update_attributes(params[:remote_user]))
redirect_to([:admin, #remote_user], notice: 'Remote user was successfully updated.')
else
flash[:error] = #remote_user.errors.full_messages
render action: 'edit'
end

render :json does not accept options

I'd love to use render :json but it seems its not as flexible. Whats the right way to do this?
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #things }
#This is great
format.json { render :text => #things.to_json(:include => :photos) }
#This doesn't include photos
format.json { render :json => #things, :include => :photos }
end
I've done something similar with render :json. This is what worked for me:
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #things.to_json(:include => { :photos => { :only => [:id, :url] } }) }
end
I guess this article can be useful for you - Rails to_json or as_json? by Jonathan Julian.
The main thought is that you should avoid using to_json in controllers. It is much more flexible to define as_json method in your model.
For instance:
In your Thing model
def as_json(options={})
super(:include => :photos)
end
And then you can write in your controller just
render :json => #things
Managing complex hashes in your controllers gets ugly fast.
With Rails 3, you can use ActiveModel::Serializer. See http://api.rubyonrails.org/classes/ActiveModel/Serialization.html
If you're doing anything non-trivial, see
https://github.com/rails-api/active_model_serializers. I recommend creating separate serializer classes to avoid cluttering your models and make tests easier.
class ThingSerializer < ActiveModel::Serializer
has_many :photos
attributes :name, :whatever
end
# ThingsController
def index
render :json => #things
end
# test it out
thing = Thing.new :name => "bob"
ThingSerializer.new(thing, nil).to_json
format.json { render #things.to_json(:include => :photos) }
in case of array what I done is
respond_to do |format|
format.html
format.json {render :json => {:medias => #medias.to_json, :total => 13000, :time => 0.0001 }}
end

Resources