Rails: controller method reading wrong model - ruby-on-rails-3

I've got two models (Articles and Documents) and I'm working with them from a third controller (called Share). I've written this method in that controller to track clicks on articles and the like:
def read_more(a)
#article = Article.find(a)
impressionist(#article)
end
And for some bizarre reason my app tries to find a Document with an ID of, say, 17, instead of an Article. I'm completely stumped.
Any ideas? Cheers!
EDIT:
The log readout is:
Started GET "/share/read_more/17" for 127.0.0.1 at 2012-12-17 09:37:49 +1100
Processing by ShareController#show as JS
Parameters: {"ftp"=>"read_more", "id"=>"17"}
Document Load (0.1ms) SELECT "documents".* FROM "documents" WHERE "documents"."id" = ? LIMIT 1 [["id", "17"]]
Completed 500 Internal Server Error in 1ms
ActiveRecord::RecordNotFound (Couldn't find Document with id=17):

I figured out the answer, should anyone else come into a similar issue.
def read_more
#article = Article.find(params[:id])
impressionist(#article)
render :json => "Read."
end
Apparently you can't have arguments in controller methods.

Related

How can I re-build nested attributes fields on form validation errors in Rails 3

I have a simple form for Recommendations. REcommendations has_many Assets.
so in my controller I am doing a simple:
6.times {#recommendation.assets.build}
My issue occurs when I try to save the Recommendation and there are Validation errors. My Create action:
def create
#recommendation = Recommendation.new(params[:recommendation])
#recommendation.user_id = current_user.id
respond_to do |format|
if #recommendation.save
format.html { redirect_to thankyou_path, notice: 'Recommendation was successfully created.' }
else
6.times {#recommendation.assets.build} if #recommendation.assets.blank?
render action: "new"
end
end
end
running this page and submitting (with validation errors) causes the following log output and a http 406 error
Started POST "/categories/1/awards/9/recommendations" for 127.0.0.1 at 2013-01-07 11:50:13 -0800
Processing by RecommendationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8PVfFZGa72+3KU/km2weZhNy0rxRfp0Qd+CkHdBoQM8=", "recommendation"=>{"nominee"=>"", "title"=>"", "department"=>"", "award_id"=>"9", "summary"=>"", "accomplishments"=>"", "caption"=>"", "url"=>"", "supervisor"=>"You ARE NOT the nominee’s direct manager / supervisor", "approvals_attributes"=>{"0"=>{"email"=>""}}}, "commit"=>"Save/Submit", "category_id"=>"1", "award_id"=>"9"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 2 LIMIT 1
(0.2ms) BEGIN
(0.1ms) ROLLBACK
Rendered shared/_recommend_timeline.html.erb (1.2ms)
Award Load (20.1ms) SELECT "awards".* FROM "awards" WHERE "awards"."id" = 9 LIMIT 1
Rendered recommendations/_form.html.erb (66.7ms)
Rendered recommendations/new.html.erb within layouts/application (69.8ms)
(0.5ms) SELECT COUNT(*) FROM "recommendations" WHERE "recommendations"."user_id" = 2
(0.6ms) SELECT COUNT(*) FROM "approvals" WHERE "approvals"."email" = 'tj#ravennainteractive.com' AND "approvals"."approved" IS NULL
Completed 406 Not Acceptable in 556ms (Views: 188.6ms | ActiveRecord: 31.5ms)
I have looked at multiple questions on stack that seem similar but
I'm not sure there is enough information to be able to answer with much confidence, but I don't think you want to rebuild exactly 6 times. Depending on your model setup, the validation could nullify one, but not all of the associations.
Perhaps you should try:
(6-#recommendation.assets.count).times {#recommendation.assets.build}
My guess is that your view is expecting exactly 6 assets but only finding somewhere from 1-5 after the invalid ones were thrown out, and that this is causing an internal error.
If that doesn't fix it, I think you may need to provide more information about what validations are running on assets, and what your view looks like.

Rails: update_column works, but not update_attributes

I have a simple model:
class Reply < ActiveRecord::Base
attr_accessible :body
belongs_to :post
end
In my controller, I have a simple update method:
def update
#reply = Reply.find(params[:id])
if #reply.update_attributes!(params[:reply])
render :js => "alert('I am trying to update!')"
else
render :js => "alert('<%= #reply.errors %>')"
end
end
This doesn't throw an error, but neither does it actually update the reply. Instead, I get the "I am trying to update!" message, like everything worked. But when I reload the page and look at the reply, it has the same text. It hasn't actually been updated. If I replace update_attributes with:
#reply.update_column(:body, params[:reply][:body])
It works fine. If I use:
#reply.update_attribute(:body, params[:reply][:body])
It once again doesn't work. Any idea what's going?
In my log, I have this:
Started PUT "/posts/2/replies/20" for 127.0.0.1 at 2013-01-19 10:39:57 -0600
Processing by RepliesController#update as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Xot7E+ldXiBm0hVvw5XUP/U5guJU2g8e4QaLbDVGzDE=", "reply"=>{"body"=>"Updated text."}, "commit"=>"Submit Revision", "post_id"=>"2", "id"=>"20"
[1m[35mUser Load (1.0ms)[0m SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
[1m[36mReply Load (0.0ms)[0m [1mSELECT `replies`.* FROM `replies` WHERE `replies`.`id` = 20 LIMIT 1[0m
[1m[35m (1.0ms)[0m BEGIN
[1m[36mPost Load (0.0ms)[0m [1mSELECT `posts`.* FROM `posts` WHERE `posts`.`id` = 2 LIMIT 1[0m
[1m[35m (0.0ms)[0m COMMIT
Rendered replies/_reply_content.html.erb (502.0ms)
Rendered replies/update.js.erb (505.0ms)
Completed 200 OK in 849ms (Views: 484.0ms | ActiveRecord: 94.0ms)
The three methods you are using do different things:
update_attributes tries to validate the record, calls callbacks and saves;
update_attribute doesn't validate the record, calls callbacks and saves;
update_column doesn't validate the record, doesn't call callbacks, doesn't call save method, though it does update record in the database.
If the only method that "works" is update_column my guess is that you have a callback somewhere that is throwing an error. Try to check your log/development.log file to see what's going on.
You can also use update_attributes!. This variant will throw an error, so it may give you information on why your model isn't saving.
You should use update_attributes and avoid the two other methods unless you know exactly what you are doing. If you add validations and callbacks later to your model, using update_attribute and update_column can lead to nasty behaviour that is really difficult to debug.
You can check this link for more info on that.
I had this same issue, but with Rails 4. The issue happens when you have params[] in update_attribute. In Rails 4 with strong parameters
#reply.update_attributes(params[reply_params])
should be
#reply.update_attributes(reply_params)
I'm not to familiar with Rails 3 but this should be the issue:
#reply.update_attributes(params[:reply])
should be
#reply.update_attributes(:reply)
A gut guess would be to say that you have a mass assignment problem and should add your attributes in your model like this
attr_accessible: :your_attribute, :your_attribute2

working on rails 3 tutorial by hartl and stuck on 12.3.4 - New Status Feed

I'm stuck on the last exercise in the Hartlt book 12.3.4 where you define the status feed for yourself and the users you are following. I'm a Rails newbie so just let me know if I need to post additional information.
When I tail the development log I can see will_paginate fire the SQL to gather the initial records, and the initial page looks fine when it is served up. When I click a link to go to any another page, it appears will_paginate doesn't fire the SQL to get retrieve more data from the database as the next page is server up fine, but there is no data.
There are also no new entries in the development log and maybe I'm wrong, but I think this indicates will_paginate didn't hit the database.
I tried to include all the relevant code snippits below. Happy to send anything that's missing.
Here is my pages_controller.rb
def home
#title = "Home"
if signed_in?
#micropost = Micropost.new
#feed_items = current_user.feed.paginate(:page => params[:page])
end
end
Here is my user.rb
def feed
Micropost.from_users_followed_by(self)
end
Here is my microposts.rb
scope :from_users_followed_by, lambda { |user| followed_by(user) }
private
def self.followed_by(user)
following_ids = %(SELECT followed_id FROM relationships
WHERE follower_id = :user_id)
where("user_id IN (#{following_ids}) OR user_id = :user_id",
:user_id => user)
end
NOTE: In the video tutorial (chapter 12, time = 02:06:00) and the book (page 517, listing 12.44) Harlt uses the variable "followed_ids" instead of "following_ids". In the virgin sample code you can download from his site the variable name is "following_ids", and I have tried it both ways - but it fails.
Bottom line - the dev log shows will_paginate retrieving the first batch of data, but it never goes back to the database for additional data.
Can anyone suggest what I can take a look at to resolve my problem?
Many thanks.
do you have more records than will fit on one page?
If not, it may be that will_paginate is doing a count first.
Then deciding not to load any records.
Get into the console and try it out.
$ rails console
user = User.find(23)
# the same user you're logged in as
user.feed.count
# is it more than one page?
user.feed.paginate(:page => 1)
# 20 records?
user.feed.paginate(:page => 2)
# nothing?
Also:
in your example scope :from_users_followed_by, lambda { |user| followed_by(user) } is redundant.
You may as well just say;
def feed
Micropost.followed_by(self)
end

Rails 3.1 custom controller action keeps asking for ID even when route is specified

I'm trying to add a custom action ('last_five') to a controller.
My routes are specified as:
people_last_five GET /people/last_five(.:format) {:action=>"last_five", :controller=>"people"}
(i.e. that's the output of rake_routes).
But when I browse to /people/last_five I get the following error.
Started GET "/people/last_five" for XXX.XX.XXX.XXX at Sun May 15 22:03:18 +0000 2011
Processing by PeopleController#last_five as HTML
User Load (1.4ms)^[[0m SELECT users.* FROM users WHERE users.id = 3 LIMIT 1
Completed in 86ms
ActiveRecord::RecordNotFound (Couldn't find Person without an ID):
I thought this was a problem in my routes.rb
In my routes.rb I currently have:
get 'people/last_five'
resources :people
I've also tried
resources :people do
get 'last_five', :on => collection
end
but that gives the same results.
Why is rails trying to get an ID when there is no "/:id/" in the route?
This even happens when I specify the route as '/people/:id/last_five' and pass it a dummy id. In that case it still tells me ActiveRecord::RecordNotFound (Couldn't find Person without an ID).
I have this problem even when I reduce the action itself to a stub for debugging, so I don't think that's the problem. In my controller:
# GET /people/last_five
def last_five
logger.info "LAST FIVE IS BEING CALLED"
##people = Person.last_five
#respond_with #people do |format|
# format.json { render :json => #people }
#end
end
Any idea what's going on here? It seems like rails is being told to get an ID by something outside of routes.rb. I've looked everywhere I can think.
Any leads are HIGHLY appreciated.
Thanks.
EDIT:
My PeopleController begins like so:
before_filter :authenticate_user!, :except => []
filter_resource_access
respond_to :html, :js, :json
Per the discussion on your questions, the cause is a before/around filter interfering rather than an issue with your specific action. Your application is searching for a User, so it may be authentication-related.
Are you sure this goes in Control, and not in Model? Rails doesn't want Model stuff in Control.

Troubleshooting empty params[] hash since Rails3 Upgrade

I have a named route that tests properly in the console and shows the :url_title which should be included in params[], yet params[] is always empty.
The question is, why is params[] empty? My expectation is it should have params[:url_title].
I also removed this route and used the default resource and params[] is still empty.
I've been checking params by using logger.
My app is an upgrade from Rails 2.3.5 to Rails 3.0.3.
Here's a code summary of what's going on.
# this is my route
match 'papers/:url_title' => 'papers#show', :as => :permalinkpaper
# this is link_to and the generated url being called
<%= link_to paper.title, paper_path(paper.url_title) %>
http://localhost:3000/papers/great-passion
# which properly matches to this controller#action for papers#show
def show
#paper = Paper.where(:url_title => params[:url_title]).first()
PaperHistory.add( current_user, #paper.id )
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #paper }
format.json { render :json => #paper }
format.mobile # { render :layout => false }
end
end
# which generals this error because the Paper looking returns noting because the params[:url_title] is nil
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
# the log stack trace
Started GET "/papers/great-passion" for 127.0.0.1 at Mon Jan 24 23:04:04 -0600 2011
Processing by PapersController#show as HTML
SQL (0.7ms) SHOW TABLES
SQL (0.5ms) SHOW TABLES
Paper Load (0.7ms) SELECT `papers`.* FROM `papers` WHERE (`papers`.`url_title` IS NULL) ORDER BY title LIMIT 1
Completed in 119ms
RuntimeError (Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id):
app/controllers/papers_controller.rb:43:in `show'
# I've validated the route in the console and it seems to know :url_title is the proper value
>> r = ActionController::Routing::Routes
>> r.recognize_path "/papers/great-passion"
=> {:action=>"show", :url_title=>"great-passion", :controller=>"papers"}
UPDATE: I have found that params[] are NOT empty when values are in the URL, such as when performing a search.
http://localhost:3000/papers?utf8=%E2%9C%93&keywords=passion
This successfully produces
Started GET "/papers?utf8=%E2%9C%93&keywords=passion" for 127.0.0.1 at Tue Jan 25 00:20:07 -0600 2011
Processing by PapersController#index as HTML
Parameters: {"utf8"=>"✓", "keywords"=>"passion"}
params: utf8✓keywordspassion
Thanks to all for the help. I was able to disassemble my app piece by piece and finally get params[] to show up.
The culprit was the open_id_authentication plugin.
I had some plugins in the vendors directory, so I removed them all and after hurdling a few resulting errors (b/c the plugins were now missing) everything worked. I systematically replaced plugins, and when I got to open_id_authentication found that the params[] again disappeared.
I had a different solution for this problem that I'll post here just in case somebody runs into the same issue. I was working on a password reset part of the site and tried various things such as putting the URL in manually, specifying the controller and action, using a bare (minimal) form and such, but all of it failed. The error given was the e-mail parameter was blank.
A look into the Exceptional logs showed that not just the e-mail parameter was blank, but even the UTF-8 check mark was missing. The only things in the params hash were the controller and action. Reloading the page also didn't turn up the usual spiel about re-submitting information.
It turns out the problem was in SSL. The page was trying to use SSL but didn't have permission and it was somehow silently killing the form. Hope that helps somebody.