How Modify route standard Rails3? - ruby-on-rails-3

I am using Rails3 and I would like make one request for get one parameter token to my controller different of ID to my action "confirms "in my controller,can someone help me?
I believe is a problem in my route.
such as:
http://0.0.0.0:3000/emails/1QWD3DF2Cd/confirms or http://0.0.0.0:3000/emails/confirms/1QWD3DF2Cd
`
class EmailsController < ApplicationController
def confirms
#email = Email.find(params[:token])
#email.confirmed # other method in model emails which mark as enable
end
end
`

You can do this
Add this to your routing.rb file.
match '/emails/confirms/:token' => 'emails#confirms', :as => 'confirms_emails'

Related

Rails Routing: One controller. One model with type. Multiple routes

I have one model named Factors, which has two types: ['personal', 'advisor']
I want to have one controller FactorsController that has all the same actions for both types of Factors, but only ever uses one type. The type that it uses is based on the route used to get there. For example,
/personal would route to factors#index and populate #factors with Factor.personal
/advisors would route to factors#index and populate #factors with Factor.advisors
How would I go about setting this up?
You can add to the routes
type_regexp = Regexp.new([:personal, :advisor].join("|"))
resources :factors, path: ':type', constraints: { type: type_regexp }
and you will be able to user params[:type] in the controllers, that gives you flexibility in case you wanna changes the routes in the future.
This also gives you the ability to use factors_path(type: :personal) in the views.
You can add this to your routes:
resources :factors, :path => :personal
resources :factors, :path => :advisor
This will then have both /personal and /advisor. You'll then want to have factors#index determine which path was used (you could use request.url) and populate #factors accordingly.
I would create three controllers:
class PersonalController < FactorController
def factor
Factor.personal
end
end
class AdvisorController < FactorController
def factor
Factor.advisors
end
end
class FactorController < ApplicationController
#all the shared stuff here, using the factor method from each in your methods
end
and then the routes would be:
route '/personal' => PersonalController#index
route '/advisors' => AdvisorController#index

using build method on association in rails 3.2 creating object in memory

I have 2 models like the following
Class Post
has_many :comments, :dependent => :destroy
end
Class Comment
validates_presence_of :post
validates_presence_of :comment
belongs_to :post
end
In Comments controller,
def create
comment = #post.comments.build(params[:comment])
if comment.save
// some code
else
// some code
end
end
When the comment is invalid as per the validation, the comment is not saved. But when the #post object is accessed in the view, it contains a comment object with nil id. This did not happen in Rails 2.3.11. We are upgraded to Rails 3.1 and then now to Rails 3.2. This comment object with nil id disappears when I do #post.reload. We are using REE.
I tried to interchange build and new methods. It had the same result as build. Similar behavior is found across our application. Is it the expected behavior or am I doing something wrong?
This seems like expected behaviour to me.
via http://guides.rubyonrails.org/association_basics.html#belongs_to-association-reference
4.1.1.3 build_association(attributes = {})
The build_association method returns a new object of the associated
type. This object will be instantiated from the passed attributes, and
the link through this object’s foreign key will be set, but the
associated object will not yet be saved.
When you call #post.comments.build(...), Rails:
Creates a new Comment object
sets comment.post_id to #post.id.
Inserts it into the comments array (in memory).
When the validation fails, it doesn't delete the comment and the comment persists in the in-memory comments array. When #post gets to your view, #post.comments still includes that badly validated comment.
As for how to deal with it, I'm not sure. Maybe you could do something like (in your controller)... (Feels pretty ugly though.)
def create
comment = #post.comments.build(params[:comment])
if comment.save
// some code
else
#bad_comment = #post.comments.pop
end
end
I had a similar problem while using rails 3.2
Firstly, you need to create two separate methods in your controller. They will be as follows:
The 'new' method that is used to build your comments using 'build_association'
def new
#post = Post.new
comment = #post.build_comments
end
The 'create' method to actually create your comments using 'create_association'
def create
#post = Post.new(params[:post])
comment = #post.create_comments(params[:post][:comment_attributes])
if comment.save
// some code
else
#bad_comment = #post.comments.pop
end
end
Note: I suggest passing 'comment' attribute as a nested attribute of 'post' through your form using 'fields_for'.
Please refer:
http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

Calling ActiveRecord::Create() from within rails user model not associating new object with user

In my rails user model, I am trying to write a method which will return a list for the current time frame, and in the absence of a list for that time frame, create one which is associated with the user and then return it:
class User < ActiveRecord::Base
def todaysList
today = Time.new
if self.lists.where(:date => today.to_date)
return self.lists.where(:date => today.to_date).first #Get the object, not the ActiveRecord::Relation
else
self.lists.create!(:date => today.to_date) #Make the list, return it!
end
end
My question is, why is it that when I call self.lists.create!(:foo => 'bar'), the user association is not populated?
I've decided to get around this a more sloppy way, by explicitly assigning the user in the create! call, as such:
self.lists.create!( :date => today.to_date, :User_ID = self.id)
however this solution just doesn't seem right.
Thanks in advance and apologies as always for stupid, redundant or badly worded questions.
I would do something like this:
def todays_list
lists.find_or_create_by_date(Date.today)
end
The method name change is just preference.

Is this a case for inheritance?

I have Rails models User, ReadingList and SessionReadingList. A user has many reading lists. A SessionReadingList is a special type of reading list for before a user has registered, stored in the session.
In my ReadingListsController every action is of the form:
def show
if current_user
#load user's reading lists
else
#load session reading list from session
end
end
I'm wondering whether I'd be better off subclassing ReadingListsController so I have e.g. SessionReadingListsController and UserReadingListsController. I don't know how I'd handle the routing then though.
So, is subclassing the solution? If so, do I redirect from the ReadingListsController depending on current_user? Or is there a better way?
You can create a custom route matcher that uses the appropriate controller.
class LoggedInConstraint < Struct.new(:value)
def matches?(request)
request.cookies.key?("user_token") == value
end
end
match 'reading-list' :to => "reading_list#index", :constraints => LoggedInConstraint.new(true)
match 'reading-list' :to => "session_reading_list#index", :constraints => LoggedInConstraint.new(true)

Rails, creating a callback

I want to use an ActiveModel callback to be called after an object has been voted on, the issue is that the gem I'm using (voteable_mongo) to make the model votable doesnt provide like a vote model or callback in my app, so how can I create a callback for it?
set_callback(:vote, :before) do |object|
object.do_something
end
Obviously that vote action I made up, but the gem I'm using has this method, how would you properly extend this method to trigger a callback?
Taking the plugin example as source here's what you could do:
class Post
include Mongoid::Document
include Mongo::Voteable
extend ActiveModel::Callbacks
define_model_callbacks :vote
# set points for each vote
voteable self, :up => +1, :down => -1
def vote(options, value = nil)
_run_vote_callbacks do
super( options, value )
end
end
end
I did not run this code so I am not sure if this is going to work correctly or not, but in the worst case you could alias the vote method using alias_method_chain or just copy and paste the source to inside the _run_vote_callbacks block (really, really ugly, but it's a solution anyway).
EDIT
This could also be done using alias_method_chain, if the code above does not work:
class Post
include Mongoid::Document
include Mongo::Voteable
extend ActiveModel::Callbacks
define_model_callbacks :vote
# set points for each vote
voteable self, :up => +1, :down => -1
alias_method_chain :vote, :callback
def vote_with_callback(options, value = nil)
_run_vote_callbacks do
vote_without_callbacks( options, value )
end
end
end