I have numerous paginations in my application; they all look alike; all but one work fine. The one broken one breaks at the very last step. The details are below. I have 3 classes- Micropost, Category, Selection. I have a link that points to details_controller, which renders a view /selections/detailslist which in turn renders the partial /selections/details. The code successfully gets to the last view and breaks in the third line, with the error message "undefined local variable or method `micropost' for #<#< Class: ...." Any help here would be greatly appreciated.
class Micropost < ActiveRecord::Base
attr_accessible :content, :category_content, :selection_content, :category_id, :selection_id, :user_id
belongs_to :user
belongs_to :category
belongs_to :selection
validates :user_id, presence: true
validates :category_content, presence: true
validates :selection_content, presence: true
end
class Category < ActiveRecord::Base
attr_accessible :content, :id, :count, :c_count
has_many :selections
has_many :microposts
end
class Selection < ActiveRecord::Base
attr_accessible :content, :count, :category_id
belongs_to :category
has_many :microposts
end
view with link
<li>
<span class="selection">
<%= selection.content %>
   
( <%= selection.count %> )
   
<%= link_to "Details", controller: :details, param1: selection.id, param2: selection.category_id %>
</span>
</li>
details_controller
class DetailsController < ApplicationController
require 'will_paginate/array'
respond_to :html, :js
def index
##category = Category.find_by_id(params[:param2])
#selection = Selection.find_by_id(params[:param1])
#microposts = #selection.microposts.paginate(page: params[:page])
render '/selections/detailslist'
end
end
view: /selections/detailslist
<% #category = Category.find_by_id(#selection.category_id) %>
<h3> <%= #category.content %> </h3>
<br>
<%= #selection.content %>
 
