I have a page that shows a list of events. When the event is clicked it takes you to a login page and it keeps the session id along with the page. When I go to the next page it always sends the last session variable.
<% #events.each do |e| %>
<%= link_to e.event_name, sessions_new_path %>
<%= e.event_start %> - <%= e.event_stop %>
<% session[:event_id] = e.id %>
<%= session[:event_id] %>
<br>
<% end %>
This shows the session[:event_id] is there and it is storing in the variable but when I click on the link it will send the last session[:event_id] of the loop. Any ideas would be helpful. I am looking at option of either passing the variable to the next page or storing it into a database cell, but not sure on how sessions are stored in databases.
Assuming you are using a supported database with ActiveRecord, you can configure your application to store sessions in the database by editing your_app/config/initializers/session_store.rb:
YourApp::Application.config.session_store :active_record_store
make sure to comment out or remove the line:
# YourApp::Application.config.session_store :cookie_store, :key => '_your_app_session'
Further, there are auth gems that handle redirecting users to protected pages after signing in. If you haven't already, look at Devise and/or authlogic. Personally, I prefer Devise.
Related
In my rails app, I have two models, a ClientPage and a ContentSection, where ClientPage has_many :content_sections. I'm using the nested_form gem to both models to be edited with the same form. This works fine as long as the ClientPage has at least one ContentSection, but if there are no associated ClientSections, the using nested_form's link_to_add method throws the following NoMethodError:
undefined method `values_at' for nil:NilClass
The form is structured as follows:
<%= nested_form_for page, form_options do |f| %>
# ClientPage fields
# ClientSections
<%= f.link_to_add "Add new section", :content_sections %>
<% end %>
As long as there is at least one ClientSection associated with the page, this works fine. As soon as there isn't, the error is thrown. Removing the link_to_add also stops the error from being thrown. (There's actually a second nested model under ContentSection, and the same issue arises if there are no associated models.)
Not sure what I'm fairly obvious thing I'm missing, but any pointers or suggestions would be greatly appreciated.
Finally worked this out -- the error was due to the fact that I was using the gem in a slightly non-standard way. Within the form, instead of rendering all of the content sections the standard way:
<%= f.fields_for :content_sections do |section_form| %>
# section fields
<% end %>
I put it inside a loop, as I needed the index of each item (which is not stored within the model itself):
<% page.content_sections.each_with_index do |section, index| %>
<%= f.fields_for :content_sections, section do |section_form| %>
# section fields
<% end %>
<% end %>
The issue doing it this way is that the fields_for method does not get called if the association is empty, and as such the gem cannot build the blueprint for the object (which is used to add in the extra item when link_to_add is called).
The solution was to make sure fields_for got called even if the association was empty:
<% if page.content_sections.empty? %>
<%= f.fields_for :content_sections do |section_form| %>
# section fields
<% end %>
<% end %>
I have a model called Note. Each note belongs_to :call_reason. And call_reason has_many :notes.
What I want to do in a view is display a list of call_reasons and a total count of each next to it so we can see what the most popular call reasons are.
Here's what I have so far:
dashboard_controller:
def index
#notes = Note.all
end
dashboard view:
<% #notes.each do |n| %>
<%= n.call_reason.reason %>
<% end %>
This lists all notes' call_reasons.
I'm stumbling on how to list each call_reason once with a total count next to it. What I have now just lists all the call_reasons per note which is a mess. I think I could scope this out somehow or change the instance variable but I'm having a hard time getting it right.
Any thoughts?
Since you want to list call reasons, you should start with that:
def index
#call_reasons = CallReason.all
end
Then in your view you can do this:
<% #call_reasons.each do |call_reason| %>
<%= call_reason.reason %> <%= call_reason.notes.count %>
<% end %>
Note that this will perform a query for every call reason in your database. To prevent this you can use a counter cache. Check out the section on counter cache on Rails Guides too.
I am using devise and cancan with rails 3.2.1 and I'm having an unusual problem that I know can be refactored and simplified, but after much searching, I'm stuck.
I have first_name and last_name fields in the user model and have successfully displayed the full name of the user in the users/show.html.erb view using this code:
<%= #user.first_name + " " + #user.last_name %>
And I was successfully displaying a link to the user's show page in the header using:
<% if user_signed_in? %>
<li><%= link_to #user.first_name + " " + #user.last_name, current_user %></li>
<% end %>
But, and I can't figure this one out, after working on another part of the app, the header started giving me an undefined method error message...
In any case, I know there is a much better way to define and work with user names and I have tried some things out, such as adding a name method to the user model, but as you can clearly tell from this post, I am a beginner and have not been able to make that work.
Please let me know if you have any ideas on how to best work with users names in an application like this.
Where are you defining #user? I'm willing to bet that it's in your UsersController show action, which means it's defined for your header in that action only.
Try replacing your header code with this:
<% if user_signed_in? %>
<li><%= link_to current_user.first_name + " " + current_user.last_name, current_user %></li>
<% end %>
The trick is that Devise makes current_user always available when the user is signed in. You don't have to worry about setting a #user instance variable.
I'm building a basic app with Rails 3.2 and Devise 2.0. I've create a User devise model and a Projects model. In my routes.rb files I have
root :to => 'projects#index'
I can sign up and sign in at Get users/sign_up and Get users/sign_in, respectively, but when it redirects to projects#index, I don't see a notice at the top that says "You've signed in successfully. Which file do I need to check to fix this?
You need to add flash messages showing to the file /projects/index.html.erb
for example this way:
<% flash.each do |key, value| %>
<%= content_tag(:div, value, :class => "flash #{key}") %>
<% end %>
I just discovered the rails-settings gem and now I need to make an admin page that lets me edit the setting values. How would I make a settings controller with an edit view that can change these dynamic app wide settings?
I haven't used this gem but it seems like it should be fairly straight forward. Since it uses a database backed model, you would simply create a controller as normal:
rails g controller Settings
From here you would define your index action to gather all your individual settings for display in the view:
def index
#settings = Settings.all
end
Then in the view you can setup a loop to display them:
<% #settings.each do |setting| %>
<%= setting.var %> = <%= setting.value %>
<% end %>
As far as editing ... this might be a bit tricky since by default rails would expect you to submit only one setting at a time to edit. You could do it this way but unless you implement the edit with ajax it might be tedious and non-intuitive.
Another way would be to set up your update method to accept all the individual settings at once, loop through and update each one with new values. It might look something like this:
// The /settings route would need to be setup manually since it is without an id (the default)
<%= form_tag("/settings", :method => "put") do %>
<% #settings.each do |setting| %>
<%= label_tag(setting.var, setting.var) %>
<%= text_field_tag(setting.var, :value => setting.value) %>
<% end %>
<%= submit_tag("Save Changes") %>
<% end %>
This should output all of the settings (given they have been assigned to the #settings variable) with the var name as the label and the current value as the text field value. Assuming that the routing is setup, when you submit this form the action that receives it should all the new settings in the params variable. Then you can do something like this in the action:
def update
params.each_pair do |setting, value|
eval("Settings.#{setting} = #{value}")
end
redirect_to settings_path, :notice => 'Settings updated' # Redirect to the settings index
end
This may not be the best way depending on how often you edit the settings and how many settings you have...but this is a possible solution.
I was looking for some suggestions for this and found another answer to this that is very simple and elegant, for anyone looking for this later. It just sets up dynamic accessors in your model, allowing your form to have settings fields just like your normal attributes. An example can be found in the original answer:
How to create a form for the rails-settings plugin