RoR fragement caching based on id - ruby-on-rails

Is there a way to cache a fragment based only on an id and a part?
For example, <% cache(:id => session[:user], :part => 'test') do %>
The code doesn't seem to work though. It still caches based on the action that called it.
Edit:
The problem that I am having is that I cannot expire a fragment in an ajax request(I am refreshing the page as well with page.reload). I think the problem is the action I'm trying to expire is a member of a resource.
Here's my routes code:
map.resources :profiles, :as => 'profile', :only => [:show, :edit, :update], :member => {
:home => :get
} do |profile|
Here's the expire fragment:
expire_fragment(:controller => 'profiles', :action => 'home', :part => 'test')
Thanks

Related

Ruby on Rails: Linking issue between pages

I'm fairly new to Ruby and Rails and this has been an issue I can't resolve on my own:
I'm working on an existing website, running on an older version of Rails and Ruby 1.9.3.
I'm trying to change the details for a certain user, but sometimes in the linking I don't get http://127.0.0.1:3000/users/firstname.lastname but http://127.0.0.1:3000/users?id=firstname.lastname.
This is the code for the links I have:
<li><%= link_to "Remove this user", user_path(#person[:uid]), :confirm => 'Are you sure you want to delete ' + #person[:uid] + '?',:method => :delete ,:title => "Delete user from LDAP" %></li>
<li><%= link_to "Edit this user", edit_userdetails_path(id:#username[:UserID]) %></li>
<li><%= link_to "Add to group", group_path %></li>
<li><%= link_to "Change password", change_pwd_path(#person[:uid]) %></li>
The first and 3rd link work like they should, the 2nd and 4th link have the behavior as described with the ?id= in the url.
This is what's in my routes file:
resources :posts
resources :timesheets
resources :personal_bugs, :only => [:new, :create, :destroy]
resources :sessions, :only => [:new, :create, :destroy]
resources :passwords, :only => [:new, :create]
resources :users, :constraints => { :id => /[0-9A-Za-z\-\.]+/ }
resources :computers
resources :userdetails, :constraints => { :id => /[0-9A-Za-z\-\.]+/ }
resources :bz2refs, :only => [:index, :update]
resources :bz2ref_activities
resources :sessions do
collection do
get :reset_password
get :recovery
end
end
resources :bz2ref_resources do
collection do
get :remove
get :restore
end
end
get "userdetails" => "userdetails#index", :as => "userdetails"
get "edit_userdetails" => "userdetails#edit", :as => "edit_userdetails"
get "log_out" => "sessions#destroy", :as => "log_out"
get "log_in" => "sessions#new", :as => "log_in"
get "change_pwd" => "passwords#new", :as => "change_pwd"
post "search" => "pages#search", :as => "search"
get "search" => "pages#search", :as => "search"
get "help" => "pages#help", :as => "help"
get "admin_urls" => "pages#admin_urls", :as => "admin_urls"
get "report" => "timesheets#report", :as => "report"
post "report" => "timesheets#report", :as => "report"
get "incomplete" => "timesheets#incomplete", :as => "incomplete"
post "incomplete" => "timesheets#incomplete", :as => "incomplete"
get "check" => "timesheets#check", :as => "check"
post "check" => "timesheets#check", :as => "check"
get "export" => "timesheets#export", :as => "export"
get "group" => "users#group", :as => "group"
get "group_show" => "users#group_show", :as => "group_show"
post "group_add" => "users#group_add", :as => "group_add"
get "computer_wake" => "computers#wake", :as => "computer_wake"
get "mirror_users" => "users#mirror", :as => "mirror_users"
get "kiosk" => "posts#latest", :as=> "kiosk"
get "lookupbug" => "timesheets#lookupbug", :as =>"lookupbug"
I call upon userdetails controller from users and then after editing I want to go back from userdetails --> users.
That is because you give an id parameter in the path.
So for example:
user_path(#person[:uid]) => localhost/users/firstname.lastname
user_path(id: #person[:uid]) => localhost/users?id=firstname.lastname
To fix the second link you need to change from edit_userdetails_path(id:#username[:UserID]) to edit_userdetails_path(#username[:UserID]), without the id.
I solved the issue by creating the hyperlink this way:
<li><%= link_to "Edit this user", controller: "userdetails", action: "edit", id: #username[:UserID] %></li>
This way it works!

Couldn't find [model] without an ID - Ruby on rails

I have multiples forms in the Edit view like you can see below:
View
-#posts.each do |post|
.form
= simple_form_for post, url: update_posts_path do |f|
= f.input :title
= f.submit
Then when I'm updating any form I get this error 'Couldn't find Pots without an ID'. You can see the controller and the routes file here:
Controller
def update
#post = Posts.find(params[:id]) //If I change it for Posts.first then is working
if #post.update_attributes(params.require(:posts).permit(:title))
redirect_to ....
else
flash[:notice] = "Sorry."
render :edit
end
end
Routes File
resources :posts, :only => [:index, :edit, :update] do
get "edit", :on => :collection, :as => :edit
patch "update", :on => :collection, :as => :update
end
I think that the error is that for some reason this (#post = Posts.find(params[:id])) is returning a nil object then the controller can't update it. Can someone give me a hand?
The error is the :on => :collection part. This allows the action to be called without an id, so params[:id] is empty.
:on => :collection is normally used for index like actions that have a set of records as a result, so don't need the id part.
btw: the whole thing:
get "edit", :on => :collection, :as => :edit
patch "update", :on => :collection, :as => :update
is redundant, the first line:
resources :posts, :only => [:index, :edit, :update]
tells Rails everything it needs.
For update action you are using :on => :collection but your request is put/patch request so you will use patch "update", :on => :member, :as => :update also make changes in form_for as per your route.Use<%=simple_form_for post ,:url=> update_post_path(post) do |f| %> instead of url: update_posts_path
Regarding params.require(:posts).permit(:title)
First problem : you are using posts instead of post
second is Parameter :id is missing
you will use params.require(:post).permit(:title,:id) instead of params.require(:posts).permit(:title)

ROR link_to method problem

I'm trying to pass some values through a link and I want them to be invisible. These are the options I've tried:
<%= link_to 'Add comment', :controller => :comments, :action => :new, :idea_id => #idea.id, :user_id => #idea.user.id, :method => :post %>
<%= link_to 'Add comment',{ :controller => :comments, :action => :new, :idea_id => #idea.id, :user_id => #idea.user.id}, :method => :post %>
<%= link_to 'Add comment', :controller => :comments, :action => :new, :idea_id => #idea.id, :user_id => #idea.user.id, %>
<%= link_to 'Add comment', new_comment_path, :idea_id => #idea.id, :user_id => #idea.user.id, :method => :post %>
First option - treats method as a parameter:
http://localhost:2000/comments/new?idea_id=1&method=post&user_id=1
Second option - goes like this: http://localhost:2000/comments/new?idea_id=1&user_id=1
and also causes routing error: "Routing Error No route matches "/comments/new"
Third option - loads the form, but of course is like: http://localhost:2000/comments/new?idea_id=1&user_id=1
Fourth option - looks good (http://localhost:2000/comments/new) but the same routing error like the second one.
What am I doing wrong?
Thanks in advance.
PS
I was asked to give my routes, so here they are:
resources :rights
resources :comments
resources :ideas
resources :users
resources :sessions, :only => [:new, :create, :destroy]
root :to => 'main#home'
#match '/comments/new' => "comments#new" # this doesn't help
match '/home', :to => 'main#home'
match '/contact', :to => 'main#contact'
match '/signin', :to => 'sessions#new'
match '/signout', :to => 'sessions#destroy'
match '/signup', :to => 'users#new'
If you have RESTful routes
<%= link_to 'Add comment', new_comment_path,
:idea_id => #idea.id, :user_id => #idea.user.id, :method => :post %>
should be
<%= link_to 'Add comment', comments_path,
:idea_id => #idea.id, :user_id => #idea.user.id, :method => :post %>
As others have said, it sounds like you have a problem in your routes file. Either check if you have the resource :comments defined or post your routes file here and we'll help you out. It's possible that it's not working because you are trying to POST...
If you want 'invisible' variables (I assume you mean that you do not want the variables to appear in the URL), you'll have to POST to the page rather than just link to it. In this case, your second example is the best bet. It goes against convention to POST to /new so that could be what is causing the 'no routes' error if you're using resource :comments
Give this a try in your routes.rb:
match '/comments/new' => "comments#new"
Give that a try, it should load the correct page and give you access to the variables you passed through to it through params.
Please note, that this goes wildly against convention. Is there a reason why you don't want those variables to appear in the URL? It's likely there's a better way of doing what you're thinking and if you explain we can advise you as best as we can.
Have you properly defined the routes?
Can you show how they are?
You should have something like this for that to work: resource :comments
Also, in general /new works with a GET, and a POST is sent when creating...
The method is part of html_options, you need to separate the two hashes like so:
<%= link_to 'Add comment', {:controller => :comments, :action => :new, :idea_id => #idea.id, :user_id => #idea.user.id}, :method => :post %>

Rails: Mapping Conflicting Routes by Detecting Param

Hey! I am trying to set up routes in a Rails application so that, depending on the type of parameter passed, Rails sends the request to a different action.
I have courses which have an attribute state which is a string with a two letter state abbreviation. When a user visits /courses/1, I want Rails to display the show action in the courses controller (and pass the parameter as :id). When a user visits /courses/CO though, I want Rails to display the index action and pass the parameter as :state.
So /courses/1 would be equivalent to
:controller => 'courses', :action => 'show', :id => '1'
And /courses/CO would be equivalent to
:controller => 'courses', :action => 'index', :state => 'CO'
I have tried this:
map.resources :courses, :except => { :index, :show }
map.connect 'courses/:state', :controller => 'courses', :action => 'index', :state => /[A-Z]{2}/
map.connect 'courses/:id', :controller => 'courses', :action => 'show', :id => /[0-9]+/
But it breaks (the rails server wont even start). I don't usually do things like this with routes, so I am outside of my know-how. Thanks!
Edit: Fixed a typo, thanks JC.
Current solution looks like this:
map.resources :courses, :except => [ :index, :show ]
map.courses '/courses', :controller => 'courses', :action => 'index', :state => 'AL', :method => :get
map.courses '/courses/:state', :controller => 'courses', :action => 'index', :requirements => { :state => /[A-Z]{2}/ }, :method => :get
map.course '/courses/:id', :controller => 'courses', :action => 'show', :requirements => { :id => /[0-9]+/ }, :method => :get
This works, but you will need to go edit all your links to the index to say things like courses_path('AA') and you won't be able to use some of the nice helpers, like form_for, which assume you are following the convention that #create is simply #index with a POST request. (Get comfortable with form_tag)
ActionController::Routing::Routes.draw do |map|
map.resources :courses, :except => [ :index, :show ]
map.courses '/courses/:state', :controller => 'courses', :action => 'index', :requirements => { :state => /[A-Z]{2}/ } , :method => :get
map.course '/courses/:id', :controller => 'courses', :action => 'show', :requirements => { :id => /[0-9]+/ } , :method => :get
end
It will keep your routes named the same, though.
(by the way, your /co does not match your regex, which requires upper case chars)
Fun aside: Do we really need the abstraction of a router? http://blog.peepcode.com/tutorials/2010/rethinking-rails-3-routes
I'm afraid this won't work since the structure that maps paths to controllers and actions is setup on start of the rails application, parameter handling happens at request time.
What you could do is to match the :id-parameter in the show-action of the CoursesController against a list of valid states and then either redirect or render a different action.
Hope this helps.

Problem with link_to_remote in rails

I'm having a consistency problem using link_to_remote in rails.
I have 2 use cases of link_to_remote, and they generate different ajax. I can't figure out why, and it is driving me crazy.
Here is use case one...
<%= link_to_remote "section-", :update => "sections", :url => {:action => :destroy, :controller => "sections", :id => #section.id } %>
This generates the appropriate ajax (as below) and works as I expect. Note that it picks up the :action param from the call and inserts it correctly in the ajax.
section-
I also have another instance where I use link_to_remote, but it generates incorrect ajax. The use case is nearly identical, except the controller is different. Either way, I wouldn't expect that to result in different ajax.
The call...
<%= link_to_remote "question-", :update =>"questions-1", :url => {:action => :destroy, :controller => "questions", :id => #question.id} %>
The resulting ajax...
question-
The obvious difference here is in the second arg to Ajax.Updater. The :action param is missing from that path. Why? This results in broken code for me, but I can't understand why this is happening. The link_to_remote calls are nearly identical.
Please point me in the right direction. Thanks.
Below is my routes.rb file...
ActionController::Routing::Routes.draw do |map|
map.resources :questions, :has_one => :section, :collection => { :sort => :post }
map.resources :sections, :has_many => :questions, :has_one => :form, :collection => { :sort => :post }
map.resources :forms, :has_many => :sections
# You can have the root of your site routed with map.root -- just remember to delete public/index.html.
map.root :controller => "forms"
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
What do you get if you copy this into your view?
<%= url_for :action => :destroy, :controller => :questions, :id => #question.id %>
I suspect the problem's not really with link_to_remote, but with routing. Once url_for is returning the URL you expect, then try link_to_remote again.
Simply adding a :method => :delete to your link_to_remote call may be the simplest fix for you:
<%= link_to_remote "question-", :update =>"questions-1", :url => {:action => :destroy, :controller => "questions", :id => #question.id}, :method => :delete %>
This should force the call to /questions/:id to use the HTTP DELETE method. If you want the above call to generate the url /questions/destroy/:id instead I believe you would need a manual change to your routes, as the default map.resources doesn't seem to be achieving that result.

Resources