I've got the following problem
I have a model called Article, which I access at two points.
First at the "home-page ( root )" I just do Article.all and list all of them.
That works fine for me, but whenever I access Article.all on my admin-panel ( /admin/articles ) it just says the following:
My controller looks like this:
def index
#news = Article.all
end
My model can be accessed easily in the rails console:
All of this is somehow solved by opening the controller and just re-saving it.
After a rails restart or logout and login on the site it is broken again
You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an
Admin:: namespace.
At the console:
namespace :admin do
resources :articles
end
This will create a number of routes for each of the articles
use one of the routes to access your controller from Admin
Try converting to array,
#news.to_a.count
Related
Issue: When a user (when signed in) creates an order, they are sent to the OrderControllers show page which can only be accessed if signed in by both the buyer and seller. From here they can edit/update their order, etc.
We also have guest_user, someone who isn't signed in, and for them I need a order confirmation in the browser (I'm using Devise gem)
I have created a method:
def order_confirmation
In the OrdersController.
Although, how can I nest this within orders so the page knows which order to show.
Is this possible to nest methods under its' own controllers, or should i just create a small controller only for order confirmations?
For example: example.com/orders/1/order-confirmation
Maybe there are better ways to go about this other than just nesting and creating a controller?
I Tried:
resources :orders do
collection do
get 'order_confirmation'
end
end
With:
def order_confirmation
#order = Order.all.find(params[:id])
end
But it won't work how i want i t seems.
The rake routes gives me:
order_confirmation_orders GET /orders/order_confirmation(.:format)
How can i get?:
order_order_confirmation_orders GET /orders/id/order_confirmation(.:format)
I was able to figure this out from the help of this SO post:
Rails: Custom nested controller actions
By using:
resources :orders do
get 'order_confirmation', :on => :member
end
This creates:
order_confirmation_order GET /orders/:id/order_confirmation(.:format) orders#order_confirmation
I have a controller, clients_controller, with corresponding index, show, edit, delete, new & form views. Is there a way to create a new view like clients/prospects.html.erb that acts the same way as clients/index.html.erb, except is routed at clients/prospects/?
I've tried this:
match '/clients/prospects' => 'clients#prospects'
And some other things in routes.rb, but of course get the error "Couldn't find Client with id=prospects".
The goal here is basically to have a prospects view and a clients view, and by simply switching the hidden field to a 1, it (in the user's mind) turns a prospect into a client (it's a CRM-like app).
There's a couple of things you need to do. First you need to put the your custom route before any generic route. Otherwise Rails assumes the word "prospects" is an id for the show action. Example:
get '/clients/prospects' => 'clients#prospects' # or match for older Rails versions
resources :clients
Also you need to copy / paste the index method in your ClientsController and name it prospects. Example:
class ClientsController < ApplicationController
def index
#clients = Client.where(prospect: false)
end
def prospects
#prospects = Client.where(prospect: true)
end
end
Lastly, you need to copy the index.html.erb view and name the copy prospects.html.erb. In the example above you would have to work with the #prospects instance variable.
Create a new action in clients controller named prospects. And then define a collection route in routes.rb for it as either resource full way. Or u directly use match as you were doing.
What you're doing is not wrong (although I'd change match to get, otherwise POST and DELETE requests to that url will also render your prospects view). Presumably you have
resources :clients
in your routes file? If so, what you have will probably work if you just move the line you quoted above the resources declaration -- the problem is that /clients/prospects matches the show route for the clients resource, so if it's defined first then that's the route that gets matched.
However, there's a more idiomatic way to define this route
resources :clients do
collection do
get :prospects
end
end
See Rails Routing documentation for more
Also see migu's answer for what else needs to be done once the url is being routed correctly (though there are other things you can do -- if you the two views are similar enough, you can reuse the view template, for example).
In my Rails site, I have a model named Person, which has an ActionController and migration (database). I've inserted few rows to this table using the console (and saved them there!).
In the PersonController I have a method "list" which I want to list all the people which are in the database :
def list
#persons = Person.all
end
However, in the list.html.erb file in the person's view, I can't access this arrey. Trying to write something like :
<% #persons.each do |r| %>
raises an error claims that #person is nil.
I think I'm doing something wrong here. In conclusion, how can I pass a database from the controller to the view, and how can I disply it?
Thanks
The method you are using to transfer data from the controller to the view is appropriate. My guess is that Person.all is not returning any results, meaning your database is not being populated via the console. Try adding your data in via seeds.rb in the db directory, and then run rake db:seed. That should do it for you. Also, generally lists of models are run through the 'index' route. I would recommend using that instead of a route 'list'.
You can also check this post to make sure you are using the console correctly:
how to add data to database from rails console
*****************EDIT*******************
To use index to list display a list of a model, open your routes.rb file and add the people resource to generate all routes for the person model
resources :people
That will give you index, show, edit, create, update, and destroy routes (run rake routes to see a list of all the routes). If you do not want all of those, you can use only: and except: with the resource command to limit the routes created. Example
resources :people, only: index
You then need to update your controller to match each route that you want to use. So instead of 'list' you can use index, show, edit, update, create, and destroy.
def index
#people = Person.all
end
is an example of the index action definition. Then you just need a view to match the action, like index.html.erb. If you have any people in the database, they should now be in the #people variable during the index action and you can use that to list out each person. If you want to create some people to try it out, you can use the console, the show action you created using the resources command in the routes.rb, or use the seed.rb file and run rake db:seed.
Your variable in controller is #persons and not #person. The error you are getting is #person is nil. If that is not the problem, then please remember that rails uses singular for the model name, which is Person and plural in other cases, people in naming the tables and the controllers.
If this doesn't help, please post your real filenames, and your first line of the controller along with other relevant code.
Good luck!
Check the database and make sure the data is there. In addition, make sure you use Person.create and not Person.new when you are creating a record via the console.
Person.new must be assigned to a variable and save must be called on that variable. Create doesn't require that extra step
u = User.new(:first => "Chris", :last => "Tilley")
u.save! //required with new
u = Person.create(:first => "Chris", :last => "Tilley") //doesn't require save
I am using ruby on rails to make a simple social networking site that includes different message boards for each committee of a student group. I want the url structure for each board to look like https://<base_url>/boards/<committee_name> and this will bring the user to the message board for that committee.
My routes.rb file looks like:
resources :committees, only: [:index]
match '/boards/:name', to: 'committees#index(name)'
My index function of committees_controller.rb file looks like:
def index(name)
#posts = Committee.where(name: name)
end
And then I'll use the #posts variable on the page to display all of the posts, but right now when I navigate to https://<base_url>/boards/<committee_name> I get an Unknown Action error, and it says The action 'index(name)' could not be found for CommitteesController.
Could someone guide me through what I have done wrong?
Once I get this working, how would I make a view that reflects this url structure?
Set up your routes like this:
resources :committees, only: [:index]
match '/boards/:name', to: 'committees#show'
and the controller like this:
def index
#committees = Committee.all
end
def show
#committee = Committee.find_by_name!(params[:name])
end
You can't really pass arguments to controller actions the way you were trying to with index(name). Instead, you use the params hash that Rails provides you. The :name part of the route declaration tells Rails to put whatever matches there into params[:name].
You also should be using separate actions for the listing of committees and displaying single committees. Going by Rails conventions, these should be the index and show actions, respectively.
When routing, you only specify the method name, not the arguments:
match '/boards/:name', to: 'committees#show'
Generally you will declare something with resources or match but not both. To stay REST-ful, this should be the show method. Index is a collection method, usually not taking any sort of record identifier.
Arguments always come in via the params structure:
def show
#posts = Committee.where(name: params[:name])
end
Controller methods that are exposed via routes do not take arguments. You may construct private methods that do take arguments for other purposes.
How do I Change the URL for the view in the controller.
In my controller I generate an ID which I want to display
in the URL of the browser when the view is rendered.
For example, when I enter / in my browser, it should redirect me
to /test/1. The ID is generated randomly by the controller.
So when I access / the 2nd time it could redirect me to /test/3.
I tried to do a match route in my routes.rb file.
But I couldn't find a solution.
routes.rb
get 'test/run'
root to: 'test#run'
match '/test/:id', to: 'test#run'
How about that:
class TestController
def show
...
end
def run
redirect_to Test.random
end
end
Of course, you have to write random scope for your Test model.
You may find helpful this question also - Random record in ActiveRecord
P.S. I'm not sure that the Test is a good name for your model. It could be already used by ruby or rails.