I dont understand why this is happening but I am getting this error.
undefined method albums_path and it says that it is on the first line in this code:
<%= form_for #album, :html => { :class => 'form-horizontal', multipart: true } do |f| %>
<div class="control-group">
<%= f.label :name, :class => 'control-label' %>
<div class="controls">
but I dont see why. here is my controller:
class AlbumsController < ApplicationController
before_action :set_album, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#user = User.find_by_id(params[:id])
#albums = Album.all.where(:user_id => #user)
end
def show
redirect_to user_albums_url
end
def new
#album = Album.new
end
def edit
end
def create
#album = current_user.albums.new(album_params)
respond_to do |format|
if #album.save
if params[:images]
params[:images].each { |image|
#album.pictures.create(image: image)
}
end
format.html { redirect_to #album, notice: 'Gallery was successfully created.' }
format.json { render json: #album, status: :created, location: #album }
else
format.html { render action: "new" }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end
def update
#album.update(album_params)
redirect_to user_albums_url
end
def destroy
#album.destroy
redirect_to user_albums_url
end
private
def set_album
#album = Album.find(params[:id])
end
def album_params
params.require(:album).permit(:name, :description, :images)
end
end
and my routes are as follows:
resources :users do
resources :albums do
resources :pictures do
resources :comments
end
end
end
Ive looked everywhere for my code even mentioning "albums_path" but it doesnt say it anywhere. Is there anything that you guys can think of being the problem? I've tried fixing the forms but it doesnt seem to work. another thing that you might want to see is the link to new action. here it is:
<%= link_to 'New Album', new_user_album_path(:user_id => current_user.id), :class => 'btn btn-mini' %>
I don't know if this helps at all but I'm using the paperclip gem to create albums.
Your albums resource is nested within users resource. Therefore you should set user in your new action (or, better, in before_filter):
before_filter :set_user
# ...
def set_user
#user = User.find(params[:user_id])
end
and add user reference to your form:
form_for [#user, #album] do |f|
BTW, instead of #albums = Album.all.where(:user_id => #user), you can have (it's much more idiomatic in Rails): #albums = #user.albums.
Related
I have 3 objects, Users, Recipes, and Tasks. Tasks are nested inside Recipes, and Recipes are nested inside Users. I am able to save/add/delete Recipes just fine, and I can add Tasks in the HTML form, but when I go to save, the Tasks do not show up as part of a Recipe, even when I go back to the form. I have been working on this for a while and would appreciate any insight.
Users Controller:
class UsersController < ApplicationController
before_filter :authenticate_user_or_admin_or_conduit!
before_action :set_user, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#users = User.all
respond_with(#users)
end
def show
respond_with(#user)
end
def new
#user = User.new
respond_with(#user)
end
def edit
end
def create
#user = User.new(user_params)
if #user.save
if conduit_signed_in?
redirect_to '/conduits', notice: 'User created successfully.'
elsif admin_signed_in?
redirect_to '/admins', notice: 'User created successfully.'
else
redirect_to #user, notice: 'User created successfully.'
end
else
render :new
end
end
def update
#user.update(user_params)
respond_with(#user)
end
def destroy
#user.destroy
respond_with(#user)
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
Recipes Controller:
class RecipesController < ApplicationController
before_action :set_recipe, only: [:show, :edit, :update, :destroy]
# GET /recipes
# GET /recipes.json
def index
#recipes = Recipe.all
end
# GET /recipes/1
# GET /recipes/1.json
def show
end
# GET /recipes/new
def new
#recipe = Recipe.new
end
# GET /recipes/1/edit
def edit
end
# POST /recipes
# POST /recipes.json
def create
#recipe = Recipe.new(recipe_params)
respond_to do |format|
if #recipe.save
format.html { redirect_to #recipe, notice: 'Recipe was successfully created.' }
format.json { render :show, status: :created, location: #recipe }
else
format.html { render :new }
format.json { render json: #recipe.errors, status: :unprocessable_entity }
end
end
class UsersController < ApplicationController
before_filter :authenticate_user_or_admin_or_conduit!
before_action :set_user, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#users = User.all
respond_with(#users)
end
def show
respond_with(#user)
end
def new
#user = User.new
respond_with(#user)
end
def edit
end
def create
#user = User.new(user_params)
if #user.save
if conduit_signed_in?
redirect_to '/conduits', notice: 'User created successfully.'
elsif admin_signed_in?
redirect_to '/admins', notice: 'User created successfully.'
else
redirect_to #user, notice: 'User created successfully.'
end
else
render :new
end
end
def update
#user.update(user_params)
respond_with(#user)
end
def destroy
#user.destroy
respond_with(#user)
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
Recipes Controller:
class RecipesController < ApplicationController
before_action :set_recipe, only: [:show, :edit, :update, :destroy]
# GET /recipes
# GET /recipes.json
def index
#recipes = Recipe.all
end
# GET /recipes/1
# GET /recipes/1.json
def show
end
# GET /recipes/new
def new
#recipe = Recipe.new
end
# GET /recipes/1/edit
def edit
end
# POST /recipes
# POST /recipes.json
def create
#recipe = Recipe.new(recipe_params)
end
# PATCH/PUT /recipes/1
# PATCH/PUT /recipes/1.json
def update
respond_to do |format|
if #recipe.update(recipe_params)
format.html { redirect_to #recipe, notice: 'Recipe was successfully updated.' }
format.json { render :show, status: :ok, location: #recipe }
else
format.html { render :edit }
format.json { render json: #recipe.errors, status: :unprocessable_entity }
end
end
end
# DELETE /recipes/1
# DELETE /recipes/1.json
def destroy
#recipe.destroy
respond_to do |format|
format.html { redirect_to recipes_url, notice: 'Recipe was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_recipe
#recipe = Recipe.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def recipe_params
params.require(:recipe).permit(:reward, task_attributes: [:description, :counter, :done, :_destroy, :id])
end
end
Tasks Controller:
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
# GET /tasks
# GET /tasks.json
def index
#tasks = Task.all
end
# GET /tasks/1
# GET /tasks/1.json
def show
end
# GET /tasks/new
def new
#task = Task.new
end
# GET /tasks/1/edit
def edit
end
# POST /tasks
# POST /tasks.json
def create
#task = Task.new(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
format.json { render :show, status: :created, location: #task }
else
format.html { render :new }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tasks/1
# PATCH/PUT /tasks/1.json
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to #task, notice: 'Task was successfully updated.' }
format.json { render :show, status: :ok, location: #task }
else
format.html { render :edit }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tasks/1
# DELETE /tasks/1.json
def destroy
#task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
#task = Task.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def task_params
params.require(:task).permit(:description, :counter, :done, :notes)
end
end
Users Model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :characters
end
Recipes Model:
class Recipe < ActiveRecord::Base
belongs_to :character
has_many :task, :dependent => :destroy
accepts_nested_attributes_for :task, allow_destroy: true
end
Tasks Model:
class Task < ActiveRecord::Base
belongs_to :recipe
end
User Form:
<div id="myform">
<%= form_for(#character) do |f| %>
<% if #character.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#character.errors.count, "error") %> prohibited this character from being saved:</h2>
<ul>
<% #character.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<li class="accordion-navigation">
Recipes
<div id="panel6a" class="content">
<fieldset>
<legend>Recipes consist of a variety of tasks</legend>
<div>
<%= f.fields_for :recipe do |recipe| %>
<%= render "recipe_fields", :f => recipe %>
<% end %>
<div class="links">
<%= link_to_add_association "Add Recipe", f, :recipe, :class =>"button" %>
</div>
</div>
</fieldset>
</div>
</li>
<% end %>
</div>
Recipe Form:
<div class="nested-fields">
<div class="row">
<div class="row">
<div class="large-3 columns">
<div class="field">
<%= f.text_field :reward %>
</div>
</div>
<div class="large-9 columns">
<fieldset>
<legend>Add Task</legend>
<div>
<%= f.fields_for :task do |task| %>
<%= render "task_fields", :f => task %>
<% end %>
<div class="links">
<%= link_to_add_association "Add Task", f, :task, :class =>"small button" %>
</div>
</div>
</fieldset>
<span style="float:right"><%= link_to_remove_association "Remove Recipe", f, data: {confirm: "Are you sure?"}, :class =>"button alert" %></span>
</div>
</div>
</div>
</div>
Task Form:
<div class="nested-fields">
<div class="row">
<div class="large-3 columns">
<div class="field">
<%= f.text_field :description %>
</div>
</div>
<div class="large-3 columns">
<div class="field">
<%= f.number_field :counter, label: "Record number if needed" %>
</div>
</div>
<div class="large-3 columns">
<div class="field">
<%= f.check_box :done, label: "Completed?" %>
</div>
</div>
<span style="float:right"><%= link_to_remove_association "Remove Task", f, data: {confirm: "Are you sure?"}, :class =>"small button alert" %></span>
</div>
</div>
I dealt with this funkiness recently. I'm guessing the Task is being created, just not relating to the Recipe. If that is the case, you need to include the recipe_id in the task_attributes array.
Nesting is all sorts of magic, but for whatever reason, the id of the parent object won't be set unless it's explicitly included as a permitted param.
Hope this helps!
The other post definitely pointed out an error, but I could not fix it until I added the task_attributes to the recipe_attributes in the User controller, like so:
params.require(:user).permit(:name, recipe_attributes: [:reward, :_destroy, :user_id, :id, task_attributes: [:description, :recipe_id, :counter, :done, :_destroy, :id]])
I'm getting an error raised of "undefined method 'comments_path' for..."
At this code in app/views/comments/_form.html.erb (line 1).
I recently tried to implement nestable comments via polymorphic associations on a website I'm building; however, I'm running into a problem that's not allowing me to move forward.
I'm trying to implement nested comments on a 'commentable' model (ie the blog in this case) and then when show is clicked, all the nested comments are shown and the individual can comment on the blog or reply to a comment (and hence result in nested comments) without leaving the page.
I've included a few other files to show the setup, but if I've missed one that's necessary, please let me know and I'll promptly add it. Any help is much appreciated. I've been stumped for several hours and I'm sure its something simple.
<%= form_for [#commentable, #comment] do |f| %>
<%= f.hidden_field :parent_id %></br>
<%= f.label :content, "New Comment" %></br>
<%= f.text_area :body, :rows => 4 %></br>
<%= f.submit "Submit Comment" %>
<% end %>
app/views/blogs/show.html.erb
<div class="content">
<div class="large-9 columns" role="content">
<h2>Comments</h2>
<div id="comments">
<%= nested_comments #comments %>
<%= render "comments/form" %>
</div>
</div>
</div>
app/controllers/comments_controller
class CommentsController < ApplicationController
def new
#parent_id = params.delete(:parent_id)
#commentable = find_commentable
#comment = Comment.new( :parent_id => #parent_id,
:commentable_id => #commentable.id,
:commentable_type => #commentable.class.to_s)
end
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment])
if #comment.save
flash[:notice] = "Successfully created comment."
redirect_to #commentable
else
flash[:error] = "Error adding comment."
end
end
private
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
def comment_params
params.require(:comment).permit(:parent_id, :body, :commentable_type, :commentable_id)
end
end
app/controller/blogs_controller.rb
class BlogsController < ApplicationController
before_filter :authenticate, :except => [ :index, :show ]
before_action :set_blog, only: [:show, :edit, :update, :destroy]
include MyModules::Commentable
# GET /blogs
# GET /blogs.json
def index
#blogs = Blog.all.order('created_at DESC')
respond_to do |format|
format.html
format.json
format.atom
end
end
# GET /blogs/1
# GET /blogs/1.json
def show
#blog = Blog.find(params[:id])
end
# GET /blogs/new
def new
#blog = Blog.new
end
# GET /blogs/1/edit
def edit
#blog = Blog.find(params[:id])
end
# POST /blogs
# POST /blogs.json
def create
#blog = Blog.new(blog_params)
respond_to do |format|
if #blog.save
flash[:success] = "Blog was sucessfuly created"
format.html { redirect_to #blog }
format.json { render :show, status: :created, location: #blog }
else
format.html { render :new }
format.json { render json: #blog.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /blogs/1
# PATCH/PUT /blogs/1.json
def update
respond_to do |format|
if #blog.update(blog_params)
flash[:success] = "Blog was successfully updated."
format.html { redirect_to #blog }
format.json { render :show, status: :ok, location: #blog }
else
format.html { render :edit }
format.json { render json: #blog.errors, status: :unprocessable_entity }
end
end
end
# DELETE /blogs/1
# DELETE /blogs/1.json
def destroy
#blog.destroy
respond_to do |format|
flash[:success] = "Blog was successfully deleted."
format.html { redirect_to blogs_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_blog
#blog = Blog.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def blog_params
params.require(:blog).permit(:title, :body, :image, :image_cache, :remote_image_url)
end
private
def authenticate
authenticate_or_request_with_http_basic do |name, password|
name == "admin" && password == "runfast"
end
end
end
my routes file looks like this...
Rails.application.routes.draw do
resources :blogs do
resources :comments
end
resources :applications
resources :reviews
resources :properties
root to: 'blogs#index'
end
the blog and comment models...
class Blog < ActiveRecord::Base
validates_presence_of :body, :title
has_many :comments, :as => :commentable, :dependent => :destroy
mount_uploader :image, ImageUploader
end
class Comment < ActiveRecord::Base
has_ancestry
belongs_to :commentable, :polymorphic => true
validates_presence_of :body
end
and finally the commentable module in lib/my_modules/commentable.rb
require 'active_support/concern'
module MyModules::Commentable
extend ActiveSupport::Concern
included do
before_filter :comments, :only => [:show]
end
def comments
#Commentable = find_commentable
#comments = #Commentable.comments.arrange(:order => :created_at)
#comment = Comment.new
end
private
def find_commentable
return params[:controller].singularize.classify.constantize.find(params[:id])
end
end
#blog
#<Blog id: 8, title: "New Blog Post about Databases.... Again", body: "RDM, the database management system, was designed ...", created_at: "2015-03-01 22:28:07", updated_at: "2015-03-03 00:11:07", image: "IMG_2210.JPG">
#commentable
#<Blog id: 8, title: "New Blog Post about Databases.... Again", body: "RDM, the database management system, was designed ...", created_at: "2015-03-01 22:28:07", updated_at: "2015-03-03 00:11:07", image: "IMG_2210.JPG">
app/helpers/comments_helper.rb
module CommentsHelper
def nested_comments(comments)
comments.map do |comment, sub_comments|
content_tag(:div, render(comment), :class => "media")
end.join.html_safe
end
end
#_params instance variable in better errors
{"utf8"=>"✓", "authenticity_token"=>"OH2tDdI5Kp54hf5J78wXHe//Zsu+0jyeXuG27v1REqjdAec7yBdlrVPLTZKEbLZxgR2L7rGwUwz5BlGTnPcLWg==", "comment"=>{"parent_id"=>"", "body"=>"Hello!\r\n"}, "commit"=>"Submit Comment", "controller"=>"comments", "action"=>"create", "blog_id"=>"8"}
You're getting the error in this view: app/views/blogs/show.html.erb.
The data for this view has been prepared in blogs#show. So in your view, you should have <%= form_for [#blog, #comment] do |f| %>, since you set #blog, not #commentable.
You should also do #comment = Comment.new. Not sure where you set this one...
Do <% raise #commentable.inspect %> in your view (app/views/blogs/show.html.erb). If it's nil, then that's why you're getting the error.
Hi i'm very new to rails and any help will much appreciated. I am trying to implement the thumbs_up GEM. I have read the documentation but still find it challenging to implement it fully.
what i would like is the display of an increasing figure when a user clicks on the thumbs_up image and vice-versa when a user clicks on thumbs_down image
by figure i mean: if a user clicks the image thumbs_up you see a figure of 1, if another user clicks the image thumbs_up the figure increases to 2 [displaying 2 users have liked the event giving it a thumbs_up]
Any advise along side with an explanation will be helpful - below is the stage i have reached
i have a.) run g thumbs_up & b.) rake db:migrate
Models:
#Event.rb
class Event < ActiveRecord::Base
belongs_to :user
acts_as_voteable
end
#User.rb
class User < ActiveRecord::Base
has_many :events, dependent: :destroy
acts_as_voter
end
Controller
class EventsController < ApplicationController
before_action :set_event, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!
def index
#events = Event.order(:date)
end
def show
#commentable = #event
#comments = #commentable.comments
#comment = Comment.new
end
def new
#event = Event.new
end
def edit
end
def create
#event = Event.new(event_params)
#event.user = current_user
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render :show, status: :created, location: #event }
else
format.html { render :new }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #event.update(event_params)
format.html { redirect_to #event, notice: 'Event was successfully updated.' }
format.json { render :show, status: :ok, location: #event }
else
format.html { render :edit }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
def destroy
#event.destroy
respond_to do |format|
format.html { redirect_to events_url, notice: 'Event was successfully destroyed.' }
format.json { head :no_content }
end
end
def vote_for
#event = Event.find(params[:id])
current_user.vote_for(#event)
respond_to do |format|
format.js
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_event
#event = Event.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def event_params
params.require(:event).permit(:name, :description, :date, :time, :city, :price, :user_id)
end
end
Views: app/views/events/show.html.erb
<p>
<strong>Name:</strong>
<%= #event.name %>
</p>
<p>
<strong>Description:</strong>
<%= #event.description %>
</p>
<p>
<%=link_to image_tag('thumbs_up', :border => 0), vote_for_event_path(#event), :remote => true %>
<%=link_to image_tag('thumbs_down', :border => 0), vote_against_event_path(#event), :remote => true %>
</p>
Routes:
Rails.application.routes.draw do
devise_for :users
resources :events do
resources :comments, only: [:create, :destroy]
member do
post :vote_for, :vote_against
end
end
end
To show the votes in your view, use the votes_for method and votes_against method.
For example in your view add these lines:
<p>
<strong>Votes For:</strong>
<%= #event.votes_for %>
</p>
<p>
<strong>Votes Against:</strong>
<%= #event.votes_against %>
</p>
Because you are learning Rails, I suggest you try using basic HTML links instead of AJAX links:
<%=link_to image_tag('thumbs_up', :border => 0), vote_for_event_path(#event) %>
<%=link_to image_tag('thumbs_down', :border => 0), vote_against_event_path(#event) %>
A basic link can help you see what's happening, and your controller will reload the entire page.
When you get the basic links working, then read about AJAX, and how to use the Rails link_to with remote: true to update an HTML div.
There are various ways to accomplish this: you can read about using Rails responders, or using coffescript, or using jQuery to attach a link handler.
There are also various user interface solutions, such as updating the vote immediately because you know the original vote and you can increment the vote immediately on the client side.
Here's a related StackOverflow question that has a bunch of good answers and discussion about remote_to and replacing a div: rails link_to :remote
I am new to Ruby on Rails and I can't wrap my head around the routing stuff.
I have a main view (index.html.erb) with a basic subscribe form with main controller, I have a resource named User in routes.rb with an associated user controller.
/app/views/main/index.html.erb
<%= form_for #user, remote: true do |f| %>
<%= f.text_field :email %>
<%= f.submit "Subscribe" %>
<% end %>
/app/controllers/main_controller.rb
class MainController < ApplicationController
def index
#user = Users.new
end
def create
#user = Users.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'Thank you !' }
format.js
else
format.html { render action: "new" }
format.js
end
end
end
end
/config/routes.rb
MyPage::Application.routes.draw do
get "main/index"
root 'main#index'
resources :users
end
UsersController is empty.
I know I need to change something in routes.rb but I don't get it. I get uninitialized constant MainController::Users error. Thanks !
Your problem is your UsersController is being confused as to inherit from MainController
This is either a routing issue or an issue with your system setup:
Routes
#config/routes.rb
root to: 'main#index'
resources :users, :main
View
<%= form_for #user, url: main_create_path, method: :post, remote: true do |f| %>
<%= f.text_field :email %>
<%= f.submit "Subscribe" %>
<% end %>
Controllers
class MainController < ApplicationController
def index
#user = Users.new
end
def create
#user = Users.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'Thank you !' }
format.js
else
format.html { render action: "new" }
format.js
end
end
end
end
class UsersController < ApplicationController
#your_stuff_here
end
I am trying to create form that contains another model in rails. I have accomplished this with using accepts_nested_attibutes and it is working great. The problem is I have an additional field in that table that records the User Name for each comment and I am not sure on how to insert that information when a new comment is being created. The username is being supplied by the Application Controller using the "current_user" method.
Regards,
Kyle
Comment Model
class Comment < ActiveRecord::Base
belongs_to :post
before_save :set_username
private
def set_username
self.created_by = current_user
end
end
Application Controller (This is just a Sandbox app so I just put a string in the method)
class ApplicationController < ActionController::Base
protect_from_forgery
helper_method :current_user
def current_user
"FName LName"
end
end
Show View
<p id="notice"><%= notice %></p>
<p>
<b>Title:</b>
<%= #post.title %>
</p>
<div id="show_comments"><%= render 'comments' %></div>
<div id="add_comments">
Add Comment
<%= form_for #post, :url => {:action => 'update', :id => #post.id}, :html => { :'data-type' => 'html', :id => 'create_comment_form' } do |f| %>
<%= f.fields_for :comments, #new_comment do |comment_fields| %>
<%= comment_fields.text_area :content %>
<%end%>
<div class="validation-error"></div>
<%= f.submit %>
<% end %>
</div>
Post Controller
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
#comments = #post.comments.all
format.html { redirect_to({:action => :show, :id => #post.id}, :notice => 'Post was successfully created.') }
format.xml { render :xml => #post, :status => :created, :location => #post }
else
format.html { render :action => "new" }
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
end
end
end
I was originally thinking you could just set it as a default or a before_save in the model. But models don't have access to current_user. So it's probably best to just set the current user in the controller. It's not as DRY as putting it in the model but it's less hackey and potentially problematic this way.
def update
#post = Post.find(params[:id])
#post.attributes = params[:post]
#post.comments.each do |comment|
comment.created_by = current_user if comment.new_record?
end
respond_to do |format|
if #post.save
#comments = #post.comments.all
format.html { redirect_to({:action => :show, :id => #post.id}, :notice => 'Post was successfully created.') }
format.xml { render :xml => #post, :status => :created, :location => #post }
else
format.html { render :action => "new" }
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
end
end
end
Just want to point out that it is possible to access current_user in the model scope. In this case I don think it is necessary, as the solution from #aNoble should work. So if is possible to set the current_user from the controller, I would prefer that.
In short, we add a method to the User class
class User < ActiveRecord::Base
cattr_accessor :current_user
def self.current_user
#current_user ||= User.new("dummy-user")
end
...
end
and in your application controllor, we add a before_filter that sets it. Make sure to call this filter after your authentication is done.
class ApplicationController < ActionController::Base
before_filter { |c| User.current_user = current_user }
end
And, then inside your Comment-model you could just do something like
class Comment
before_create :set_user
def set_user
created_by = User.current_user unless created_by
end
end
(so I only set the created_by if it was not yet set, and only upon creation of a new comment).