NoMethodError while using breadcrumbs_on_rails gem - ruby-on-rails

I'm trying to use gem breadcrumbs_on_rails.
I want to use the name attribute of my vehicle model in the current breadcrumbs element, so I'm using a Symbol as Breadcrumb Element, which calls the corresponding method defined in the same context and sets the Element attribute to the returned value (as per gem documentation).
#vehicles_controller.rb
def show
#vehicle = Vehicle.find(params[:id])
#user = User.find(params[:user_id])
add_breadcrumb "home", :root_path
add_breadcrumb "user profile", :current_user
add_breadcrumb :set_vehicle_name, :user_vehicle_path
end
...
private
#return vehicle name for breadcrumb
def set_vehicle_name
#vehicle.name
end
My view is as follow:
#vehicles/show.html..erb
<ol class="breadcrumb">
<%= render_breadcrumbs :separator => " / " %>
</ol>
When I run the server and access the page I get the following error:
NoMethodError in Vehicles#show
undefined method `set_vehicle_name' for #<#<Class:0x007f40edd52958>:0x007f40f18fe790>
Can you tell me what's causing this error? thanks

I made it working appending helper_method :set_vehicle_name after the private method definition, as specified in this post.
The gem uses the context of an ActionView::Base (breadcrumbs.rb#L25)
to evaluate any methods (breadcrumbs.rb#L50). It's complaining because
you haven't made your method in your controller available to the view.
Use helper_method to make it available to your views and it will work.
hope it might help

Related

"First argument in form cannot contain nil or be empty", but they aren't (to my knowledge) nil?

I'm trying to make a bootstrap modal form using Rails, however I keep getting the aforementioned error. Here is my form code (results in error):
<%= bootstrap_form_for([#restaurant, #review], url:
new_restaurant_review_path([#restaurant, #review])) do |f| %>
Here is my controller code:
before_action :set_restaurant
def new
#review = Review.new(restaurant: #restaurant)
end
private
def set_restaurant
#restaurant = Restaurant.find(params[:restaurant_id])
end
I'm not sure what to do.
I'm assuming the form is for a new review that belongs to a restaurant. I know in older versions of Rails, something like this would work.
<%= form_for([#restaurant, Review.new]) do |f| %>
I'd check your #restaurant variable and make sure it's not nil. I can see that you are initializing #review, but unless you've initialized #restaurant with a before_action or something like that, it's not being initialized in your new action.

undefined method `each' for nil:NilClass when rendering from a different view

