No route matches [GET] "/zombie" - ruby-on-rails

Earlier it was working fine. I don't know what happen but I get this error now.
Rails.root: /Users/abhimanyuaryan/RubymineProjects/TwitterBy

The path in the error message is "/zombie" but all of your paths
use "/zombies"
you might want to modify the various id paths /zombies/:id(.format) to
be /zombie/id(.format). that's matches rails way of doing thing.
hth

As mentioned in the answer, your problem is that you're trying to access /zombie when the routes are either /zombies or /zombie/:id.
I wanted to add that if you're a beginner, the routes system can seem a little confusing...
The way to understand it is that Rails catches URL routes you send it. Rails is not magic, it's built on top of the HTTP protocol, and as such you can only send urls to your app, such as /zombies or /zombie/:id
Rails uses the ActiveDispatch middleware to take the URL's coming to the app, and routing them to a controller/action, where your code resides. Rails then takes the rendered HTML from your code and returns it to the browser, allowing the user to interact with their data etc.
The important thing to note is that Rails can only work with what you send it.
The Routes documents are a good step on seeing how this works; ultimately, you have to understand that you're responsible for sending the right URL's to rails, which can be achieved quite simply with the path helpers.
Objects
Finally, I also wanted to showcase something else - object orientation.
Rails is built on Ruby, which makes both of them object orientated. This is a programming pattern made popular with video games.
The counter to object orientated programming is flow based programming, which puts the flow of an application at the center of design. Typical "native" apps are flow-based, whilst games are object orientated.
The technical difference between the two is that object orientated programs store a series of "objects" (variables) in memory, allowing the user to "interact" with them.
Flow based design may keep just as much data in memory, but will only let the user access it through certain flow interactions. The best example of this would be the likes of setup/installation applications.
Anyway, because Ruby is object orientated, Rails has been designed to be such as well. Once you understand this, everything becomes much simpler.
Instead of thinking of Rails as controllers/variables/data, you want to think in terms of objects -- which object am I interacting with?
This is why most of Rails is built in a certain way -- to make the manipulation of objects work much smoother:
#config/routes.rb
resources :zombies #-> provides routes to interact with Zombie objects
#app/controller/zombies_controller.rb
class ZombiesController < ApplicationController
def index
#zombies = Zombie.all #-> show ALL zombie objects
end
def show
#zombie = Zombie.find params[:id] #-> find a single zombie object
end
def new
#zombie = Zombie.new #-> new zombie object
end
def create
#zombie = Zombie.new zombie_params
#zombie.save #-> save the new Zombie object
end
private
def zombie_params
params.require(:zombie).permit(:zombie, :params)
end
end
#app/models/zombie.rb
class Zombie < ActiveRecord::Base
has_many :enemies #-> each zombie object has many enemies
end
See how it all fits together?
If you focus on the object rather than the flow, it becomes much simpler.

Related

Should this be a lone Model, a Model and Controller, or some other Ruby class entirely?

