Rails with Cells and Helpers - ruby-on-rails

I'm having trouble accessing the cookies object in my cell views via helper. My code looks like this:
#cell
helper SessionsHelper
#cell view
signed_in?
#sessions helper
signed_in?
cookies.sth
end
I'm getting the error: undefined local variable or methodcookies'`.
How do I make cookies visible there?
Alternatively, I'd like to pass Helper as an object collaborator to my cell, because this helper contains a lot of useful methods. Is doing SessionHelper.new the correct way to do that?
<%= render_cell :my_cell, :display, session_helper: SessionsHelper.new %>
I now see that SessionsHelper is in fact a module, so I cannot invoke the new() method. What should I do with undefined cookies?

I always define signed_in? in ApplicationController. (There cookies is available) And then do:
helper_method :signed_in?
to make it available as a helper method.
As for your second question: session_helper: SessionsHelper.new is not necessary. All methods from all helpers are available all views.

Related

Using helper methods in views

I'm having some trouble realising how the helper methods should be used in views. For example, take these parts of code:
Mycontrollers_helper.rb
module MycontrollersHelper
def destroy_everything
Model.destroy_all
redirect_to root_path
end
end
How should it be used in the view then ? Let's say adding the method to a button in the view:
<%= button_to 'Destroy all', destroy_everything, method => :post %>
Is just writing a method in the helper.rb file enough or does it require some additional lines in the controller it refers to ? Is this even the correct syntax for something like this ?
Helpers in rails actually view helpers. So they are meant to provide some help to render your views.
If you want to delete something, and then redirect to some action, just use a controller action for that.
I think you are taking about view helper, which you want to call from your view template.
You can call your view helper with the name of the method.
Calling destroy_everything will works fine if this helper is included in your controller.
Update:
If you write your helper method in application helper then you don't need to worry about load/ include the helper.

Draper Decorators and using methods on Application controller

I have some code in my view that tests if a user is logged in with a method that is on the application controller:
def logged_in?
!!current_user
end
I use this method on a view to display certain information only if the user is logged in.
<%= **logged_in?** ? link_to('+', upvote_post_path(post), method: 'post', remote: true) : '+' %>
<span id = "post-<%= post.slug %>-votes"> <%= post.total_votes %></span>
Now if I want to move this logic to a decorator it won't work because the decorator cannot access this method on the application controller. I need this to be on there. So my question is: What is the best way to handle this situation? The logic can be access from the application helper. Is there a way that my decorator object access this method without repeating the method twice?
you can access helper h.some_methods
def link_to_edit_event
h.link_to h.t('buttons.edit'), h.edit_event_path(id)
end
from Draper
Normal Rails helpers are still useful for lots of tasks. Both Rails'
provided helpers and those defined in your app can be accessed within
a decorator via the h method:
class ArticleDecorator < Draper::Decorator
def emphatic
h.content_tag(:strong, "Awesome")
end
end

Why isn't my rails 4 helper working?

I have a helper module for my home page with two methods that do the same thing:
module HomeHelper
def parsed_text(tweet)
auto_link (tweet).gsub(/(#\w+)/, %Q{\\1})
end
def other_parsed_text
self.auto_link.gsub(/(#\w+)/, %Q{\\1})
end
end
In my view this works:
<%= parsed_text(tweet.text) %>
But this doesn't:
<%= tweet.text.other_parsed_text %>
I get a NoMethodError at /
undefined method other_parsed_text. Isn't self the caller of the method inside of my helper method?
What am I doing wrong? I want the second style of calling methods with a . notation to work too. How do I do that?
This does not work because you didnt extend the class that tweet.text is of. You can use ActiveSupport::Concern if you want to extend some class. What you are doing now is provding some methods that can be called with parameters.
// I posted an example here: https://stackoverflow.com/a/8504448/1001324

Rails: method defined in application_helper.rb not recognized by categories_controller.rb

More newbie issues.
I understand that if I define a method in my application helper, it is available to the entire app code.
In my applicaton helper, I have:
def primary_user_is_admin
if current_user
user_login_roles = JSON.parse(current_user.role)
if user_login_roles["admin"]
return 1
end
end
return nil
end
If I call it from the categories_controller:
if !primary_user_is_admin
redirect_to root_url
end
I get an error message: undefined local variable or method `primary_user_is_admin'
This also happens if I put the primary_user_is_admin code in the registrations_helper.rb file
However, if I use it in any of the views (views/user/edit.html.erb for instance)
<% if primary_user_is_admin %>
<% end >
then it works. What am I missing?
Helpers are not included into a controller by default. You can
include ApplicationHelper
To gain access to the methods in the ApplicationHelper module. The previous discussion has a bunch of useful solutions for accessing helpers in controller.
Methods defined in helpers are only available to views by default. You have to 'include ApplicationHelper' in the applications controller to get access to this method in the controllers.

What is the best way to avoid code duplication between views and controllers in Ruby on Rails?

I currently have code in my ApplicationController to check if a user is logged in and has the required access to perform a given action (the tests take place in a before_filter).
I require the same functionality in the views to decide if I should be showing the admin links in a list view, but how do I best avoid duplicating code in the controllers and views?
The way I have chosen to do it now, is to have the user_can_edit_customers? essentially be a wrapper for 'can_edit_customers?' on my User class:
ApplicationController:
class ApplicationController
And then do something similar in my view helpers.
This way all functionality is encapsulated in the User model but I still need to define wrappers in my controllers and helpers, but are there smarter ways of doing this?
Note, the user stuff is only an example - this also applies to other pieces of functionality.
I would say do away with the wrappers and just call can_edit_customers? directly on the user object passed to the view.
If you want to keep them a solution might be to use helper_method in your controller.
helper_method :current_user, :can_edit_customers?
def current_user
#current_user ||= User.find_by_id(session[:user])
end
def can_edit_customers?
#current_user.can_edit_customers?
end
This way the method also becomes available in the view.
<% if can_edit_customers? -%>...<% end -%>
Just to be more direct. The helper_method "macro" in a controller causes a controller method to behave as if it's also a method in the application helper.
helper_method :current_user, :can_edit_customers?
Personally I think you should not use helpers.
I would take a different solution.
Let's say that we have Cucumber, a model, that should not be editable by some users. I create #editable? method as follows:
class Cucumber < ActiveRecord::Base
def editable?(current_user)
# Something happens here.
end
end
Note that if a page is accessible by everyone, current_user might be false.
Then, in the views you're able to do:
<%- if #cucumber.editable?(current_user) -%>
<%# Something happens here. -%>
<%- end -%>
And, in the controllers, use a filter.
The best thing about this approach is that it follows Fat Model, and enables you to easily cover your permissions with unit tests.
I think helpers are the way to do what you want. As for checking in views whether the user has or not the priviledge to do something, you could put a flag in your session data (e.g. session[:admin] = true and check that in your view.
It is common practice to make methods like logged_in? available in the controller and the views. For most cases, you don't need to push down authorization logic into the models.
Definetly go with with the approach user Hates described. Have a look at plugins like restful_authentication and acts_as_authenticated, to see how they did it.
There are several railscasts (http://railscasts.com/episodes?search=authentication) covering this topic. For instance, you could write a helper that takes a block and is then used like this:
<%- admin_user_ do %>
<%= link_to .. %>
<%= link_to .. %>
<%= link_to .. %>
<%- end %>

Resources