undefined method `default_image' for nil:NilClass - ruby-on-rails

ActionView::Template::Error (undefined method `default_image' for nil:NilClass):
409:
410: <!-- Image -->
411: <div class="image">
412: <% if #product.default_image %>
413:
414: <%= image_tag #product.default_image.path, :weight => '262px',:height => '197px'%>
415: <% end %>
model:
# Return attachment for the default_image role
#
# #return [String]
def default_image
self.attachments.for("default_image")
end
# Set attachment for the default_image role
def default_image_file=(file)
self.attachments.build(file: file, role: 'default_image')
end
controller:
class ProductsController < ApplicationController
def index
#products = Shoppe::Product.root.ordered.includes(:product_categories, :variants)
#products = #products.group_by(&:product_category)
#product = Shoppe::Product.root.find_by_permalink(params[:permalink])
#order = Shoppe::Order.find(current_order.id)
end
end

#product = Shoppe::Product.root.find_by_permalink(params[:permalink]) returns nil. So when you try to call default_image on it then it breaks.
You could check it exists via
<% if #product && #product.default_image %>
<%= image_tag #product.default_image.path, :weight => '262px',:height => '197px'%>
<% end %>
Or if you wanted to raise an error if it doesn't exist you can use the bang method of the dynamic finder.
#product = Shoppe::Product.root.find_by_permalink!(params[:permalink])
Also that's the older syntax for dynamic finders. The new one is
#product = Shoppe::Product.root.find_by!(permalink: params[:permalink])

Related

RoR NoMethodError in Posts#new

