Implementing a specific action for a model that respond_with(#object) - ruby-on-rails

I have a Subscription model that users can create. Users needs to validate a PIN sent to them to confirm subscription after is created. I'm having a bit of trouble trying to figure it out the best way to implement this.
I implemented a confirms controller with two new and create actions.
def new
#confirm = Subscription.new
end
def create
#keyword = Keyword.joins(:shortcode).where("shortcodes.shortcode = ? and shortcodes.country = ?",params[:subscription][:shortcode],params[:subscription] [:country]).find_or_create_by_keyword(params[:subscription][:keyword])
if #confirm = Subscription.where(:phone => params[:subscription][:phone], :country => params[:subscription][:country], :keyword_id => #keyword.id).last
#confirm.check_subscription_pin(params[:subscription][:pin])
respond_with(#confirm)
elsif #confirm && #confirm.errors.any?
flash[:notice] = #confirm.errors
render :action => :new
else
flash[:notice] = "Subscription not found."
render :action => :new
end
end
This solution doesn't look very convincing since I would like to always respond_with(#confirm) to allow REST POST done via JSON.

There's no params[:subscription] received when you make your curl call. Phone and Pin are nested within subscription, hence the error.
<pre>undefined method `[]' for nil:NilClass</pre>
I don't know how to make a curl call with nested params by the way.

Related

Get any id to any user exists in the database

I am new to rails and have a task that asks me to send an invitation for any user to be admin in my magazine here is my piece of code
def invite
inviteUser = { 'user_id' => current_user.id, 'Magazine_id' => params[:id] }
CollaborationInvitation.create(inviteUser)
#magazine = Magazine.find(params[:id])
redirect_to :back
rescue ActionController::RedirectBackError
redirect_to root_path
end
I need to replace current_user.id with something that refers to any user's id which exists in my database to send him an invitation to be admin with me I tried to add #User=Users.All and then pass it as a variable but it got me an error I tried a lot of things but every time I get an error except for adding current_user.id
ps: I am using devise for authentication
You asked a couple things, and it is kind of confusing what you want to do.
Here is how you get all ids of records in a model.
Rails4: User.ids
Rails3: User.all.map(&:id)
Or (not sure if #pluck is in Rails 3 or not)
User.pluck(:id)
If you want to get a random user (you mentioned "any user") you could do.
User.find(User.pluck(:id).sample)
Though I think what you really want to do is to pass the id or some other attribute of a user as a param to the action and send that user an invitation.
Presumably you either have a post or get route for "users#invite" (the action you wrote in your question). You can add a named parameter there or you can pass a url param or if you are using a post route, you could add the param to the post body.
Then in your contoller you can do something like this (I'll use email as an attribute):
def invite
#user = User.find_by(email: params[:user_email])
#Rails 3 like this
# #user = User.find_by_email(params[:user_email])
# now do stuff with user
end
User.all will return you the collection of users. So,
Find the user object to get an id...
Try this code....
def invite
inviteUser = { 'user_id' => User.find_by_email('user#example.com').id, 'Magazine_id' => params[:id] }
CollaborationInvitation.create(inviteUser)
#magazine = Magazine.find(params[:id])
redirect_to :back
rescue ActionController::RedirectBackError
redirect_to root_path
end
You can try
User.last.id
or
User.find_by_email("xyz#test.com").id
or
User.where(email: "xyz#test.com").first.id
Replace xyz#test.com with desired user email address. To get more details on rails active record query interface, please read rails guides http://guides.rubyonrails.org/active_record_querying.html

Rails 4 | Properly creating and saving in controller

I'm creating a messaging system of sorts. It's part of a bigger overall system in Rails 4.
Anyway, to setup my question briefly I have users who can both send and receive messages. So in my "new" users' view I send a parameter [:receiver_id] to the message controller when creating a new message.
My question is how do I get the #send_to variable down to the create action properly. I had to send it into the messages#new action via the receiver_id from the users' view. Do I store it as a message parameter somehow or make it a hidden parameter?
Here is my messages controller
class MessagesController < ApplicationController
def new
#message = Message.new
#this :receiver_id is being sent from the show view in the user controller / view
#it is being used to pass a parameter
#send_to = User.find(params[:receiver_id])
#message.sender = current_user
#message.receiver = #send_to
#the form_for should save the message with the RESTful action of create method in this controller
end
def create
debugger
#messasge = Message.create!(message_params)
redirect_to users_path
end
def index
#messages = current_user.messages
end
def sent
#messages = current_user.messages
end
def message_params
params.require(:message).permit!
end
end
I know from rails routing mostly about RESTful actions, and yes I have read over the routing guide again before writing this.
EDIT:
I have moved these two lines down into the create function. The #send_to needs the :receiver_id though.
#message.sender = current_user
#message.receiver = #send_to
You should implement an asynchronous request for sending messages, cause it might be annoying for system users to redirect to another page just to send a message. From the above snippets it is not known (the logic).
Having an asynchronous request, which would serve a dialog with new message form, next step is just to send form data to messages#create action. I assume that user, while fulfilling form data, can select somehow message recipient.
Action new does not need to know who is the message receiver.
Don't use Message.create! (with !) because it will raise an exception if creation fails. Use save instead and handle case if it would fail,
e.g:
def create
#message = Message.new params[:message]
#message.save
respond_to do |f|
f.json do
render :json => {:success => #message.persisted?, :message => #message}.to_json
end
end
end

Is there a way to get the visitors city and country in Rails controller?

In my current app, i use Geocoder gem to get the city and the country of the visitor. I use hidden fields in my view to get these details. When the login form is submitted, these details will be sent to the controller and the controller will save them to the database. When I try to get these details directly from the controller by using
request.location.city
It will assigning a blank value to the database. If I use hidden fields in the view, some one can temper with them right? So, how can I fix this?
You should store visitor information before you render any content:
class UsersController
def new
# I suspect that, for fast insert, you should probably use a NoSQL database
# to perform `store!` or even just write it to a log file
Visitor.store!(:city => request.location.city, :ip => request.ip)
end
def create
#user = User.build(params[:user].merge(:city => request.location.city))
if #user.valid?
#user.save
flash[:notice] = "You've been registered!"
redirect_to user_dashboard_path
else
flash[:notice] = "Couldn't register your account"
render action: "new"
end
end
end

How do I make an API call to viralheat on submit and then parse and save the JSON response?

I want to send a request via Viralheat's API in my controller's update method so that when a user hits the submit button, an action is completed and the API call is made. I want to post to http://www.viralheat.com/api/sentiment/review.json?text=i&do&not&like&this&api_key=[* your api key *]
This will return some JSON in the format:
{"mood":"negative","prob":0.773171679917001,"text":"i do not like this"}
Is it possible to make that API call simultaneously while executing the controller method and how would I handle the JSON response? Which controller method would I put it in?
Ultimately I'd like to save the response mood to my sentiment column in a BrandUsers table. Submit is in main.html.erb which then uses the update method.
Controller
def update
#brand = Brand.find(params[:id])
current_user.tag(#brand, :with => params[:brand][:tag_list], :on => :tags)
if #brand.update_attributes(params[:brand])
redirect_to :root, :notice => "Brand tagged."
else
render :action => 'edit'
end
end
def main
#brands = Brand.all
if current_user
#brand = current_user.brands.not_tagged_by_user(current_user).order("RANDOM()").first
end
With the wrest gem installed, you could do something like
params[:api_key] = "your key"
url = "http://www.viralheat.com/api/sentiment/review.json"
response = url.to_uri.get(params).deserialize
response would contain the json already turned into a hash. So you can access the mood with
response[:mood]

is this a secure approach in ActiveRecords in Rails?

I am using the following for my customers to unsubscribe from my mailing list;
def index
#user = User.find_by_salt(params[:subscribe_code])
if #user.nil?
flash[:notice] = "the link is not valid...."
render :action => 'index'
else
Notification.delete_all(:user_id => #user.id)
flash[:notice] = "you have been unsubscribed....."
redirect_to :controller => 'home'
end
end
my link looks like;
http://site.com/unsubscribe/32hj5h2j33j3h333
so the above compares the random string to a field in my user table and accordingly deletes data from the notification table.
My question; is this approach secure? is there a better/more efficient way for doing this?
All suggestions are welcome.
I don't see anything wrong in your solution if the action doesn't require authentication.
If the action requires authentication then I would make sure that the salt belongs to the current user
#user = User.find_by_id_and_salt(current_user.id, params[:subscribe_code])
Is it all that important that the user be informed if their unsubscribe link was wrong? What are the chances of that anyway? Wasn't it generated programmatically and that program is tested? If the answer is "yes" (hint: it should be) then my suggestion would be to always tell the user that they've unsubscribed, regardless of what happened.
def index
begin
#user = User.find_by_salt!(params[:subscribe_code])
rescue ActiveRecord::RecordNotFound
ensure
#user.notifications.delete_all if #user
flash[:notice] = "You have been unsubscribed."
redirect_to :action => "index"
end
end
I think this is safer:
#user = User.find :all, :conditions => { salt => params[:subscribe_code] }
That way you are sure that Rails knows params[:subscribe_code] is to be escaped. There are probably lots of ways to write it that would work though.
your link should be
http://site.com/unsubscribe/?subscribe_code=32hj5h2j33j3h333
otherwise "32hj5h2j33j3h333" will get as a params[:id]
else is fine. Assuming subscribe_code will be unique.

Resources