Activity
Just rewatched the video and realized Chris suggested hidden fields as the best solution for this. So I got it working by adding these hidden fields to my Stripe form:
<%= hidden_field_tag(:plan_id, @plan.id) %>
<%= hidden_field_tag(:plan_seats, @plan.seats) %>
And modifying my controller as such:
def create
@company = Company.friendly.find(params[:company_id])
@plan_id = params[:plan_id] # <<<<
@plan_seats = params[:plan_seats] # <<<<
customer = Stripe::Customer.create(
email: current_user.email,
source: params[:stripeToken],
)
subscription = customer.subscriptions.create(
plan: @plan_id # <<<<
)
@company.users.each do |user|
user.update(
subscribed_at: Time.now,
canceled_at: nil
)
end
current_user.update(
stripe_id: customer.id,
stripe_subscription_id: subscription.id,
card_last4: params[:card_last4],
card_exp_month: params[:card_exp_month],
card_exp_year: params[:card_exp_year],
card_type: params[:card_brand],
stripe_plan_id: @plan_id, # <<<<
invitation_limit: @plan_seats # <<<<
)
redirect_to company_path(@company)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to company_upgrades_path(@company)
end
I worked through the Subscriptions with Stripe video and got everything working fine, with a single Plan ID.
Now I'm trying to modify it to work with multiple Plan ID's to give my users payment options.
I created a model to hold all of my plans, with each plan ID matching the plan ID at Stripe, so that I can pull the ID from params to send to Stripe.
The wall I've hit is that I can't seem to actually send the param ID to Stripe.
What am I doing wrong?
subscriptions_controller.rb
def create
@company = Company.friendly.find(params[:company_id])
@plan = Plan.find(params[:id]) ### This ID works on #show but can't be found in #create
customer = Stripe::Customer.create(
email: current_user.email,
source: params[:stripeToken],
)
subscription = customer.subscriptions.create(
# plan: '001' ### This works
plan: @plan ### This doesn't
)
@company.users.each do |user|
user.update(
subscribed_at: Time.now,
canceled_at: nil
)
end
current_user.update(
stripe_id: customer.id,
stripe_subscription_id: subscription.id,
card_last4: params[:card_last4],
card_exp_month: params[:card_exp_month],
card_exp_year: params[:card_exp_year],
card_type: params[:card_brand],
stripe_plan_id: @plan, ### Need this to work
invitation_limit: @plan.users ### Need this to work
)
redirect_to company_path(@company)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to company_upgrades_path(@company)
end
Posted in Just want to say thanks!
Hoping this isn't too cheesy, but I wanted to take a second to thank Chris for taking the time to make all of these invaluable videos here and to the community for helping me find solutions to problems that I couldn't find elsewhere.
1 year (and 2 days) ago I decided to learn how to code so that I could make my own project management tool. None of the others like Trello or Wrike or Asana gave me a clear enough insight into the overall operations of my company or into the current/upcoming workload of my team. Also, I've always struggled with RSI/Carpal Tunnel type pain and the number of steps these other tools required just to accomplish basic things was ridiculous. 7 clicks just to reschedule a task and return to the page you were just on, really?! lol
Anyways, I managed to finish my app, https://nuvro.com/, something I couldn't have done without GoRails. I not only learned how to implement vital features but learned a ton about rails and coding in general.
Posted in Chartkick doesn't load on Heroku?
nm, found the fix. I had to include the chartkick js tags into the header of my application layouts while including my other js files at the very end of the body, to prevent breaking my wysiwyg editors.
Posted in Chartkick doesn't load on Heroku?
I setup a few charts in my app using Chartkick, which work fine in development but not in production. I have the same "Chartkick is not defined" issue as this guy https://github.com/ankane/chartkick/issues/347 but what fixed it for him didn't for me. I even tried possible fixes found on other SO threads, with no luck.
Anyone have the same problem on Heroku?
Posted in PDF Receipts not working
That did the trick!
Posted in PDF Receipts not working
When I used resources :charges
in my routes it threw an exception due to the lack of a charge ID. It's because of this that I changed my route to resource :charge
Posted in PDF Receipts not working
I just finished working through the pdf receipts video but can't get it to work. I have the webhook working and all charges are displayed properly, but the link to the pdf 404's.
Can you see where I went wrong?
# config/initializers/stripe.rb
class RecordCharges
def call(event)
charge = event.data.object
user = User.find_by(stripe_id: charge.customer)
user.charges.create(
stripe_id: charge.id,
amount: charge.amount,
card_last4: charge.source.last4,
card_type: charge.source.brand,
card_exp_month: charge.source.exp_month,
card_exp_year: charge.source.exp_year
)
end
end
StripeEvent.configure do |events|
events.subscribe 'charge.succeeded', RecordCharges.new
end
# charge.rb
belongs_to :user
def receipt
Receipts::Receipt.new(
id: id,
product: "Nuvro",
company: {
name: "Nuvro LLC",
address: "2040 S Alma School Rd Suite 1-484\nChandler, AZ 85286",
email: "support@nuvro.com",
logo: Rails.root.join("app/assets/images/nuvro-50.png")
},
line_items: [
["Date", created_at.strftime('%B' '%d,' '%Y')],
["Account Billed", "#{user.first_name} #{user.last_name} (#{user.email})"],
["Product", "Nuvro"],
["Amount", "$#{amount / 100}.00"],
["Charged to", "#{card_type} (**** **** **** #{card_last4})"],
["Transaction ID", uuid]
]
)
end
# user.rb
has_many :charges
# charges_controller.rb
def show
@charge = current_user.charges.find(params[:id])
respond_to do |format|
format.pdf {
send_data @charge.receipt.render,
filename: "#{@charge.created_at.strftime("%m-%d-%Y")}-nuvro-receipt.pdf",
type: "application/pdf",
disposition: :inline
}
end
end
# routes.rb
resource :charge # charges#show
# views/companies/edit.html.erb
<% current_user.charges.each do |charge| %>
....
<%= link_to "View Receipt", charge_path(@charge, format: :pdf) %>
...
<%= link_to "View Receipt", charge_path(charge, format: :pdf) %> # tried this, didn't work
I'm missing something obvious, I just know it :)
Thanks Chris, webhooks were indeed the answer.
I just finished following the screencasts on setting up Stripe, everything went well!
I have my app setup to cancel accounts :at_period_end
so that subscribers can continue accessing content through the duration of their subscription.
Question is, how to postpone the removal of their subscription_id from the users table also :at_period_end
?
Thanks for the direction Chris! My activity feed is working perfectly now.
I hadn't realized that I was hitting the db twice, using assign_attributes now and am going to use transactions for notifications next.
I got comments to create properly by noticing the mistakes I had made with:
@comment = current_user.events.create(action: "commented", eventable: @task)
It should have been:
@task.events.create(action: "commented", eventable: @task, user_id: current_user.id)
Abhinay, I personally decided against public_activity because I couldn't get it to work properly with my nested resources. Activity feeds from scratch gave me the control I needed to tweak everything to work with my particular app. Plus I had already setup notifications using Chris' screencast and the activity feed works similarly, really helped keep things streamlined.
After spending more time on this I can see that using the notifications system for an activity feed isn't going to work very well. So moving onto implementing 'activity feeds from scratch'...
I just need to be able to create the events from within controller actions.
Here is what I tried in my comments_controller:
@task_id = params[:task_id]
@comment = Comment.new(comment_params)
@comment.update_attributes(task_id: @task_id, user_id: current_user.id)
@comment.save!
@comment = current_user.events.create(action: "commented", eventable: @task)
(@task.users.uniq - [current_user]).each do |user|
Notification.create(getter: user, doer: current_user, action: 'commented', notifiable: @task)
end
But this prevents comments from being created for some reason.
What am I doing wrong?
I worked through https://gorails.com/episodes/improving-in-app-notifications yesterday and it works great.
I tried to use this same system create activity feeds for my different models, but ran into a problem. Duplicates. Every activity/notification contained (seemingly) duplicate records, most likely due to the fact that a notification record is created for each user. So when I iterate through all notifications it lists out what appear to be duplicates.
- Is there any way to single out one record for each event? I tried pulling out records only for actors, but it didn't work.
As an alternative I also tried working through https://gorails.com/episodes/activity-feed-from-scratch but couldn't figure out how to create event records from within controller actions. I tried this in my comments_controller but it prevented comments from being created:
@comment = current_user.events.create(action: "commented", eventable: @task)
- What's the correct way to create events from within controller actions?
Option 1 would be awesome, option 2 would be great... option 3 (public_activity gem or getstream.io would suck).
Any help is appreciated :)
Posted in How to delete records in a join table?
Thanks Chris!
I actually had a document_attachments controller setup and was getting unilitialized constant errors, which through research I learned could be due to a routing conflict with Refile due to the similar name.
I'll try this again with a different name, maybe document_uploads, and hope the convention over configuration thing doesn't bite me.
Posted in How to delete records in a join table?
I'm using Refile for uploads and am having a tough time figuring out how to delete individual files. I need to display a delete link under each thumbnail, so my first thought was to do something like:
<% @document.document_attachments.each do |doc| %>
<%= link_to attachment_image_tag(doc, :file), attachment_url(doc, :file), target: '_blank' %><br />
<%= link_to 'Delete', document_attachment_path(doc, :file), method: :delete %>
<% end %>
I tried different paths/routes/controllers but nothing works. Maybe it's because I'm using a document_attachments join table?
class Document < ApplicationRecord
has_many :document_attachments, dependent: :destroy
accepts_attachments_for :document_attachments, attachment: :file, append: true
end
class DocumentAttachment < ApplicationRecord
belongs_to :document
attachment :file
end
What's the best way to get these delete links working?
Decided to go with Refile instead of Shrine. I found it easier to work with and was able to implement everything I needed in two days, while I was still wrestling with Shrine after two weeks. I probably just lack the experience that Shrine requires.
Okay thanks for the direction guys, I'll start looking into this to see how to get it done.
I recently worked through the 4 episodes here on direct uploads to S3 with shrine.
I have things setup to upload both images and documents and am now trying to write a conditional to create either an associated image or document record depending on whether the uploaded file is an image or a document (so that I only need one form for users). This is what I have so far, but I feel I might be working in the wrong direction.
Models:
class Project < ApplicationRecord
has_many :project_images, as: :attachable
has_many :project_documents, as: :attachable
end
class ProjectImage < ApplicationRecord
include ImageUploader[:image]
belongs_to :attachable, polymorphic: true
end
class ProjectDocument < ApplicationRecord
include DocumentUploader[:image]
belongs_to :attachable, polymorphic: true
end
Project Images Controller:
def create
@project = Project.find(params[:project_id])
@project_id = params[:project_id]
@project_image = @project.project_images.build(project_image_params)
@project_image.update(user_id: current_user.id, project_id: @project_id)
respond_to do |format|
if @project_image.save
format.html { redirect_to @project }
format.json { render :show, status: :created, location: @project }
else
format.html { render :new }
format.json { render json: @project_image.errors, status: :unprocessable_entity }
end
end
end
Project Documents Controller:
def create
@project = Project.find(params[:project_id])
@project_id = params[:project_id]
@project_document = @project.project_documents.build(project_document_params)
@project_document.update(user_id: current_user.id, project_id: @project_id)
respond_to do |format|
if @project_document.save
format.html { redirect_to @project }
format.json { render :show, status: :created, location: @project }
else
format.html { render :new }
format.json { render json: @project_document.errors, status: :unprocessable_entity }
end
end
end
Project View:
<%= form_for ([@project, @project_image]) do |f| %>
<p>
<%= f.file_field :image, multiple: true, name: 'project_image[image]' %>
</p>
<% end %>
I started by trying to write a conditional in project_images#create but couldn't define how an uploaded document would differ from an image. Maybe I can grab the file extension on the way in somehow?
Then I moved onto another approach, but I'm stuck here as well:
Attachment Model:
class Attachment < ApplicationRecord
belongs_to :attachable, polymorphic: true
belongs_to :project
end
Attachments Controller:
class ProjectAttachment < ApplicationRecord
def create
@project = Project.find(params[:project_id])
@project_id = params[:project_id]
@attachment = @project.attachments.build(attachment_params) # @object inserts here somehow?
@attachment.update(user_id: current_user.id, project_id: @project_id)
respond_to do |format|
if @attachment.save
format.html { redirect_to @attachment.project }
format.json { render :show, status: :created, location: @attachment }
else
format.html { render :new }
format.json { render json: @attachment.errors, status: :unprocessable_entity }
end
end
end
private
def create_object
id = params[:project_document_id] || params[:project_image_id]
model = ProjectDocument if params[:project_document_id]
model = ProjectImage if params[:project_image_id]
@object = model.find(id)
end
end
Project View:
<%= form_for ([@project, @attachment]) do |f| %>
<p>
<%= f.file_field :image, multiple: true, name: 'attachment[image]' %>
</p>
<% end %>
Am I on the right track with either of these attempts?
One small issue I'm running into.. since photos are displayed after uploading with js it's necessary to refresh the page for rails handling to kick in. For example, new images are not linked to their own show pages until a refresh. Also, the max width setting is removed after a refresh, since rails takes over.
Is there any way to handle all display options with rails from the start, so that no page refresh is necessary?
Posted in has_many :through association woes
Your suggestion above worked to set the user_id in my project_assignments join table.
After tinkering with this for longer I think the other problem I'm having is being caused by trying to use two join tables, one for projects and the other for tasks.
I'm going to stick with the one join table, see if I can use it to assign projects to users and then later try to add a task_id parameter to the same table, if needed, to assign tasks.