Currently in my app a QuoteRequest has_one Quote which belongs_to a QuoteRequest. QuoteRequest has full MVC, i.e. QuoteRequest#new view enables user to create and persist the object and its data to a QuoteRequest table in the db.
I'm now working out how to design the next stage, that should be;
when a QuoteRequest is created it should kick off the application crawling to an external site
crawling and scraping to get the quote results using the QuoteRequest data, persisting that result to the app’s db.
then rendering a view of that persisted quote data.
As a newbie I’m struggling to decide how best to design and write this. I believe I understand the general MVC standard, of a C serving the user a V, that V capturing something from the user and the C then taking that something and sending it to the M to persist it into the db. But I'm not unsure how anything other than something with this defined MVC relationship would fit into the Rails environment.
In my next stage after QuoteRequest is created there’s a part of the process that doesn’t need a view, ie once the QuoteRequest data is persisted to the db it needs to kick off something in the app, currently Quote though no functionality written in Quote yet, that goes out
crawls, scrapes and saves, then we’re back to needing a view for that saved scrape to be rendered.
So I’m wondering whether this ‘non view requiring’ stage of the process ought to be neither a model or a controller, rather some type of standard Ruby class. E.g. flow as below(pls excuse strange 'pseudo code'!):
On successful QuoteRequest.save >> OtherClass.start_crawl >> on OtherClass.crawl_success >> save as a Quote.create (no view) >> Quote.show(OtherClass.crawl_sucess_result) view >> Done.
Can anyone help me out with making decisions about how to design this, I guess pretty simple, pattern. Thanks
I'm trying to use your "pseudo code" and combine controller and PORO (plain Old Ruby Object), below some tips for your case
class QuoteRequestsController < ApplicationController
def new
#quote_request = QuoteRequest.new
end
def create
#quote_request = QuoteRequest.new(quote_request_params)
if #quote_request.save
flash[:success] = "QuoteRequest successful save"
# contact other class
#crawling_service = MyModuleService::Other.new(#quote_request)
#crawling_service.start_crawl
if #crawling_service.crawl_result # if success
# create your quote
#quote = #quote_request.create_quote(arg1, arg2, etc)
#quote.save
# after save redirect_to quote show
redirect_to quote_path(#quote)
end
else
flash[:error] = #barang.errors.full_messages[0]
end
end
end
create PORO as services in rails
create app/services folder, then you can create one file
in this folder with name for example my_module_service.rb
module MyModuleService
attr_reader :crawl_result
class Other
def initialize(quote_request)
#quote_request = quote_request
end
def start_crawl
# your start crawl process
if success
crawl_result = true
# this for send message back whether success or not the crawling
else
crawl_result = false
end
end
end
end
As I look at it, I feel like the crawling should be a background task so it doesn't hog up processes.
Add after_save in the QuoteRequest model (or you could also just invoke it in your controller)
Create an empty Quote object perhaps
Use a background-task library like resque or sidekiq.
Write a worker (activejob) that does the crawl and updates the Quote object above with the results.)
The view of the quote should show that it's processing at the time when it's not yet crawled.

Rails Thread.current[] & thread safety

So there I was, right. Just looking through some code, studying bits and pieces when all of a sudden, my ocular receptors were assaulted by the unfamiliar. I was like:
What!!! What's that all about!
Anyway, what I saw was (source):
def authenticate_user!
if doorkeeper_token
Thread.current[:current_user] = User.find(doorkeeper_token.resource_owner_id)
end
# ...
end
So after looking at it for a while, thinking:
Wtf is this Thread.current[] insanity? Is this even necessary? What's it even trying to do?
It seemed to me it was kind of like wearing a baseball cap backwards: You may look pretty f'ing cool but that sun glare is winning. I then decided to Google around, read some articles and some SO.
None seemed to concisely answer my question: Given the context of the code, would it not be the same as:
def authenticate_user!
if doorkeeper_token
#current_user = User.find(doorkeeper_token.resource_owner_id)
end
# ...
end
If not, what situation/scenario is it useful/protecting against?
I hope you enjoyed my story and want to contribute an awesome ending.
There are different bulletin boards on which you can pin information. The bulletin board where local variables are posted is hidden behind hedges and cannot be seen by the views who live in the next yard:
current_user = User.find(doorkeeper_token.resource_owner_id)
The bulletin board where #variables are posted is nailed to the top of a ladder, so the views have an unobstructed view of the #variables over the tops of the hedges:
#current_user = User.find(doorkeeper_token.resource_owner_id)
But other methods, which live in classes across the street, cannot see the #variables posted on the bulletin board on top of the ladder because a row of trees is in the way.
Thread variables, such as:
Thread.current[:current_user] = User.find(doorkeeper_token.resource_owner_id)
launch a kite, which flies higher than the trees, and the variables posted on the kite can be seen by the methods that live across the street.
Why not create a ruby global variable, e.g. $current_user, instead? Because then requests initiated simultaneously by different users will write to the same global variable, potentially screwing things up.
Given the context of the code
There's not enough context to tell why a (thread) global variable is needed.
From the author:
I use Thread to store current user to be able transparently
authenticate user and extend this later. Currently this code gives
priority to token-based authentication via Doorkeepr, and you can
extend it to any other algorithm. I am not a big fan of Devise and did
not want to use the token-based authentication strategy it provides.
Once you write user info inside Thread.currrent[:current_user], any
other service can read it independently and use for whatever purposes
it is needed. For example, as i mentioned above, checking
authorization, logging who did the events happening in the system, etc
as for writing it to #current_user, i am not sure it will be
accessible in all contexts. But i have not really checked this
Reference: https://github.com/rilian/devise-doorkeeper-cancan-api-example/issues/1#issuecomment-143479288

