Bad routing, rails - ruby-on-rails-3

I didn't figure out the mechanics of the routing yet..
I have a User, Msg and comment model.
A User creates a Msg and inside the msg i'd like to put simple text box for comments. similar to twitter.
However, When the the form is submitted (using the form below) instead of returning to localhost/msgs/:id it returns to localhost/comments.
I have no view for /comments and I don't want to have. I want all comments to be displayed in msg/:id page.
comments controller:
class CommentsController < ApplicationController
before_filter :authenticate
def create
msgid = flash[:msg]
#current_msg = Msg.find(discid)
#comm = #current_msg.comments.build(params[:comment])
#comm.user_id = current_user.id
#comm.msg_id = msgid
puts discid
if #comm.save
flash[:success] = "Comment posted"
redirect_to msg_path(discid)
else
flash[:error] = "Comment was not posted."
redirect_to msg_path(discid)
end
end
route.rb
match '/comments' , :to => 'msgs#show'
resources :users
resources :msgs
since the comments are displayed in the show view of the msgs here is the show action in the msgs controller
def show
#msg= Msg.find(params[:id])
#title = #msg.title
#comment = Comment.new
#comments = #msg.comments.all
flash[:msg] = #msg.id
end
The error I get is
ActiveRecord::RecordNotFound in MsgsController#show
Couldn't find Msgwithout an ID
and it points to line 46 which at the moment is #msg = Msg.find(params[:id])
If I remove the route line and put a regular resources :comments I get a missing template for comments/create..
Help is appreciated.

Issue solved.. I add a :id => discid in the redirecא_to..
Also used Template is missing to understand the issue

Related

Why isn't my search method working in Ruby on Rails?