So I've been building an app using rails and the google datastore. I keep encountering an error in my new.html.erb file where I get the NoMethodError.
I've scoured looking for a solution to my problem and it's most likely a simple typo somewhere in my code. I've been staring at the code for hours so maybe some fresh new eyes can help me figure it out
This is my posts_controller.rb
class PostsController < ApplicationController
PER_PAGE = 10
def index
#post, #cursor = Post.query limit: PER_PAGE, cursor: params[:cursor]
end
def new
#post = Post.new
end
def create
#post = Post.new post_params
if #post.save
flash[:success] = "Posted"
redirect_to posts_path(#post)
else
render :new
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(post_params)
redirect_to #post
else
render 'edit'
end
end
def show
#post = Post.find(params[:id])
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
This is my new.html.erb
<h1>Create Post</h1>
<%= form_for #post do |f| %>
<% if #post.errors.any? %>
<% #post.errors.full_messages.each do |msg| %>
<div class="alert alert danger"><%= msg %></div>
<% end %>
<% end %>
<div class="form-group">
<%= f.label:title %><br>
<%= f.text_field(:title, {:class => 'form-control'}) %>
</div>
<div class="form-group">
<%= f.label:body %><br>
<%= f.text_area(:body, {:class => 'form-control'}) %>
</div>
<p>
<%= f.submit({:class => 'btn btn-primary'}) %>
</p>
<% end %>
This is my model post.rb
class Post
attr_accessor :title, :body
# Return a Google::Cloud::Datastore::Dataset for the configured dataset.
# The dataset is used to create, read, update, and delete entity objects.
def self.dataset
#dataset ||= Google::Cloud::Datastore.new(
project: Rails.application.config.
database_configuration[Rails.env]["dataset_id"]
)
end
# Query Book entities from Cloud Datastore.
#
# returns an array of Book query results and a cursor
# that can be used to query for additional results.
def self.query options = {}
query = Google::Cloud::Datastore::Query.new
query.kind "Post"
query.limit options[:limit] if options[:limit]
query.cursor options[:cursor] if options[:cursor]
results = dataset.run query
posts = results.map {|entity| Book.from_entity entity }
if options[:limit] && results.size == options[:limit]
next_cursor = results.cursor
end
return posts, next_cursor
end
# [START from_entity]
def self.from_entity entity
post = Post.new
post.id = entity.key.id
entity.properties.to_hash.each do |name, value|
post.send "#{name}=", value if post.respond_to? "#{name}="
end
post
end
# [END from_entity]
# [START find]
# Lookup Book by ID. Returns Book or nil.
def self.find id
query = Google::Cloud::Datastore::Key.new "Post", id.to_i
entities = dataset.lookup query
from_entity entities.first if entities.any?
end
# [END find]
# [START validations]
# Add Active Model validation support to Book class.
include ActiveModel::Validations
validates :title, presence: true
# [END validations]
# Save the book to Datastore.
# #return true if valid and saved successfully, otherwise false.
def save
if valid?
entity = to_entity
Post.dataset.save entity
self.id = entity.key.id
true
else
false
end
end
end
routes.rb
Rails.application.routes.draw do
get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
get 'signout', to: 'sessions#destroy', as: 'signout'
resources :sessions, only: [:create, :destroy]
resource :main, only: [:show]
resources :posts
root to: 'posts#index', as: "home"
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
EDIT: This is the error log that I'm getting
ActionView::Template::Error (undefined method `to_key' for #<Post:0x2ae2c68>
Did you mean? to_query):
1: <h1>Create Post</h1>
2: <%= form_for #post do |f| %>
3: <% if #post.errors.any? %>
4: <% #post.errors.full_messages.each do |msg| %>
5: <div class="alert alert danger"><%= msg %></div>
app/views/posts/new.html.erb:2:in `_app_views_posts_new_html_erb__241418705_22466964'
Your Post Model is a plain ruby object but you treat it like an ActiveModel/ActiveRecord object.
Try adding
include ActiveModel::Model inside the Post model like so:
class Post
include ActiveModel::Model
...
end
You have defined #posts in new method but you are using #post in the new.html.erb. Which is the reason for the error. Keep the same name either #posts or #post

undefined method `email' for nil:NilClass when rendering form inside index

I can't seem to figure why I get undefined method `email' for nil:NilClass whenever I try to call any methods on my message class.
index.html.erb messages:
<div class="callout">
<div class="messages-box">
<% #messages.each do |message| %>
<% user_status = message.user_id == current_user.id ? "reciever" : "sender" %>
<div class="<%= user_status %> callout">
<p><%= message.body %></p>
<p><%= message.user.email %></p>
</div>
<% end %>
<%= simple_form_for([#conversation, #message]) do |f| %>
<%= f.input :body %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.submit "Add Reply", class: 'button' %>
<% end %>
</div>
</div>
message controller:
class MessagesController < ApplicationController
before_action :setup_conversation
def index
#messages = #conversation.messages
#message = #conversation.messages.new
end
def new
#message = #conversation.messages.new
end
def create
#message = #conversation.messages.new(message_params)
redirect_to conversation_messages_path(#conversation) if #message.save
end
private
def setup_conversation
#conversation = Conversation.find(params[:conversation_id])
end
def message_params
params.require(:message).permit(:body, :user_id)
end
end
works fine if I remove the form or If remove the #message instance variable from the index action in the corresponding controller but I need it for the form in the index view.
This is a pretty interesting case because you're getting bit by ActiveRecord collection proxies.
In this line, you assign #messages, which is an instance of a subclass of ActiveRecord_Associations_CollectionProxy, which doesn't actually have any records from the database:
#messages = #conversation.messages
What it does have, however, is a reference to the instance of Conversation that you've already assigned to #conversation.
On the next line, you create a new instance of Message associated with the same #conversation:
#message = #conversation.messages.new
You still haven't made any SQL queries at this point. Then we get into rendering, where you call each on #messages, which triggers the query:
#message.each do |message|
...
end
Because CollectionProxy is more sophisticated than a simple AssociationRelation, it coalesces the data from your database — saved records with a User association — with the new data in the collection — your non-persisted #message.
The result is that inside of this block, the last message.user is nil, having not been set. This doesn't explode on the previous lines because Ruby is happy to render message.body (which is nil) and compare nil with foo#example.com.

undefined method `to_key' for #<User::ActiveRecord_Relation:0x007f1bf8c2fd60>

I am really new at rails so please forgive me if i can't see it.
I am trying to edit the permissions on each individual user and i am getting this error in form_for:
undefined method `to_key' for #<User::ActiveRecord_Relation:0x007f1bf8c2fd60>
From what i have seen on other questions on stackoverflow, this usually happens when you try to call a collection in a form but this is not the case?
view:
<div class="n-container">
<tr-form data-riot riot-tag="tr-form">
<%= form_for(#user) do |f| %>
<section>
<div class="w-container">
<h1>User permissions</h1>
<% #permissions.each do |permission| %>
<%= check_box_tag 'permission_ids[]', permission.id %>
<div>
<%= permission.description %>
</div>
<% end %>
</div>
</section>
<section>
<div class="f-controls align-right">
<%= f.submit class: "btn fill blue", value: "Submit" %>
</div>
</section>
<% end %>
</tr-form>
</div>
users_controller:
class UsersController < ApplicationController
def user_params
params.require('user').permit(
permissions: []
)
end
def permissions
#user = User.where(id: params[:user_id])
#permissions = Permission.all
end
end
routes:
resources :users do
get 'permissions'
post 'permissions'
end
Thank you in advance!
One should use ActiveRecord::FinderMethods#find, not where, to receive a single instance:
def permissions
# WRONG: where returns a relation
# #user = User.where(id: params[:user_id])
#user = User.find(params[:user_id])
#permissions = Permission.all
end
It worth to mention, that find raise a RecordNotFound exception on fail, hence you probably want to rescue from it:
def permissions
#user = User.find(params[:user_id])
#permissions = Permission.all
rescue RecordNotFound => rnf
# Log or just skip
end
where might be [ab]used here as well, but in such a case you need to explicitly say that you need the only user:
#user = User.where(id: params[:user_id]).first

dragonfly rails 4 image_tag error

I'm building my photography portfolio in Rails 4.1.6 and Ruby 2.0.0p576.
I have 'collections' which have many 'photos'.
I am using dragonfly 1.0.10 for image uploads.
Collections Model
class Collection < ActiveRecord::Base
belongs_to :admin
has_many :photos
end
Photos Model
class Photo < ActiveRecord::Base
belongs_to :collection
extend Dragonfly::Model
dragonfly_accessor :image
end
Collection Controller
class CollectionsController < ApplicationController
respond_to :html, :xml, :json
def index
#collections = Collection.all
end
def new
#collection = Collection.new
respond_with (#collection)
end
def create
#collection = Collection.new(collection_params)
#collection.save
respond_with (#collection)
end
def edit
#collection = Collection.find(params[:id])
end
def update
#collection = Collection.find(params[:id])
if #collection.update(collection_params)
redirect_to #collection
else
render 'edit'
end
end
def show
#collection = Collection.find(params[:id])
end
def destroy
#collection = Collection.find(params[:id])
#collection.destroy
respond_with (#collection)
end
private
def collection_params
params.require(:collection).permit(:name, :desc, photos: [:image] )
end
end
Photos Controller
class PhotosController < ApplicationController
def new
#collection = Collection.find(params[:id])
#photo = #collection.new
end
def create
#collection = Collection.find(params[:collection_id])
#photo = #collection.photos.create(photo_params)
redirect_to collection_path(#collection)
end
private
def photo_params
params.require(:photo).permit(:image)
end
end
This is storing my photos for me correctly.
But on my collection show page, I'm getting a "NoMethodError in Collections#show undefined method `image'.
In terminal, I get the following error:
ActionView::Template::Error (undefined method `image' for #):
Code for the show page is below:
collections/show.html.erb
<h1><%= #collection.name %></h1>
<p><%= #collection.desc %></p>
<% #collection.photos.each do |photo| %>
<div>
<%= image_tag #collection.photos.image.thumb('400x300#').url %>
</div>
<% end %>
I'm an absolute rails n00b and need some help as to how to fix this and be able to view all the photos of the collection on its show page.
Please help!
You have a wrong usage of the each loop:
<% #collection.photos.each do |photo| %>
<div>
<%= image_tag photo.image.thumb('400x300#').url %>
</div>
<% end %>
Read How does iteration work in Ruby?

using f.select, undefined method `map' for nil:NilClass

Ok so i am tring to list my genres in a f.select form and I am getting an error. I have look everywhere and i am just not understanding what i am doing differently. when I enter rails c and type g = Genre.all it lists all genres then g.map out puts => #<Enumerator: ...>
Error:
undefined method `map' for nil:NilClass
View Page:
<%= f.fields_for :genres do |g| %>
<div class="field">
<%= g.label :genre %>
<%= g.select :genres, #genres.map {|g| g.name} %>
</div>
<% end %>
Controller:
def create
#song = Song.new(params[:song])
#genres = Genre.all
if #song.save
redirect_to player_path
else
render :new
end
end
You need to assign #genres variable in new action too:
def new
#genres = Genre.all
end

Resources