Unable to change the parameter from id to a custom variable in Rails

I've been racking my brain trying to figure out something that should be extremely simple, so I'm sure I'm just overlooking something and a fresh set of eyes might be useful since all my code is seemingly blurring together. I'm attempting to create vanity URLS for a site that allows users to create categories and then post relevant stories based on those categories. So, for example, I would like users to access /categories/movies in order to view the movie section. If I set it up to use the category id, /categories/1, it works no problem. For whatever reason, rails keeps trying to use the id parameter to find the category as opposed to the title parameter. I'm using Ruby 2.0.0 and Rails 4.0. I've read that the "find_by" method will become deprecated soon, so if there's a better way to handle this, that'd be great. Here's the relevant code:
Categories Controller
def show
#categories = Category.find_by_title(params[:title])
#category = Category.find_by_title(params[:title])
#posts = Post.where(category: set_category).all
end
Routes.rb
resources :categories
get "/categories/:title" => "categories#show"
Terminal readout when rendering page
Processing by CategoriesController#show as HTML
Parameters: {"id"=>"Movies"}
Just to reiterate, the parameters should read {"title"=>"Movies"} not id. Like I said, I'm sure it's something extremely simple that I've overlooked. Any help would be appreciated. Thanks.
I had to implement vanity urls as well and followed this blog post/tutorial
You pretty much create a slug in your model with the vanity-url, so
class Category < ActiveRecord::Base
def slug
title.downcase.gsub(" ", "-")
end
def to_param
"#{slug}"
end
end
Your show action in your controller would use the find_by_slug method
I think there is a gem that does this as well called friendly_id and here is a railscast but I have not personally used it
Hope this helps

Forms for polymorphically associated resources where a basic resource path "/resource" does not exist

I have a polymorphic resource Location that can latch on to, let's say, instances of Store. The extent to which this "should" be a polymorphic resource is questionable, but that's besides the point at the moment.
A location accesses its polymorphic parent via location.locatable.
Since the location will always be the child of a resource like a store, I'd like to remove the route to POST /locations and instead have the application direct POST requests to /stores/1/locations.
Now, the default Rails method when it comes to dealing with polymorphic associations is to do it at the controller level with
def new
#location = Store.find(params[:store_id]).vendors.new
end
This, as expected, prepopulates location.locatable_id and location.locatable_type. Wonderful. But it still routes to locations_path by default, which I would like to get rid of.
And I try, it raises a route not found error.
So how can I prepare a general location form that is extensible to new parents?
I have come to the following:
form_for(#location, :url => [#location.locatable, #location]) do |l|
Which seems to work fine, but the passing of a path as an array irks me, and for some reason I can't find any documentation on the subject. Is there a better way to accomplish this? I'm new-ish to polymorphic resources, and it would be nice to do this right from the start.
Also, a (quite) minor peripheral issue is that this doesn't cooperate out of the box with the default RSpec-generated view spec since Rails actually tries to find #location.locatable. This is fairly easy to get around though. I was planning on rewriting the view spec from top to bottom anyway.

Rails: Mimic relations in tableless activerecord

I'm using the BaseWithoutTable plugin to extend ActiveRecord. This allows me to create models without underlying tables (I'm getting data from a webservice). I would like my web application to remain restful, however i'm stumped on how to do that without relations.
To be more concrete, let's say I have a book model and an author model and I get both resources from a web service. I would like to access book resources like /authors/1/books.
It seems there could be two routes I could choose. First, hack the relations (belongs_to, has_many) so that I can define my own without the need for foreign keys. Second, I could possibly build custom routes and controller methods that allow me to access the previous url.
If anyone has any thoughts on how to do this I would much appreciate it.
Thanks and let me know if you need more info.
For the url given you could do the something like the following.
/authors/1/books
class Books < ApplicationController
before :find_author
def show
#books = Books.get_from_web_service_for_author(#author)
end
def find_author
#author = params[:author_id]
end
end
You would need to define the method for accessing your webservice and also have a nested resource defined in your routes.

Resources