I'm trying to learn how to use the "Ancestry" gem. I watched the related episode in Railscast and get the code. The message table works fine. But I'm trying to duplicate it with a new table called locations. I've copied and changed names on all the code (I believe).
I created the first location. But, when I go to localhost:3000/locations, I get undefined methodmodel_name' for NilClass:Classfor_form.html.erb` line:
<%= form_for #location do |f| %>
routes.rb:
Messenger::Application.routes.draw do
resources :locations
resources :messages
root :to => 'messages#index'
end
_form.html.erb:
<%= form_for #location do |f| %>
<%= f.error_messages %>
<%= f.hidden_field :parent_id %>
<p>
<%= f.label :locname, "New Location" %><br />
<%= f.text_area :locname, :rows => 8 %>
</p>
<p><%= f.submit "Post Location" %></p>
<% end %>
index.html.erb:
<% title "Locations" %>
<%= nested_locations #locations.arrange(:order => :created_at) %>
<%= render "form" %>
locations_controller.rb:
class LocationsController < ApplicationController
def index
#locations = Location.scoped
#location = Location.new
end
def show
#location = Location.find(params[:id])
end
def new
#location = Location.new(:parent_id => params[:parent_id])
end
def create
#location = Location.new(params[:location])
if #location.save
redirect_to locations_url
else
render :new
end
end
def destroy
#location = Location.find(params[:id])
#location.destroy
redirect_to locations_url
end
end
locations_helper.rb:
module LocationsHelper
def nested_locations(locations)
locations.map do |location, sub_locations|
render(location) + content_tag(:div, nested_locations(sub_locations), :class => "nested_locations")
end.join.html_safe
end
end
Related
Following the example guides.rubyonrails.org/getting_started.html I receive an error undefined method `articles' for nil:NilClass in attempt of addition of article on the page.
routes.rb
Rails.application.routes.draw do
root :to => redirect('/pages/1')
resources :articles
resources :pages do
resources :articles
end
views/articles/new.html.erb
<h1>New Article</h1>
<%= form_for([#page, #page.articles.build]) do |f| %>
<p>
<%= f.label :item %><br>
<%= f.text_field :item %>
</p>
<p>
<%= f.label :description %><br>
<%= f.text_area :description %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
articles_controller.rb
class ArticlesController < ApplicationController
def new
#article = Article.new
end
def edit
#article = Article.find(params[:id])
end
def create
#page = Page.find(params[:page_id])
#article = #page.articles.create(article_params)
redirect_to root_path if #article.save
end
private
def article_params
params.require(:article).permit(:item, :description)
end
end
What am I doing wrong?
You aren't defining #page in your new action. You need to add something similar to what you've done in create to the new action (and probably the edit action as well).
before_action :load_page
...
protected
def load_page
#page ||= Page.find(params[:page_id])
end
I try to make my CRM application works and can't figure out where broken part is.
When trying to create new contact, on link '/companies/1/contacts/new'
got 'NoMethodError in Contacts#new'.
Screenshot is attached, see code below. Please help to find mistake..
route.rb is:
Rails.application.routes.draw do
resources :companies do
resources :contacts do
member do
post :new
end
end
end
root 'companies#index'
end
Contacts Controller:
class ContactsController < ApplicationController
before_action :set_company
def index
#contacts = Contact.where(company_id: params[:company_id])
end
def new; #contact = #company.contacts.new; end
def create
#contact = #company.contacts.create(contact_params)
#contact.save ? redirect_to #company : render :new
end
private
def set_company; #company = Company.find(params[:company_id]); end
def contact_params
params.require(:contact).permit(:name, :position, :phone, :email)
end
end
View:
new.html.erb:
<%= render 'form' %>
<%= link_to 'Back', company_contacts_path %>
Form helper:
<%= form_for(#contact) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You need to specify the company as the first argument to form_for:
form_for(#company, #contact)
Then form_for will be able to infer the correct path.
this error is occuring and i have no idea why, thanks,
undefined method `article_path' for #<#:0x000001029cb960>
edit.html.erb
<h1>Editing <%= #article.name %></h1>
<%= form_for(#article) do |f| %> <-- ????something here?
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
articles model
class MediaController < ApplicationController
def index
#articles = Articles.all
end
def show
#article = Articles.find(params[:id])
end
def edit
#article = Articles.find(params[:id])
end
def update
#article.find(params[:id])
article_params = params.require(:article).permit(:name, :description, :location)
#article.update(article_params)
redirect_to #article
end
end
routes.rb
resources :media
patch "events/:id" => "media#update", as: "update_medium"
Change your routes to
patch "articles/:id" => "media#update", as: "update_medium"
And model name to singular like :
#articles = Article.all
I'm relatively new to RoR, and have been working on a lesson-site sharing back-end.
Currently I have two models: Lesson and Revision. The idea is that a teacher would create a lesson (with a title, description, etc.), at the lesson/new page. The form would redirect to another form with other fields (content, comments) at the lesson/lesson_id/revision/new page. Eventually teachers will be able to "save and modify" lessons by copying revisions to their own profile, but the model isn't there yet.
I'm still focusing on two supposedly basic issues, both in creating new lessons and revisions.
1) Saving the lessons to a user, and revisions to a user and lesson. At one point I had revisions saved to users, but lessons were not saving.
2) Redirecting from the lesson form to the revision form, and the revision form to the revision page. I've tried changing the redirects in the controller and one of the form_for blocks, to no avail. The new lesson form still wants to go to /lessons rather than /lesson/1/revision/new, which I've tried to redirect to with new_lesson_revision_path. The revision form also just goes back to /revisions, which will be an admin index but I'd rather go to /lesson/1/revision/1 etc.
Thanks in advance for any advice on either or both of these issues!
Below is my code for reference. An excerpt from routes.rb:
resources :lessons
resources :revisions #For index pages for admin
resources :lessons do
resources :revisions
end
Models
class Lesson < ActiveRecord::Base
attr_accessible :stable, :summary, :title, :time_created
has_many :revisions, :class_name => "Revision"
has_many :users, :through => :revisions
end
class Revision < ActiveRecord::Base
attr_accessible :comment, :lesson_id, :user_id, :description, :content, :time_updated
belongs_to :lesson, :class_name => "Lesson", :foreign_key => "lesson_id"
belongs_to :user, :class_name => "User", :foreign_key => "user_id"
accepts_nested_attributes_for :lesson
end
Lessons
new.html.erb
<% if user_signed_in? %>
<h2>New lesson</h2>
<%= form_for #lesson do |f| %>
<%= render "form" %>
<% end %>
<%= link_to 'Back', lessons_path %>
<% else %>
<h3> Please <%= link_to 'sign in', new_user_session_path %> or <%= link_to 'create an account', new_user_registration_path %> to make and save lessons.</h3>
<% end %>
Lessons
_form.html.erb
<%= form_for #lesson, :url => new_lesson_revision_path(#lesson_id, #revision) do |f| %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :summary %><br />
<%= f.text_area :summary %>
</div>
<div class="field">
<%= f.label :stable %><br />
<%= f.check_box :stable %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Revisions
new.html.erb
<% if user_signed_in? %>
<h2>New revision</h2>
<%= form_for #revision do |f| %>
<%= render "form" %>
<% end %>
<%= link_to 'Back', lessons_path %>
<% else %>
<h3> Please <%= link_to 'sign in', new_user_session_path %> or <%= link_to 'create an account', new_user_registration_path %> to make and save revisions.</h3>
<% end %>
Revisions
_form.html.erb
<%= form_for(#revision) do |f| %>
<div class="field">
<%= f.label :description %><br />
<%= f.text_field :description %>
</div>
<div class="field">
<%= f.label :content %><br />
<%= f.text_area :content %>
</div>
<div class="field">
<%= f.label :comment %><br />
<%= f.text_area :comment %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Lesson Controller: new/create
def new
#lesson = Lesson.new
end
def create
#user = current_user
#lesson = Lesson.new(params[:lesson])
##user.lessons << #lesson
params[:lesson][:user_id] = current_user.id
params[:lesson][:lesson_id] = #lesson.id
respond_to do |format|
if #lesson.save
format.html { redirect_to new_lesson_revision_path(params[:lesson_id]), notice: 'Your lesson was successfully created.' }
format.json { render json: #lesson, status: :created, location: new_lesson_revision_path}
else
format.html { render action: "new" }
format.json { render json: #lesson.errors, status: :unprocessable_entity }
end
end
end
Revisions Controller: new/create
def new
#revision = Revision.new
end
def create
#lesson = Lesson.find(params[:lesson_id])
#revision = #lesson.revisions.new(params[:revision])
#revision.user_id = current_user.id
#revision.lesson_id = #lesson.id
#revision.time_updated = DateTime.now
respond_to do |format|
if #revision.save
format.html { redirect_to current_user.profile }
format.json { }
else
render :new
end
end
end
Lastly here are most of the results from my rake routes:
home_index GET /home/index(.:format) home#index
profile POST /profile(.:format) profiles#create
new_profile GET /profile/new(.:format) profiles#new
edit_profile GET /profile/edit(.:format) profiles#edit
GET /profile(.:format) profiles#show
PUT /profile(.:format) profiles#update
DELETE /profile(.:format) profiles#destroy
lessons GET /lessons(.:format) lessons#index
POST /lessons(.:format) lessons#create
new_lesson GET /lessons/new(.:format) lessons#new
edit_lesson GET /lessons/:id/edit(.:format) lessons#edit
lesson GET /lessons/:id(.:format) lessons#show
PUT /lessons/:id(.:format) lessons#update
DELETE /lessons/:id(.:format) lessons#destroy
lesson_revisions GET /lessons/:lesson_id/revisions(.:format) revisions#index
POST /lessons/:lesson_id/revisions(.:format) revisions#create
new_lesson_revision GET /lessons/:lesson_id/revisions/new(.:format) revisions#new
edit_lesson_revision GET /lessons/:lesson_id/revisions/:id/edit(.:format) revisions#edit
lesson_revision GET /lessons/:lesson_id/revisions/:id(.:format) revisions#show
PUT /lessons/:lesson_id/revisions/:id(.:format) revisions#update
DELETE /lessons/:lesson_id/revisions/:id(.:format) revisions#destroy
GET /lessons(.:format) lessons#index
POST /lessons(.:format) lessons#create
GET /lessons/new(.:format) lessons#new
GET /lessons/:id/edit(.:format) lessons#edit
GET /lessons/:id(.:format) lessons#show
PUT /lessons/:id(.:format) lessons#update
DELETE /lessons/:id(.:format) lessons#destroy
root / home#index
/profile(.:format) profiles#show
Your question : 1) Saving the lessons to a user, and revisions to a user and lesson. At one point I had revisions saved to users, but lessons were not saving.
see on your lessons_form
<%= form_for #lesson, :url => new_lesson_revision_path(#lesson_id, #revision) do |f| %>
You are using new_lesson_revision_path action form, this is not saving a #lesson, change your lessons_form to :
<%= form_for #lesson do |f| %>
and lessons_controller.rb looks like :
def new
#lesson = Lesson.new
end
def create
#user = current_user
#lesson = Lesson.new(params[:lesson])
....
#lesson.save
# see, redirect_to new lesson with params[lesson_id]
redirect_to new_lesson_revision_path(params[:lesson_id])
end
and on revisions_controller.rb looks like :
def new
#revision = Revision.new
# get #lesson with params(:lesson_id)
#lesson = Lesson.find(params[:lesson_id])
end
def create
#revision = #revision.new(params[:revision])
#revision.user_id = current_user.id
#revision.time_updated = DateTime.now
respond_to do |format|
if #revision.save
format.html { redirect_to current_user.profile }
format.json { }
else
render :new
end
end
end
and on your revisions_form, you can add lesson_id with hidden_field
<%= form_for(#revision) do |f| %>
<%= f.hidden_field :lesson_id, :value => #lesson.id %>
..
..
<% end %>
no 2
Why should you not use nested form or multistep form?
If you are use nested form, you can make lessons_form and
revisons_form in one form.
see screencasts part
1 and
part 2
for nested form
If you are using multistep form, you can resolved you problem no 2
see screencasts Wizard Forms
Addtional
error: undefined method 'revisions' for nil:NilClass - from the line #revision = #lesson.revisions.new(params[:revision])
Because #revision is stand-alone on your case, you could change this
#revision = #lesson.revisions.new(params[:revision])
to
#revision = #revision.new(params[:revision])
I am trying to add a link to my Posts>Index page which lets people send direct message (using Simple Private Messaging) to the creator of the Post.
Currently I have a link to /messages/new to do this, but this is not working - Iget the following error in my app when I try to access /messages/new.
I want to replace the link to /messages/new (in POSTS>INDEX file below) with something better that works. Let me know if you have any thoughts!!
**NoMethodError in Messages#new**
Showing /Users/fkhalid2008/loand/app/views/messages/new.html.erb where line #1 raised:
undefined method `user_messages_path' for #<#<Class:0x12a77f198>:0x12a76dce0>
Extracted source (around line #1):
1: <% form_for #message, :url => user_messages_path(#user) do |f| %>
2: <p>
3: To:<br />
4: <%= f.text_field :to %>
ADDITIONAL INFORMATION: The app itself is like Gumtree.com, where Users come and create Posts (e.g. selling my car), and people respond my sending them Messages (through the Simple Pvt Messages plugin).
Thanks!
Faisal
MESSAGES>NEW VIEW
<% form_for #message, :url => user_messages_path(#user) do |f| %>
<p>
To:<br />
<%= f.text_field :to %>
<%= error_message_on #message, :to %>
</p>
<p>
Subject:<br />
<%= f.text_field :subject %>
<%= error_message_on #message, :subject %>
</p>
<p>
Message<br />
<%= f.text_area :body %>
<%= error_message_on #message, :body %>
</p>
<p>
<%= submit_tag "Send" %>
</p>
<% end %>
MESSAGE MODEL
class Message < ActiveRecord::Base
is_private_message
attr_accessor :to
end
ROUTES.RB
Mysalary::Application.routes.draw do
resources :messages do
collection do
post :delete_selected
end
end
resources :users
resources :profiles
resources :pages
resources :posts
get "pages/home"
get "pages/about"
get "pages/legal"
get "pages/feedback"
root :to => 'posts#new'
end
MESSAGES CONTROLLER
class MessagesController < ApplicationController
before_filter :set_user
def index
if params[:mailbox] == "sent"
#messages = #user.sent_messages
else
#messages = #user.received_messages
end
end
def show
#message = Message.read_message(params[:id], current_user)
end
def new
#message = Message.new
if params[:reply_to]
#reply_to = #user.received_messages.find(params[:reply_to])
unless #reply_to.nil?
#message.to = #reply_to.sender.login
#message.subject = "Re: #{#reply_to.subject}"
#message.body = "\n\n*Original message*\n\n #{#reply_to.body}"
end
end
end
def create
#message = Message.new(params[:message])
#message.sender = #user
#message.recipient = User.find_by_login(params[:message][:to])
if #message.save
flash[:notice] = "Message sent"
redirect_to user_messages_path(#user)
else
render :action => :new
end
end
def delete_selected
if request.post?
if params[:delete]
params[:delete].each { |id|
#message = Message.find(:first, :conditions => ["messages.id = ? AND (sender_id = ? OR recipient_id = ?)", id, #user, #user])
#message.mark_deleted(#user) unless #message.nil?
}
flash[:notice] = "Messages deleted"
end
redirect_to :back
end
end
private
def set_user
#user = User.first
end
end
POSTS>INDEX VIEW
<table class="table table-striped">
<tbody>
<% #posts.each do |post| %>
<tr>
<td>I am a <%= post.title %> getting married in <%= post.job %> in <%= post.location %>, and looking for a <%= post.salary %>. My budget is <%= post.salary %>.</td>
<td> <button class="btn" data-toggle="button" onClick="javascript:location.href = '/messages/new';" />Contact</button></td>
<td><%= time_ago_in_words(post.created_at) %> ago.</td>
<!--/.
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
-->
</tr>
<% end %>
</tbody>
</table>
you routes.rb doesn't define path user_messages_path, it's simple :)
If you want nested restful routes, you need something like
resources :users do
resources :messages
end
Just use
<% form_for #message do |f| %>
<% end %>