( <%= #selection.count %> )
<br>
<ol class="selections">
<%= render partial: 'selections/details', collection: #microposts %>
</ol>
<%= will_paginate #microposts %>
view: selections/details
<li>
<span class="selection">
<% user = User.find_by_id(micropost.user_id) %>
<%= user.name %>
</span>
</li>
error message:
undefined local variable or method `micropost' for #<#< Class:0x007fed1811ba90>:0x007fed17bc9fb0>
Related
I tried to create edit and update action for my assosiated model named as Entity.
But When edit pages pop up no saved data shown. Means it is showing all field as empty and when I put values in it, creates a another object.
And also validation messages are not showing
Entities Controller
class EntitiesController < ApplicationController
def edit
#schema = Schema.find(params[:schema_id])
#entity = #schema.entities.find(params[:id])
end
def update
#schema = Schema.find(params[:schema_id])
#entity = #schema.entities.find(params[:id])
if #entity.update(entity_params)
redirect_to schema_entities_path(#schema)
else
render 'edit'
end
end
private
def entity_params
params.require(:entity).permit(:clientId, :name, :description, :mnemonic)
end
end
edit form for it:
<%= form_for([#schema, #schema.entities.build], data: { turbo: false }) do |f| %>
<%= f.text_field :clientId, placeholder:"ClientId" %>
<%= f.text_area :name, placeholder: "Name" %>
<%= f.text_area :description, placeholder: "Description" %>
<%= f.text_area :mnemonic, placeholder: "Mnemonic" %>
<%= f.submit 'Submit' %>
<% if #entity.errors.any? %>
<div id="error_explanation">
<% #entity.errors.full_messages.each do |msg| %>
<p class="error_msg"><%= msg %></p>
<% end %>
</div>
<% end %>
<% end %>
Its model:
class Entity < ApplicationRecord
belongs_to :schema
has_many :fields, dependent: :destroy
has_many :joins, through: :fields
validates :name, presence: true, uniqueness: true
def self.search(search)
where("name LIKE ?", "%#{search}%")
end
end
This is how I am passing values from index page:
<%= link_to 'Edit', edit_schema_entity_path(schema_id: #schema.id, id: data.id) if data.id %>
I have 3 tables: coaches, categories and also a join table categories_coaches, on submit I want to store category_id and coach_id in join table categories_coaches and name, email, university, batch, phone in coach table. how to do so?
now details are storing in coach table but not storing in join table
please help me to solve this problem.
coach.rb
class Coach < ActiveRecord::Base
has_and_belongs_to_many :categories
end
category.rb
class Category < ActiveRecord::Base
belongs_to :coach
end
registrationcontroller.erb
class Coaches::RegistrationsController < Devise::RegistrationsController
def new
#individual=#individual ||= Coach.new
super
end
def create
build_resource sign_up_params
#individual=#individual ||= Coach.new
super
end
private
def sign_up_params
params.require(:coach).permit(:name, :email, :university, :batch, :linkedin_url, :code, :phone,category_ids: []
)
end
end
view page
<%= simple_form_for(#individual, as: :coach, url: registration_path(:coach)) do |f| %>
<%= f.input :name, required: true, %>
<%= f.input :university %>
<%= f.input :batch %>
<%= f.input :email%>
<%= f.input :phone%>
<div class="category-scroll">
<% Category.all.each do |c| %>
<% if c.parent_id != nil %>
<div class="category-left">
<%= check_box_tag "category_ids[]", c.id, false, :id => "category_ids_#{c.id}" %>
<%= c.name %>
</div>
<% else %>
<b><%= c.name %></b>
<% end %>
<% end %>
</div>
<div class="form-group">
<%= f.button :submit, "SUBMIT", class: "apply-continue_form" %
<% end %>
What you've mentioned sounds like a has_and_belongs_to_many relationship to me.
I'll detail what you should do, and the underlying mechanics of the association:
#app/models/coach.rb
class Coach < ActiveRecord::Base
has_and_belongs_to_many :categories
end
#app/models/category.rb
class Category < ActiveRecord::Base
has_and_belongs_to_many :coaches
end
This, as opposed to the has_many :through relationship, does most of the legwork for you. You were correct in setting up your join_table as you did:
The importance of getting this right is that each time you CRUD either your Coach or Category objects, you'll have access to their associated data through the :categories and :coaches methods respectively.
Thus, you'll be able to populate the data like this:
#config/routes.rb
resources :coaches #-> url.com/coaches/new
#app/controllers/coaches_controller.rb
class CoachesController < ApplicationController
def index
#coaches = Coach.all
end
def new
#coach = Coach.new
end
def create
#coach = Coach.new coach_params
end
private
def coach_params
params.require(:coach).permit(:name, :email, :university, :batch, :phone, :categories)
end
end
This will then allow you to make the following view:
#app/views/coaches/new.html.erb
<%= form_for #coach do |f| %>
<%= f.text_field :name %>
<%= f.email_field :email %>
<%= f.text_field :university %>
<%= f.text_field :batch %>
<%= f.text_field :phone %>
<%= f.collection_select :categories, Category.all, :id, :name %>
<%= f.submit %>
<% end %>
I'm trying to create a video with many-to-many tags. So, each tag would be each row in Tag table. I'm not sure I have to do it myself or Rails has some magic that could do that?
Here's my model.
class Video < ActiveRecord::Base
belongs_to :user
has_many :video_tags
has_many :tags, through: :video_tags
end
class Tag < ActiveRecord::Base
end
class VideoTag < ActiveRecord::Base
belongs_to :video
belongs_to :tag
end
Here's my form
<%= form_for(#video, html: { class: "directUpload" }, multipart: true) do |f| %>
<% if #video.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#video.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #video.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :path %><br>
<%= f.file_field :path%>
</div>
<div class="field">
<%= f.label :tags %><br>
<%= f.text_field :tags %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And here's my Controller
class VideosController < ApplicationController
def show
#videos = Video.where(user_id: params[:user_id])
end
def new
#video = Video.new
#s3_direct_post = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: 201, acl: :public_read)
end
def create
#video = Video.new(video_params)
#video.user_id = 1
if #video.save
redirect_to #video
end
end
private
# Use callbacks to share common setup or constraints between actions.
# Never trust parameters from the scary internet, only allow the white list through.
def video_params
params.require(:video).permit(:title, :path, :tags)
end
end
But then I got this error which I thought I must have missed something. I just want to have tag separated by space.
Started POST "/videos" for ::1 at 2015-04-07 00:21:11 -0400
Processing by VideosController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"authenticity_token",
"video"=>{"title"=>"asdfasdf",
"path"=>"//s3.amazonaws.com/uploads/token/57203191c21df0cacf98f3fa9340f4.mp4",
"tags"=>"test "}, "commit"=>"Create Video"}
Completed 500 Internal Server Error in 3ms
NoMethodError (undefined method `each' for "test ":String):
app/controllers/videos_controller.rb:14:in `create'
My following answer will help you
https://stackoverflow.com/questions/22611372/rails-4-paperclip-and-polymorphic-association
you can use accept_nested_attributes_for and,
<%= f.fields_for :tags, #_your_tags do |t| %>
instead of
<div class="field">
<%= f.label :tags %><br>
<%= f.text_field :tags %>
</div>
Your association would be like this:
class Video < ActiveRecord::Base
belongs_to :user
has_many :video_tags
has_many :tags, through: :video_tags
end
class VideoTag < ActiveRecord::Base
belongs_to :video
belongs_to :tag
end
class Tag < ActiveRecord::Base
has_many :video_tags
has_many :videos, through :video_tags
end
I found this wiki pretty helpful. And yes rails has a special way to handle this. These are called nested models or you can also user nested_form gem
I'm trying to build a form that allows a user to create a new Post, a Tag for that post, and a TagType for that tag, all with one submit button.
My models are set up as follows:
class Post < ActiveRecord::Base
belongs_to :user
has_many :post_tag_relationships, dependent: :destroy
has_many :tags, through: :post_tag_relationships
.
.
end
class Tag < ActiveRecord::Base
has_many :reverse_post_tag_relationships, class_name: "PostTagRelationship"
has_many :posts, through: :reverse_post_tag_relationships,
class_name: "PostTagRelationship"
belongs_to :tag_type
.
.
end
class TagType < ActiveRecord::Base
has_many :tags
.
.
end
In the page controller where the form is located, I have the methods defined as follows:
#post = current_user.posts.build
#tag = #post.tags.build
#tag_type = #tag.tag_type.build
My form displays just fine if I only include the post and tag methods, as in:
<%= form_for(#post) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new post..." %>
</div>
<%= fields_for(#tag) do |u| %>
<div class="field">
<%= u.text_area :name, placeholder: "Tag" %>
</div>
<% end %>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
But when I add fields_for(#tag_type), with:
<%= fields_for(#tag_type) do |y| %>
<div class="field">
<%= y.select :name %>
</div>
<% end %>
I get an undefined method 'model name' for NilClass:Class
I'm pretty new with Rails, and my guess is that it has something to do with the fact that a tag belongs_to tag_types (whereas a post has_many tags). If anyone knows a fix, it would be much appreciated. Thanks.
You can use rails nested attributes http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html or create a form object http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
EDIT
The Routing Error has disappeared thanks to carlosramireziii who helped changed the Form to
<%= form_for (#micropost) do |f| %>
<%= fields_for :comments do |ff| %>
<%= ff.text_area :content %>
<% end %>
<div class="CommentButtonContainer">
<%= f.submit "Comment" %>
</div>
<% end %>
But the issue now is that the post will not save, any suggestions?
I am currently making a comments model that is connected to a:
micropost_id :integer and user_id :integer
The problem that I continue to receive is when I post something I get this in return:
Routing Error
No route matches [POST] "/microposts/comments"
This is my routes.eb
Project::Application.routes.draw do
resources :microposts do
resources :comments
end
This is the Comment Form
<%= form_for([#micropost, #micropost.comments.new]) do |f| %>
<%= f.text_area :content %>
<div class="CommentButtonContainer">
<%= f.submit "Comment" %>
</div>
<% end %>
This is the Comment Template
<%= div_for comment do %>
<div class='UserCommentContainer'>
<div class='UserComment'>
<div class='UserName sm'>
Anonymous
</div>
<div class='UserCommentText'>
<%= comment.content %>
</div>
</div>
</div>
<% end %>
And finally this is what is inside the Micropost
<div id='CommentContainer' class='Condensed2'>
<div class='Comment'>
<%= render "comments/form" %>
</div>
<div id='comments'>
<%= render #micropost.comments %>
</div>
</div>
Everything else related to the comments model and controller I have posted below, I have been mulling around this for a long time and could really use help, thank you!
Comments Model
class Comment < ActiveRecord::Base
attr_accessible :content
belongs_to :micropost
validates :content, presence: true, length: { maximum: 140 }
validates :user_id, presence: true
validates :micropost_id, presence: true
default_scope order: 'comments.created_at DESC'
end
Micropost Model
class Micropost < ActiveRecord::Base
belongs_to :user
has_many :comments
validates :user_id, presence: true
end
User Model
class User < ActiveRecord::Base
has_many :microposts
has_many :replies, :through => :microposts, :source => :comments
end
Comments Controller
class CommentsController < ApplicationController
def create
#comment = #micropost.comments.new(params[:comment])
if #comment.save
redirect_to #user
else
redirect_to #user
end
end
end
User Controller
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#micropost = Micropost.new
#comment = #micropost.comments.new
#microposts = #user.microposts.paginate(page: params[:page])
end
end
I believe the problem is that you are trying to save a new comment on a micropost that hasn't been saved yet. Since you have your comments routes nested underneath the microposts routes, the micropost needs to exist before you can create a new comment.
If you want to create both objects in the same form, you need to use nested model attributes.
Micropost
class Micropost < ActiveRecord::Base
belongs_to :user
has_many :comments
accepts_nested_attributes_for :comments
validates :user_id, presence: true
end
Form
<%= form_for(#micropost) do |f| %>
<%= f.fields_for :comments do |ff %>
<%= ff.text_area :content %>
<% end %>
<div class="CommentButtonContainer">
<%= f.submit "Comment" %>
</div>
<% end %>