In my Ruby on Rails application, I have a cinema system and am trying to return the screen a showing is in when a user searches for the showing.
To display the search drop down I am using this code in my _application.html.erb:
<%= render( :partial => '/screen_lookup', :locals => {:showings => #showings = Showing.all, :my_path => '/screens/display_screens_by_showing' })%>
Which renders the search from the _screen_lookup.html.erb:
<%= form_tag my_path, :method=>'post', :multipart => true do %>
<%= select_tag ('showings_id'),
options_from_collection_for_select(#showings, :id, :showing_times, 0 ),
:prompt => "Showings" %>
<%= submit_tag 'Search' %>
<% end %>
And uses the display_screens_by_showing in the screens_controller:
def display_screens_by_showing
#screens = Screen.showing_search(params[:showing_id])
if #screens.empty?
# assign a warning message to the flash hash to be displayed in
# the div "feedback-top"
flash.now[:alert] = "There are no films of that genre."
# return all products, in alphabetical order
#screens = Screen.all
end
render :action => "index"
end
And this searches using the method in the screen.rb model:
def self.showing_search(showing_id)
screen = Showing.where("id = ?", showing_id).screen_id
self.where("id = ?", screen)
end
Now, the problem I am having is that because a showing belongs_to a screen, and a screen has_many showings, I need to be able to search for the showing, and store that showing's screen_id in a variable to search for the screen that showing is in with, which I have tried doing in the model:
screen = Showing.where("id = ?", showing_id).screen_id
self.where("id = ?", screen)
But the error I am getting is:
NoMethodError in ScreensController#display_screens_by_showing
undefined method `screen_id' for #<ActiveRecord::Relation []>
These are the model relationships:
showing.rb:
class Showing < ActiveRecord::Base
belongs_to :screen
end
screen.rb:
class Screen < ActiveRecord::Base
has_many :showings
end
What code will get my search working?
The problem is that where doesn't return a record, it returns a relation that can be enumerated or chained, instead you want to use find or find_by to return a single record, which is kind equivalent to where + first
screen = Showing.find(showing_id).screen_id
which is sort of like doing
screen = Showing.where(id: showing_id).first.screen_id
If you want to pass a hash you can use find_by which will be like this
screen = Showing.find_by(id: showing_id).screen_id
PS:
I'm not sure what you're doing exactly, but i think those two lines can be merged into a single query ( not sure what it should be returning, but I'm assuming a screen )
def self.showing_search(showing_id)
Showing.find(showing_id).screen
end

Process form data before creating table entry

Backstory: I'm building a site that takes in a Soundcloud URL as part of a post. Currently, I store the link they provide and, when a user loads their feed view, I retrieve the associated image / title / favorite count etc. via my post_helper. I have quickly come to realize that this is not scalable and is hurting load times.
So, what I think I should do (feel free to tell me that there is a better way), is to retrieve the SC/YT metadata on form submit and store it along with the other post data (id, user, content etc.) in the posts' table entry. How would I go about calling the helper methods to retrieve such on form submit and include the metadata in the submitted params?
post_helper.rb excerpt:
def soundcloud_info(soundcloud_url, type)
begin
resolve = scClient.get('/resolve', :url => soundcloud_url)
track_info = scClient.get("/tracks/#{resolve.id}")
rescue Soundcloud::ResponseError => e
%Q{ Error: #{e.message}, Status Code: #{e.response.code} }
end
if type == "title"
%Q{#{track_info['title']}}
elsif type == "image"
%Q{#{track_info['artwork_url']}}
elsif type == "favCount"
%Q{Favorite count: #{track_info['favoritings_count']}}
end
end
post_controler.rb excerpt:
def create
#post = current_user.posts.build(params[:post])
if #post.save
flash[:success] = "Your post was successful!"
redirect_to root_url
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
end
end
So apparently it's pretty straight forward... all I need to do is modify the parameters in the controller before I call #post = current_user.posts.build(params[:post]). My issue was that I was trying to do so in the helper.
I haven't quite adapted the whole thing to get all my required fields, but here's an example of how I have adapted the create method to pull the api URL out if someone submits SoundCloud's embed iframe.
micropost_controller.rb excerpt:
def create
#url = params[:post][:link_html]
if #url[/^.*src="(https|http):\/\/w.soundcloud.com\/player\/\?url=(.*)">/]
params[:post][:link_html] = CGI::unescape($2)
end
#post = current_user.posts.build(params[:post])
if #post.save
flash[:success] = "Your post was successful!"
redirect_to root_url
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
end
end

Devise Invitable optional custom message

I would like to add an optional text_field to add an optional message to the invitation email. So if nothing put into the message then the standard message from invitation_instructions.html.erb should be send otherwise the message of the text_field.
How to do this in devise?
To accomplish this you can use your own mailer instead of having devise email things for you.
Here is how to do it:
class User < ActiveRecord::Base
attr_reader :raw_invitation_token
end
class InvitationsController < Devise::InvitationsController
def create
#from = params[:from]
#subject = params[:invite_subject]
#content = params[:invite_content]
#user = User.invite!(params[:user], current_user) do |u|
u.skip_invitation = true
end
#user.deliver_invitation
email = NotificationMailer.invite_message(#user, #from, #subject, #content)
end
end
class NotificationMailer < ActionMailer::Base
def invite_message(user, venue, from, subject, content)
#user = user
#token = user.raw_invitation_token
invitation_link = accept_user_invitation_url(:invitation_token => #token)
mail(:from => from, :bcc => from, :to => #user.email, :subject => subject) do |format|
content = content.gsub '{{first_name}}', user.first_name
content = content.gsub '{{last_name}}', user.first_name
content = content.gsub '{{full_name}}', user.full_name
content = content.gsub('{{invitation_link}}', invitation_link)
format.text do
render :text => content
end
end
end
end
The raw_invitation_token only exists in newer versions of devise_invitable (compatible with devise >= 3.1).
We are essentially skipping the devise invitation process all together and using our own mailer. We take the content as a parameter and send it as the body of the email. We even substitute placeholders with their actual values.
This solution will give you a lot of flexibility to whatever you want with emails. You can even add a tracking pixel to it if you would like.

How to tell if something has been read in Rails for notification

I'd like to implement a simple notification system on my site where an unseen/unread item is displayed to the user. Similar to the one used across Stack Exchange for the user's inbox where unread comments on questions, etc are displayed.
I came across this question that provides an overview of how I'd do this. What I'm confused about is how to figure out if something has been read. I could add a read_at column but how do I actually fill it? If anyone could help me with some basic guidance I'd appreciate it!
UPDATE #1: What if I add a conditional to my Item#show action where I check the user_id (ID of the user creating the item) against current_user.id. Something like the below:
unless #item.user_id == current_user.id
#item.read_at = Time.now
end
UPDATE #2: Using the code below, I'm attempting to update the message's read_at if its recipient_id matches the current_user ID. However it's not working.
def show
#message = Message.find(params[:id])
if #message.recipient_id == current_user.id
#message.read_at == Time.now
#message.save
end
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #message }
end
end
FINAL UPDATE: Thanks to #prasvin, here's my solution. I added a read_at column to the object. The object also has an existing recipient_id column. So in my Controller's show action, I put the following:
def show
#message = Message.find(params[:id])
if #message.recipient_id == current_user.id
#message.update_attributes(:read_at => Time.now)
end
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #message }
end
end
Then in my helper.rb file:
def new_messages
Message.where(:recipient_id => current_user.id, :read_at => nil).count
end
And in my layout:
<% if new_messages > 0 %><span class="notification"><%= new_messages %></span><% end %>
How about filling in read_at column in show action, i.e. we have the object in the show action,and then update its read_at attribute before redering the page

Basic Rails 3 saving parent object with association object

I have a basic rails question where I need to save two associated objects.
The association is Rtake has_many :companies and Company belongs_to :rtake
def create
#rtake = RTake.new(:email => params[:contact_email])
#rtake.role = "PROVIDER"
#company = #rtake.companies.build(params[:company])
#company.rtake = #rtake
respond_to do |format|
if #company.save_company_and_rtake
format.html{ redirect_to admin_companies_url}
else
flash.now[:errors] = #company.errors.full_messages.join(", ")
format.html{ render "new" }
end
end
end
In my company.rb class I have
def save_company_and_rtake
status1 = self.save(:validate => false)
status2 = self.rtake.save(:validate => false)
status = status1 && status2
status
end
The problem I face is that the company.rtake_id remains nil. Ideally shouldn't the company.rtake_id get updated to the #rtake.id after save.
I know I am missing something basic. Would appreciate some help.
You shouldn't need this line:
#company.rtake = #invitation
#invitation is nil from what you've shown .
But also, when you built the #company, #rtake.id isn't set because it hasn't been saved.
#company = #rtake.companies.build(params[:company])
#company.rtake = #rtake
#rtake.companies.build(params[:company]) This already means #company.rtake == #rtake. it's redundent here.