I'm having trouble defining an amount for a pay action in my item controller. I'm trying to pull in the item price stored in the db. I've tried everything. I reread this, http://guides.rubyonrails.org/action_controller_overview.html, and still no luck.
In items controller:
def pay
# Find the user to pay.
user = User.find( params[:id] )
amount = #I have no idea what to put here
fee = 100
If I put in a number it works fine. However when I try to access the item price that is stored in the db, that is when things blow up.
I've tried various definitions:
#item.price #fail
item_price #fail
Item.find (params: [:price]) #fail
Item.price #fail
#EVERYTHING FAILS
Schema:
ActiveRecord::Schema.define(version: 20150127171203) do
create_table "items", force: true do |t|
t.string "name"
t.decimal "price"
t.text "description"
t.integer "booth_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "category_id"
t.integer "user_id"
t.string "image"
t.string "image_two"
end
create_table "users", force: true do |t|
t.string "name"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
t.string "activation_digest"
t.boolean "activated", default: false
t.datetime "activated_at"
t.string "reset_digest"
t.datetime "reset_sent_at"
t.boolean "admin", default: false
t.string "avatar"
t.text "about"
t.string "location"
t.string "publishable_key"
t.string "secret_key"
t.string "stripe_user_id"
t.string "currency"
end
(edit) I also tried defining items in the pay action and that did not help either. 'item = Item.find ( params[:id]'
Does anyone know the right way to do this? I feel like this should be easy but I'm having trouble with it.
Thanks for your consideration and help!
How is a user related to an item? I ask this because if you are using active record, the associations you make in your database will determine the methods that are created for you. Does a user has_many items in your model? Does an item belong_to a user? In which case would be
#user = User.find(1)
and you could find the price like
#item = #user.items.find(1)
#price = #item.price
EDIT
Ok, I took a look at the code you provided here. This example shows a pay method defining a route in the users controller which seems to only be setup to accept a one time fee. In the comments above it, it even says make a one-off payment so we know this is true.
Even in this example here they explicitly say it's for a fixed amount. Now how do we make it dynamic? Well, look at the code. There's some logic in the pay controller isn't there?
You see that Stripe::Charge object being created?
charge = Stripe::Charge.create(
{
amount: amount,
currency: user.currency,
card: params[:token],
description: "Test Charge via Stripe Connect",
application_fee: fee
},
# Use the user-to-be-paid's access token
# to make the charge.
user.secret_key
)
You can move this logic into your item MODEL. Call it pay or something as long as it takes in the user as a parameter.
def pay(user)
amount = self.price
begin
charge = Stripe::Charge.create(
{
amount: amount,
currency: user.currency,
card: user.token,
description: "Test Charge via Stripe Connect",
application_fee: fee
},
# Use the user-to-be-paid's access token
# to make the charge.
user.secret_key
)
flash[:notice] = "Charged successfully! <a target='_blank' rel='connected-account' href='https://dashboard.stripe.com/test/payments/#{charge.id}'>View in dashboard ยป</a>"
rescue Stripe::CardError => e
error = e.json_body[:error][:message]
flash[:error] = "Charge failed! #{error}"
end
end
Then somewhere in your items CONTROLLER define the pay method instead of users like you had before(Make sure you change your routes accordingly). Then call the pay method you just defined, this way you have the price and you can find the user that is currently logged in.
def pay
user = User.find(session[:user_id])
item = Item.find(params[:id])
item.pay(user)
redirect "somewhere"
end
Related
Here is my schema:
create_table :policies do |t|
t.string :name
t.timestamps
end
create_table :permissions do |t|
t.string :name
t.string :method
t.string :controller
t.timestamps
end
create_join_table :policies, :permissions do |t|
t.index :policy_id
t.index :permission_id
end
And here is the code I am using to create the records and their associations:
policy = Policy.create! name: "View All"
permission = Permission.create!({
name: "View Events",
method: "index",
controller: "Events"
})
policy.permissions << permission
And its returning the following error:
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "permission_policies" does not exist
The table name that was created through the migration is policies_permissions
I wonder if this is an issue with the class names not being inferred properly
Swap the positions of permissions and policies in the migration so that you create permissions_policies instead of policies_permissions. Rails infers the class names for a join table in alphabetical order.
See this answer for more information on join table naming conventions.
I'm implementing a Rails 4 app that has a Reflexive Many-to-Many Association to represent some MailChimp and HelpScout API parameters.
Some of those parameters have child parameters. Thus, those child parameters have parent parameters (otherwise they couldn't be a child, right?! ;D ).
To implement the reflexive association the two tables below were created
create_table "api_params", force: true do |t|
t.string "name"
t.string "description"
t.string "type"
t.boolean "required"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "nested_params", force: true do |t|
t.integer "parent_param_id"
t.integer "child_param_id"
t.boolean "required"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "nested_params", ["child_param_id"], name: "index_nested_params_on_child_param_id"
add_index "nested_params", ["parent_param_id"], name: "index_nested_params_on_parent_param_id"
What I'd like to have are two methods. One to retrieve a database record's parents and another one to retrieve its children. Below I show you an example.
apiParam = ApiParam.first # retrieving any database record
apiParam.parent_params
# => returns a set of apiParam's parents
apiParam.child_params
# => returns a set of apiParam's children
I read all day long about associations but the examples are always the same. I mean, there is always a class where you define a has_many through and another one where you define a belongs_to but it wasn't enough for what I need.
Thanks in advance. I appreciate any kind of help.
I have your solution (in my case I have the model SyncType):
class SyncType < ActiveRecord::Base
has_and_belongs_to_many(:parents,
:class_name => "SyncType",
:join_table => "sync_type_parents",
:foreign_key => "sync_type_id",
:association_foreign_key => "sync_type_parent_id")
has_and_belongs_to_many(:children,
:class_name => "SyncType",
:join_table => "sync_type_parents",
:foreign_key => "sync_type_parent_id",
:association_foreign_key => "sync_type_id")
end
migration:
create_table "sync_type_parents", :force => true, :id => false do |t|
t.integer "sync_type_id", :null => false
t.integer "sync_type_parent_id", :null => false
end
Enjoy! ;)
I found the answer and I hope it can be helpful for everyone with same kind of problem.
In short, I've got the answer from Ryan Bates' railscasts.com website. More specificly, the answer were found here.
My classes are now as follow:
class NestedParam < ActiveRecord::Base
belongs_to :api_param
belongs_to :child_param, class_name: 'ApiParam'
end
class ApiParam < ActiveRecord::Base
has_many :nested_params
has_many :child_params, :through => :nested_params
has_many :parent_api_params, :class_name => "NestedParam", :foreign_key => "child_param_id"
has_many :parent_params, :through => :parent_api_params, :source => :api_param
end
ActiveRecord::Schema.define(version: 20140910175658) do
create_table "api_params", force: true do |t|
t.string "name"
t.string "description"
t.boolean "required", default: true
t.boolean "struct", default: false
t.string "type"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "nested_params", force: true do |t|
t.integer "api_param_id"
t.integer "child_param_id"
t.boolean "required"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "nested_params", ["api_param_id"], name: "index_nested_params_on_api_param_id"
add_index "nested_params", ["child_param_id"], name: "index_nested_params_on_child_param_id"
end
when trying to run migration to add a spatial index, get
Unknown key: spatial/Users/ME/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.0.2/lib/active_support/core_ext/hash/keys.rb:70:in `block in assert_valid_keys'
Using
Ruby 2.0.353
Rails 4.0.2
RGEO 0.3.20
RGEO Active Record 0.4.6
List item
activerecord-mysql2spatial-adapter 0.4.3
Migration Index file looks like
class CreateAddresses < ActiveRecord::Migration
def change
create_table :addresses, :options => 'ENGINE=MyISAM' do |t|
t.string :street_1
t.string :street2
t.string :city
t.string :state
t.string :zip
t.string :country
t.string :full_address
t.column :latlon, :point, :null => false
t.timestamps
end
add_index :addresses, :latlon, :spatial => true
end
end
UPDATE
Corrected this and other errors when I changed the adapter in my database.yml file from mysql2 to mysql2spatial
I've been stuck on this problem for two days now, and have not been able to find a solution online. I am hoping some of you might be able to help.
I've got the following models:
App.Project = DS.Model.extend({
name: DS.attr('string'),
project_teams: DS.hasMany('projectTeam')
});
App.ProjectTeam = DS.Model.extend({
sde_effort: DS.attr('number'),
project: DS.belongsTo('project'),
team: DS.belongsTo('team')
});
App.Team = DS.Model.extend({
project_teams: DS.hasMany('projectTeam'),
name: DS.attr('string')
});
And the following code in my projectsController:
var project = store.createRecord('project', {
name: projectName
});
project.save().then(function(projectRecord){
var teamHookerUpper = function(teamId, sdeEffort, idx){
store.find('team', teamId).then(function(team){
var project_team = store.createRecord('project_team', {
project: projectRecord,
sde_effort: sdeEffort,
team: team
});
console.log('project team has been created');
project_team.save().then(function(pt){
projectTeamIds.push(pt.get('id'));
if(idx == sdeHeads.length - 1){
console.log(projectRecord);
projectRecord.set('project_teams', projectTeamIds);
projectRecord.save();
}
});
});
}
for(var i = 0; i < sdeHeads.length; i++){
teamHookerUpper(teamIds[i], sdeHeads[i], i);
}
});
The logic is the following:
Get the value from a txt in the front end and create a new Project. When you create the project, select all teamIds and sdeEfforts (a metadata value) associated with that project, create multiple TeamProject objects and link them to the newly created Project. The Team value associated with ProjectTeam is just an id and I am able to retrieve the object by making a call to the DB.
At present the Project object is created successfully, and multiple ProjectTeam objects are created successfully, however when adding the ProjectTeams, the values for project and team are null. Furthermore, you see that each ProjectTeam object i create a push to an array. Once i've iterated over all teamIds (from the front end), i add the array of ProjectTeams to Project and update Project.
However, when inspecting the ajax call, I see that a PUT request is sent to the appropriate url however, no data is sent whatsoever (status code 204)
I have been stuck on this for two days and have exhausted all the resources I managed to find. I am hoping the community will be able to assist me with this one.
Is there another approach of going about this? Have I been fixated into this approach that I haven't considered other approaches? Please give me some guidance, that would be highly appreciated.
EDIT:-----
here are ajax calls and their respective responses:
{"project":{"name":"fghfg"}} <- post Project
{"project_teams":[],"project":{"id":3,"name":"fghfg", "created_at":"2014-01-03T12:11:28.372Z","updated_at":"2014-01-03T12:11:28.372Z","project_teams":[]}} <- response
{"project_team":{"sde_effort":34,"project":"3","team":"1"}} <- post ProjectTeam
{"projects":[],"teams":[],"project_team":{"id":2,"sde_effort":34,"created_at":"2014-01-03T12:11:28.494Z","updated_at":"2014-01-03T12:11:28.494Z","project":null,"team":null}} <- response
{"project_teams":[],"team":{"id":1,"name":"Team 1","created_at":"2014-01-03T12:10:42.787Z","updated_at":"2014-01-03T12:10:42.787Z","project_teams":[]}} <- response for GET teams/1
{"project":{"name":"fghfg"}} <- PUT project. No response for this call :/
EDIT 2:
Here's the corresponding data schema in ruby
ActiveRecord::Schema.define(version: 20131230144053) do
create_table "project_teams", force: true do |t|
t.integer "sde_effort"
t.integer "project_id"
t.integer "team_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "project_teams", ["project_id"], name: "index_project_teams_on_project_id"
add_index "project_teams", ["team_id"], name: "index_project_teams_on_team_id"
create_table "projects", force: true do |t|
t.string "name", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "teams", force: true do |t|
t.string "name", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
end
I'm trying to insert data with migration and don't understand what's wrong with this code:
def change
create_table :sourcebuster_settings do |t|
t.integer :session_length
t.boolean :use_subdomains, default: false
t.string :main_host
t.timestamps
end
Sourcebuster::Setting.create session_length: 30,
use_subdomains: false
end
create_table works fine, but no data inserted after migration. No errors in console.
Previous migrations with the same method of data insertions works fine also. Problem only with this one.
I got it. In my setting model:
before_save { self.main_host = main_host.gsub(/(http:|https:|www\.|:|\/)/,'').downcase if self.main_host }
validates_presence_of :main_host, if: lambda { self.use_subdomains }
validates :main_host, format: { with: VALID_HOST_REGEX }, allow_blank: true
Added allow_blank: true to main_host validation.