Every time I try to render something that is located from a different view, I get a NoMethodError: undefined method `each' for nil:NilClass.
It happens when I put the following code in the view I want to render stuff on:
views/uploads/myuploads.html.erb
<%= render template: 'guitar_sounds/index' %>
And it tells me that the error seems to be in a particular block of code where the template is located:
views/guitar_sounds/index.html.erb
<% #guitar_sounds.each do |sound| %> <!-- Error here -->
<%= render "guitar_sound", sound:sound %>
<% end %>
However, when I load that page view on its own, I get no errors.
Can someone help me?
Loading a partial does not automatically hit a controller method. By that, it sounds like the only controller method being run is uploads#myuploads, but your #guitar_sounds variable is being defined in guitar_sounds#index. I'd simply define the #guitar_sounds variable in your UploadsController
UploadsController < ApplicationController
def myuploads
# here is where #guitar_sounds needs to be defined
#guitar_sounds = GuitarSound.all
end
end
Let's say you needed #guitar_sounds in lots of methods, you could define it in a before_action
UploadsController < ApplicationController
before_action :set_guitar_sounds
def myuploads
# normal controller code
end
private
def set_guitar_sounds
#guitar_sounds = GuitarSound.all
end
end
Now #guitar_sounds will be set for every method in the UploadsController
Your template guitar_sounds/index expects #guitar_sounds to be defined, and be able to iterate over its items.
If you reuse the template without assigning any values to #guitar_sounds, by default it will be nil, thus you can see the error.
Hope it clarifies a bit the problem!
guitar_sounds/index expects #guitar_sounds to be defined, aka, not nil, so it can iterate over its items.
You should, instead, use local variables.
<%= render template: 'guitar_sounds/index', guitar_sounds: #guitar_sounds %> #or other # variable
And at your view:
<% guitar_sounds.each do |sound| %>
<%= render "guitar_sound", sound:sound %>
<% end %>
Now guitar_sounds (note the missing #) is a local variable that you pass to the render function!
EDIT: Check rails documentation about this: Passing Local Variables to partials/templates.

When moving a views to a new directory, what changes must I make for them to work

To be specific I simply created a subdirectory in the one they were currently contained in and I am now getting
Missing template users/index, application/index with {:locale=>[:en]....
I assume I need to make a simple change elsewhere so rails knows where to find the views however I have not been able to figure it out.
Edit: to elaborate further, its not all of them, just a specific group that I wanted to organize.
Edit2: to elaborate even further... the path to these views is users_path, and I need to somehow update it so that it knows where to find the views. Would this be in the routes?
Edit3:
in the users_controller.rb i tried:
render view/index.html.erb
and got the error
undefined local variable or method `view'
i also tried
render :partial => "view/index.html.erb"
and got the error
undefined method `render'
Edit4:
class UsersController < ApplicationController
before_filter :authenticate_user!
def index
#users = User.all
end
def show
#user = User.find(params[:id])
unless #user == current_user
redirect_to :back, :alert => "Access denied."
end
end
end
Edit5:
<div class="container">
<h3>Users</h3>
<table>
<tbody>
<% #users.each do |user| %>
<tr>
<%= render user %>
</tr>
<% end %>
</tbody>
</table>
</div>
Try in the appropriate place of your controller: e.g., render 'subfolder/view_file'. If you don't specify this in the controller, Rails will look for the default location for the view (so you need to specify this if the view is not in the default location). So if it's the index view that you've relocated, you need to specify generally at the end of the index method in the controller, which view it needs to render: render 'subfolder/index'.
If the relocated view is a partial, you would need to specify the path to this partial there where you call for the partial.
It's not in the routes where you need to make adjustments: in routes you specify which controller method to execute as a user visits a certain url of your website.

Fix Rails Gem CanCan bug for ActiveModel::ForbiddenAttributesError

When attempting to create on a model with CanCan set as manage: all I am continuously getting this error:
ActiveModel::ForbiddenAttributesError - ActiveModel::ForbiddenAttributesError:
I found a fix online here.
That pastes this code into my applications controller:
before_filter do
resource = controller_name.singularize.to_sym
method = "#{resource}_params"
params[resource] &&= send(method) if respond_to?(method, true)
end
This leads to my issue. I have two models with belongs_to_has_many association and a method that adds an user to a group.
When I want to add an user to a group using add_user which takes the group id and the user object I now get this error.
The routine is called by:
<%= link_to 'Add', add_user_group_path(group: #group, user_id: id) %>
The method looks like this:
def add_user
group = Group.find(params[:id])
user = User.find(params[:user_id])
group.users << user
end
And this is the error:
Parameters: {"group"=>"16", "id"=>"16", "user_id"=>"332"}
NoMethodError - undefined method `permit' for "16":String:
What is the before_filter method doing that would cause this error?
================ UPDATE ===================
I ended up figuring it out.
Since the group id is automatically passed in the add_user call from the controller I had to change this line:
<%= link_to 'Add', add_user_group_path(group: #group, user_id: id) %>
to:
<%= link_to 'Add', add_user_group_path(user_id: id) %>
And it now works. Turns out when you pass the #group object the param "group => x" gets parsed weird.
CanCan is not working with Rails4. Use CanCanCan, and you don't need any of these workaround. Just have some following methods just like what we normally do in Rails4.
create_params or update_params (depending on the action you are performing)
_params such as article_params (this is the
default convention in rails for naming your param method)
resource_params (a generically named method you could specify in each
controller)
Link Here: https://github.com/CanCanCommunity/cancancan

Rails way to render different actions & views based on user type?

I have a couple different user types (buyers, sellers, admins).
I'd like them all to have the same account_path URL, but to use a different action and view.
I'm trying something like this...
class AccountsController < ApplicationController
before_filter :render_by_user, :only => [:show]
def show
# see *_show below
end
def admin_show
...
end
def buyer_show
...
end
def client_show
...
end
end
This is how I defined render_by_user in ApplicationController...
def render_by_user
action = "#{current_user.class.to_s.downcase}_#{action_name}"
if self.respond_to?(action)
instance_variable_set("##{current_user.class.to_s.downcase}", current_user) # e.g. set #model to current_user
self.send(action)
else
flash[:error] ||= "You're not authorized to do that."
redirect_to root_path
end
end
It calls the correct *_show method in the controller. But still tries to render "show.html.erb" and doesn't look for the correct template I have in there named "admin_show.html.erb" "buyer_show.html.erb" etc.
I know I can just manually call render "admin_show" in each action but I thought there might be a cleaner way to do this all in the before filter.
Or has anyone else seen a plugin or more elegant way to break up actions & views by user type? Thanks!
Btw, I'm using Rails 3 (in case it makes a difference).
Depending on how different the view templates are, it might be beneficial to move some of this logic into the show template instead and do the switching there:
<% if current_user.is_a? Admin %>
<h1> Show Admin Stuff! </h1>
<% end %>
But to answer your question, you need to specify which template to render. This should work if you set up your controller's #action_name. You could do this in your render_by_user method instead of using a local action variable:
def render_by_user
self.action_name = "#{current_user.class.to_s.downcase}_#{self.action_name}"
if self.respond_to?(self.action_name)
instance_variable_set("##{current_user.class.to_s.downcase}", current_user) # e.g. set #model to current_user
self.send(self.action_name)
else
flash[:error] ||= "You're not authorized to do that."
redirect_to root_path
end
end

Resources