ArgumentError in Users#show Rails - ruby-on-rails-3

I keep getting the above error and the following message:
'nil' is not an ActiveModel-compatible object that returns a valid partial path.
The error points to the source as line 18.
15: <% if #user.microposts.any? %>
16: <h3>Comments (<%= #user.microposts.count %>)</h3>
17: <ol class="microposts">
18: <%= render #microposts %>
19: </ol>
20: <%= will_paginate #microposts %>
21: <% end %>
I tried checking the naming conventions but I took them exactly as shown in a rails tutorial by Michael Hartl. I have a similar chunk of code for a model called "recipes" so I'm assuming I will get a similar error with that too. The weird thing is that I can create both microposts and recipes and both will show on the home page for the signed_in user. I am getting this error when I go to "Users" and try to click on the accounts there. Any ideas? Thanks in advance

The failing line is attempting to render a partial view -- the argument to render, #microposts is nil but is usually a string that references a view file, for example
<%= render "microposts" %>
would tell rails to look for a file named _microposts.html.erb in the views/users directory. The use of render in a view is different than in a controller.
See doc on rendering partials here
P.S. Welcome to StackOverflow -- nice first question!

I just had this issue, while other answer is informative, this underlying problem has more to do with a discrepancy in the tutorial. It instructs you to add this code to your users_controller:
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(page: params[:page])
end
but earlier in the tutorial you have this #show method that I didn't recall and I ended up having two #show methods in my controller upon adding the one from chapter 13:
def show
#user = User.find(params[:id])
redirect_to root_url and return unless #user.activated?
end
..so what I did to resolve this is combined them into one method and then I got the user page with the unstyled microposts like in the tutorial figure. Not entirely sure how to refer this Hartl but I figured I would add this here as I am also just starting Rails, ran into this issue for about 20 frustrating minutes and somehow noticed the duplicate method after scanning my user_controller for some reason.
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(page: params[:page])
redirect_to root_url and return unless #user.activated?
end

Related

Error using nested_form gem with empty association

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 %>

Editing multiple records at once - how to update without IDs

Still new to Rails. I'll try to provide as much detail as possible.
I have a form that lets me update multiple records at one time.
It's based off the 'Editing Multiple Individually' Railscast episode.
<%= form_tag(auction_clerk_path(#auction), :method => :put) do %>
<% #lots.each do |lot| %>
<%= fields_for "lots[]", lot do |f| %>
<%= f.number_field :sale_price %>
<% end %>
<% end %>
<% end %>
(Simplified to just include a single input for each instance)
An Auction contains multiple Lots (items for sale).
The auction_clerk_path is the route I'm using to just show all lots on one auction.
Everything is working just fine... until I use try to customize my lot paths...
I've added the following to my lot.rb file to be able to use:
/auctions/:auction_id/lots/:lot_number
instead of /auctions/:auction_id/lots/:id
def to_param
lot_number
end
So, in the form mentioned earlier, the fields render with name="lots[12][sale_price]" where 12 is the id.
However with the to_param change, now the fields render with name="lots[1][sale_price]" where 1 is the lot_number.
When I save, the submitted parameters are lot_numbers instead of ids.
So obviously when it tries to update, it won't find the correct records.
My method definition looks like this:
def save_clerking
#updated_lots = Lot.update(params[:lots].keys, params[:lots].values).reject { |l| l.errors.empty? }
if #updated_lots.empty?
flash[:notice] = "Lots updated"
redirect_to auction_clerk_path(#auction)
else
render :action => "clerk"
end
end
I either need to change my method definition to lookup by lot number, or change the form to somehow output IDs in the first place... but I don't know how.
Any help is appreciated. Thanks!
Fixed this through some help on another question.
I changed my method def to
#updated_lots = []
params[:lots].each do |lot_number, attributes|
lot = Lot.where("lot_number = ? AND auction_id = ?", lot_number, params[:auction_id]).first
if lot.update_attributes(attributes)
#updated_lots << lot
end
end
You could fetch the ids by lot number in the controller action and feed those to the update method instead of the params keys.

Correct way to share a view in the index page

I'm a Ruby-on-Rails newbie, just starting out.
I have an MVC called "account_types", generated via scaffold to produce:
controllers/account_types_controller.rb
helpers/account_types_helper.rb
models/account_type.rb
views/account_types/_form, edit, index etc...
Going to localhost:3000/account_types gives me the index view.
What I'd like to do is display the same data as selected from the account_types index method in the application index page as a list.
I wrote a new view called account_types/_list.html_erb as follows:
<ul>
<% #account_types.each do |account| %>
<li><% account.label %></li>
<% end %>
</ul>
I then edited home/index.html.erb (This is based on examples given in other questions on SO):
<%= render :partial => 'account_types/list', :module_types => #module_types %>
However I get
undefined method `each' for nil:NilClass
and the error displays the code from account_types/_list.html.erb where I've written
<% #account_types.each do |account| %>
The scaffolded views work fine, why aren't mine?
Are partials the right thing to use here?
Thanks in advance.
What is the correct way to define an application-wide partial and its variables in rails says to use a before_filter on ApplicationController.
You pass :module_types to partial, but use account_types. As I can see you just need to change your index.html.erb to:
<%= render :partial => 'account_types/list', :account_types => #module_types %>
You can use partials for this if you want, though it would be unnecessary in this case as far as I can tell (they are for sharing chunks of code between several views). In order to get this code to work you'll need to define #account_types in your controller with something like
#account_types = AccountType.all
You can see exact line in your account_types_controller.rb under index action. :module_types => #module_types is not necessary here, since I doubt you defined #module_types either and you don't use module_types in your partial at all.
It's obvious, that you don't understand how Rails works, so I suggest reading through a good tutorial (like this one) before you proceed with whatever you have in mind.

Undefined method unexisting_url

I´m a newbie with Rails3 and I´ve got a strange problem. After searching in google and in StackOverflow for a while I decided to write down my question.
I have a Competencia and a Partida model. Competencia has_many :partidas and Partidas belongs_to :competencia.
I´m working with nested resources and my code looks like this:
routes.rb
resources :competencias do
resources :partidas
end
partidas_controller.rb
class PartidasController < ApplicationController
def new
#competencia = Competencia.find(params[:competencia_id])
#partida = #competencia.partidas.build
end
def create
#competencia = Competencia.find(params[:competencia_id])
#partida = #competencia.partidas.build(params[:partida])
if #partida.save then #blabla end
end
end
views/partidas/new.html.erb
<%= form_for [#competencia, #partida], :url => competencia_partidas_path(#competencia) do |f| %>
<!--blabla-->
<% end %>
I know that it isn´t the right way to specify the url in the form_for helper (specially if I´m not using a custom action), but it was the only way I could work it out. When I wrote something like this: <%= form_for [#competencia, #partida] do |f| %> I´ve got this error:
Showing /Users/ks/rails/projects/chronos/app/views/partidas/new.html.erb where line #4 raised:
undefined method `competencium_partidas_path' for #<#<Class:0x00000101718548>:0x00000101713728>
When I checked the routes (rake routes) everything seems to be fine.
competencia_partidas GET /competencias/:competencia_id/partidas(.:format) {:action=>"index", :controller=>"partidas"}
POST /competencias/:competencia_id/partidas(.:format) {:action=>"create", :controller=>"partidas"}
new_competencia_partida GET /competencias/:competencia_id/partidas/new(.:format) {:action=>"new", :controller=>"partidas"}
Can someone explain me where the competencium name comes from?. What would be the correct approach to solve this?
The problem is that Rails assumes english grammar rules for pluralization. You can read more here: http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html. You can customize the inflector or use English model names. I'm Italian and even when a project is meant only for Italian customer I prefer to use English names.
Rails tries to singularize you model name. In your case, it thinks competencia is the plural of a latin word. To add an exception, put the following in config/initializers/inflections.rb:
ActiveSupport::Inflector.inflections do |inflect|
inflect.singular "competencia", "competencia"
end

Memberships engine not working properly

I've installed RefineryCMS and a couple of its engines (like Blog). Everything was working fine until I installed Memberships engine.
After struggling a couple of days, I could make it "work". By "work" I mean that I could create a user, but since I have it installed, each time I access the home page I get the following error:
undefined method `refinery_user?'
Extracted source (around line #1):
1: <% if refinery_user? %>
2: <% unless admin? # all required JS included by backend. %>
3: <% content_for :stylesheets, stylesheet_link_tag('refinery/site_bar') unless !!local_assigns[:exclude_css] %>
4: <%= yield(:stylesheets) unless local_assigns[:head] or local_assigns[:exclude_css] %>
I've "ctrl+click" on that method and it does exist!! It has the following code:
def refinery_user?
user_signed_in? && current_user.has_role?(:refinery)
end
The weird thing is that I've put a breakpoint on that line but the app didn't stop there...
Does anybody know what's going on?
Make sure your /config/initializers/devise.rb file exists and that it includes the following (probably at the bottom):
config.router_name = :refinery