How to get data from one model to other - ruby-on-rails-4

I have two models
name
user model
result model
user model contains email, password, sign_in_time etc
result model contains user_email and result fields
I want to fetch email from user model into result model's user_email fields
how can I achieve this
That's the schema files of both
create_table "users", force: :cascade do |t|
t.string "email", limit: 255, default: "", null: false
t.string "encrypted_password", limit: 255, default: "", null: false
t.string "reset_password_token", limit: 255
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", limit: 4, default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip", limit: 255
t.string "last_sign_in_ip", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "admin", limit: 1
t.boolean "superadmin", limit: 1, default: false, null: false
end
result
create_table "results", force: :cascade do |t|
t.string "user_email", limit: 255
t.integer "result", limit: 4
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
please help me!

Have you set relationship between user model and result model? Can you explain more detail? Basically, If you want to get data from another model to a model, I think you have to set relationship for 2 models.

Related

Active Record and Ruby on Rails strange behaviour

Hi I have two models which are related to each other through a third model. The two main models are User and Club which have a relation through the Reservations table. The Reservation model has a column called active which is a boolean. The relationship between User and Club is a has_many to has_many ,through Reservation
When a user makes a reservation in a club, an entry is made in the reservation table and the field in the reservation active column is set to true. If the user makes another reservation at the same club, then the previous reservation should have the active column updated from true to false
Here is my code:
user = User.where(:email => params["user_email"]).first
club = Club.find(params["club_id"].to_i)
reservation = Reservation.new
reservation.club_id = club.id
reservation.user_id = user.id
reservation.active = true
user.reservations.where("club_id = ? AND active = ?", club.id, true).each do |res|
puts res.id
res.active = false
res.save
end
reservation.save
Now the user.reservations.where("club_id = ? AND active = ?", club.id, true) query returns the correct entries. I update the value and save it again. However when I look in the database I still see active column has the value true.
What is even stranger is when I run the same command, which I used in my code, in the rails console, it returns the correct entries. When I modify the command a bit and try to find all the entries with column marked as false I also get the right entries. If I select an entry which should have active marked as false, and try this reservation.active == false this returns false, but when I run user.reservations.where("club_id = ? AND active = ?", club.id, true) the results does not contain the entry.
Can anyone explain why I am seeing such strange behaviour. Thanks in advance
* UPDATE *
Here is my schema
create_table "reservations", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "club_id"
t.integer "user_id"
t.boolean "active"
end
create_table "clubs", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
end
create_table "users", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email"
end

Unable to update attribute value in Rails

The Key model has the following migration
class CreateKeys < ActiveRecord::Migration
def change
create_table :keys do |t|
t.string :value
t.integer :alive_time
t.integer :block_time
t.timestamps null: false
end
end
end
Running the following does not update the block_time value:
#available_keys = Key.where(:block_time => 0)
#key = Key.find(#available_keys[0].id)
#key.update_attribute(:block_time, Time.now.to_i)
I tried some variants in the rails console:
Running: Key.find(10).update_attributes({:block_time => Time.now.to_i})
Causes: UPDATE "keys" SET "value" = ?, "alive_time" = ?, "updated_at" = ? WHERE "keys"."id" = ?
The SQL being run updates the alive_time but not the block_time
Why? How do I ensure correct behaviour?
EDIT
The schema.rb contents:
ActiveRecord::Schema.define(version: 20150708123716) do
create_table "keys", force: :cascade do |t|
t.string "value"
t.integer "alive_time"
t.integer "block_time"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end

HABTM not working - unknown bind

I created three models:
class Role < ActiveRecord::Base
has_many :users
has_and_belongs_to_many :permissions
accepts_nested_attributes_for :users, :permissions
end
class Permission < ActiveRecord::Base
has_and_belongs_to_many :roles
accepts_nested_attributes_for :roles
end
and a migration as following:
class Changetable < ActiveRecord::Migration
def change
create_table :permissions_roles, id: false do |t|
t.belongs_to :permissions
t.belongs_to :roles
end
end
end
And that leeds to following schema.rb which looks exactly the same in my sql database:
create_table "permissions", force: true do |t|
t.string "subject_class"
t.string "subject_id"
t.string "action"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "permissions_roles", id: false, force: true do |t|
t.integer "permissions_id"
t.integer "roles_id"
end
create_table "roles", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
Now when I call Roles.first.permissions I got following error message:
irb(main):001:0> Role.first.permissions
←[1m←[36mSQL (1.0ms)←[0m ←[1mUSE [rails_confreport_develop]←[0m
←[1m←[35mRole Load (2.0ms)←[0m EXEC sp_executesql N'SELECT TOP (1) [roles].* FROM [roles] ORDER BY [roles].[id] ASC'
RuntimeError: Unknown bind columns. We can account for this.
Same happens if I call Permission.first.roles! What am I missing?
Best regards!
The mistake was the spelling of the foreign keys in my joined-table.
Changed this:
create_table "permissions_roles", id: false, force: true do |t|
t.integer "permissions_id"
t.integer "roles_id"
end
to this:
create_table "permissions_roles", id: false, force: true do |t|
t.integer "permission_id"
t.integer "role_id"
end
And it works.

Carrierwave is not handling file upload when AR backed object is updated

Can the update action in rails handle file uploads with Carrierwave? After completing the action I cannot find a record of the 'uploaded' image any where. In rails console, I call, user.small_cover, and the following is returned which does not look satisfactory: #, #mounted_as=:small_cover>
My update action is fairly large so I will only show the important slice
...
elsif a_nonprofit_staff_member_updates_profile?(organization)
#user.update_columns(user_params)
flash[:notice] = "You have updated your profile successfully."
redirect_to user_path(#user.id)
...
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password,
:organization_id, :bio, :skills, :interests, :position, :user_group, :contact_reason,
small_cover: [:original_filename] )
end
I tried just using, :small_cover, as the attribute but got an error, no Name method for Nil object, which was very strange to me seeing as that the object was not nil and I was not calling a, name, method. Am I packaging the submitted parameters correctly?
How does one upload a file successfully using carrierwave when the action is updating and not creating an AR backed object in rails? Am I handling the parameters incorrectly
UPDATE:
Here is the relevant code for my user model and my uploader
class User < ActiveRecord::Base
has_secure_password validations: false
belongs_to :organization
has_one :administrated_organization, foreign_key: 'user_id', class_name: 'Organization'
has_many :sent_messages, class_name: 'PrivateMessage', foreign_key: 'sender_id'
has_many :received_messages, -> {order('created_at DESC')}, class_name: 'PrivateMessage', foreign_key: 'recipient_id'
has_many :administrated_projects, through: :administrated_organization, source: :projects
has_many :volunteer_requests, class_name: 'VolunteerApplication', foreign_key: 'administrator_id'
has_many :projects, through: :volunteer_applications, source: :administrator
has_many :delegated_projects, class_name: "Contract", foreign_key: 'contractor_id'
has_many :projects, through: :contracts, source: :contractor
has_many :requests_to_volunteer, class_name: 'VolunteerApplication', foreign_key: 'applicant_id'
has_many :projects, through: :volunteer_applications, source: :applicant
has_many :assignments, class_name: "Contract", foreign_key: 'volunteer_id'
has_many :projects, through: :contracts, source: :volunteer
has_many :questions
validates_presence_of :email, :password, :first_name, :last_name, :user_group
validates_uniqueness_of :email
mount_uploader :small_cover, SmallCoverUploader
before_create :generate_token
end
class SmallCoverUploader < CarrierWave::Uploader::Base
end
Schema:
ActiveRecord::Schema.define(version: 20140619170102) do
create_table "contracts", force: true do |t|
t.integer "contractor_id"
t.integer "volunteer_id"
t.boolean "active"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "project_id"
t.boolean "dropped_out"
t.boolean "complete"
t.boolean "incomplete"
t.boolean "work_submitted"
end
create_table "conversations", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
t.integer "volunteer_application_id"
t.integer "contract_id"
end
create_table "organizations", force: true do |t|
t.string "name"
t.datetime "ruling_year"
t.text "mission_statement"
t.string "guidestar_membership"
t.string "ein"
t.string "street1"
t.string "street2"
t.string "city"
t.integer "state_id"
t.string "zip"
t.integer "ntee_major_category_id"
t.string "funding_method"
t.integer "user_id"
t.string "cause"
t.string "state_abbreviation"
t.text "goal"
t.string "contact_number"
t.string "contact_email"
t.string "budget"
end
create_table "private_messages", force: true do |t|
t.integer "sender_id"
t.integer "recipient_id"
t.string "subject"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "project_id"
t.integer "conversation_id"
end
create_table "projects", force: true do |t|
t.string "title"
t.text "description"
t.string "skills"
t.string "causes"
t.datetime "deadline"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
t.integer "organization_id"
t.integer "estimated_hours"
t.string "state"
end
create_table "questions", force: true do |t|
t.integer "user_id"
t.string "title"
t.text "description"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: true do |t|
t.integer "organization_id"
t.string "first_name"
t.string "last_name"
t.string "email"
t.string "interests"
t.string "skills"
t.string "street1"
t.string "street2"
t.string "city"
t.integer "state_id"
t.integer "phone_number"
t.string "zip"
t.boolean "organization_administrator"
t.boolean "organization_staff"
t.boolean "volunteer"
t.datetime "created_at"
t.datetime "updated_at"
t.string "password_digest"
t.string "position"
t.integer "project_id"
t.string "time_zone"
t.text "bio"
t.string "contact_reason"
t.string "organization_role"
t.boolean "nonprofit"
t.string "type"
t.string "user_group"
t.string "state_abbreviation"
t.string "new_password_token"
t.integer "profile_progress_status"
t.string "small_cover"
end
create_table "volunteer_applications", force: true do |t|
t.integer "user_id"
t.integer "project_id"
t.boolean "accepted"
t.boolean "rejected"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "applicant_id"
t.integer "administrator_id"
end
end
Uploader
class SmallCoverUploader < CarrierWave::Uploader::Base
end
You should try separately with something like:
#user.small_cover.update(cover_params)
I guess your association is belongs_to :small_cover
You'll need to user a second strong parameter method (here called cover_params). That means you'll need to adapt params.
I just want to make an update here, and I am happy to clarify if my brief answer does not satisfy the reader's curiosity.
I basically just used cloudinary and attachinary. This combo works like a dream. Goodbye Carrierwave!

How do I hide from a user the ability to perform an action on a resource after a period of time in Rails 4?

For my projects table I have a column, state, which take string values: "open", "in production", "pending approval" and "completed". The actions that trigger changes between these states are messages that go to and from users about the projects or actions associated to messages. When the object, project, goes from "open" to "in production", in the users inbox a user has a button appearing on the conversation associated with the project that reads, "Drop Project." Moreover, I can wire up the functionality as well. Clicking this button will disassociate you with the project.
My question: how can I have this button hide itself or disappear after 5 days of the project's state, having gone from "open" to "in production"? In other words, I want the user to have the opportunity to disassociates his self from the project within a certain time limit. After that, he is stuck with the project and is encouraged to finish it.
Also, how would I test this with rspec? Is this strictly with an integration test, or can I test it with a unit test too?
I am aware of this SO post (Rails 3 Check if attribute changed), but it has not helped me figure out the solution to my problem. However, I feel like it could serve as support.
Here is my db schema and models:
ActiveRecord::Schema.define(version: 20140514191454) do
create_table "conversations", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
end
create_table "organizations", force: true do |t|
t.string "name"
t.datetime "ruling_year"
t.text "mission_statement"
t.string "guidestar_membership"
t.string "ein"
t.string "street1"
t.string "street2"
t.string "city"
t.integer "state_id"
t.string "zip"
t.integer "ntee_major_category_id"
t.string "funding_method"
t.integer "user_id"
t.string "cause"
end
create_table "private_messages", force: true do |t|
t.integer "sender_id"
t.integer "recipient_id"
t.string "subject"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "project_id"
t.integer "conversation_id"
end
create_table "project_users", force: true do |t|
t.integer "user_id"
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "projects", force: true do |t|
t.string "title"
t.text "description"
t.string "skills"
t.string "causes"
t.datetime "deadline"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
t.integer "organization_id"
t.integer "estimated_hours"
t.string "state"
end
create_table "user_conversations", force: true do |t|
t.integer "user_id"
t.integer "conversation_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: true do |t|
t.integer "organization_id"
t.string "first_name"
t.string "last_name"
t.string "email"
t.string "interests"
t.string "skills"
t.string "street1"
t.string "street2"
t.string "city"
t.integer "state_id"
t.integer "phone_number"
t.string "zip"
t.boolean "organization_administrator"
t.boolean "organization_staff"
t.boolean "volunteer"
t.datetime "created_at"
t.datetime "updated_at"
t.string "password_digest"
t.string "position"
t.integer "project_id"
t.string "time_zone"
end
end
Conversation
class Conversation < ActiveRecord::Base
has_many :private_messages, -> {order('created_at ASC')}
def sender_user_name_of_recent_message
message = self.private_messages.last
user = message.sender_id
name = User.find_by(id: user)
"#{name.first_name} #{name.last_name}"
end
def the_id_of_sender
message = self.private_messages.last
user = message.sender_id
name = User.find_by(id: user)
name.id
end
def private_message_subject
message = self.private_messages.last
message_subject = message.subject
end
def private_message_body
message = self.private_messages.last
message_body = message.body
end
def join_request
message = self.private_messages.first
project = Project.find_by(id: message.project_id)
if project
project.state == "open"
end
end
def project_complete_request
message = self.private_messages.first
project = Project.find_by(id: message.project_id)
if project
project.state == "pending approval"
end
end
def opportunity_drop_project
message = self.private_messages.first
project = Project.find_by(id: message.project_id)
if project
project.state == "in production"
end
end
end
User
class User < ActiveRecord::Base
has_secure_password validations: false
belongs_to :organization
belongs_to :project
has_many :project_users
has_many :projects, through: :project_users
has_many :sent_messages, class_name: 'PrivateMessage', foreign_key: 'sender_id'
has_many :received_messages, -> {order('created_at DESC')}, class_name: 'PrivateMessage', foreign_key: 'recipient_id'
has_many :conversations
def private_messages
messages = self.sent_messages + self.received_messages
messages.sort!
end
def user_conversations
collection = self.received_messages.select(:conversation_id).distinct
all_conversations = collection.map do |member|
convo_id = member.conversation_id
Conversation.find_by(id: convo_id)
end
all_conversations.sort
end
def organization_name
organization.name
end
end
Organization
class Organization < ActiveRecord::Base
belongs_to :organization_administrator, foreign_key: 'user_id', class_name: 'User'
has_many :projects
has_many :users
end
PrivateMessage
class PrivateMessage < ActiveRecord::Base
belongs_to :recipient, foreign_key: 'recipient_id', class_name: 'User'
belongs_to :sender, foreign_key: 'sender_id', class_name: 'User'
belongs_to :conversation
validates_presence_of :subject, :body
end
Project
class Project < ActiveRecord::Base
belongs_to :organization
has_many :project_users
has_many :users, through: :project_users
def project_admin
organization.organization_administrator
User.find(organization.organization_administrator.id)
end
def open
self.state == "open"
end
end
ProjectUser
class ProjectUser < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
I don't think there is a built-in Rails way to do this. ActiveModel::Dirty won't work because it only tells you if an object attribute has been changed in memory, once the object is saved to the DB it isn't dirty anymore. I think you'll just have to create a timestamp companion column for state and reset that value to the current time every time you change state. Then you'd just check against the time difference between now and the state_changed attribute.
You can do this by assigning Time.now to the state_changed attribute every time you assign a new state. Or, alternately, you could use a before_save callback on the project object. Use AM::Dirty to check if project.state has been changed, and set the state_changed attribute to Time.now if it has been. That way would be more DRY.
And then in the code for the actions you want time dependent you'd wrap them in a conditional like
if project.state == "in production" && project.state_changed < 5.days.ago
And you'd also create a helper for your views that made the same calculation and only show the button if it is true.
I was missing some large objects here. A user has many projects through volunteer applications and a user has many projects through contracts.
Seeing as that accepting a user's solicitation on a project occurs in the user's inbox which contains an array of conversations that have a foreign key, contract_id, I implemented the following method in the Conversation model:
def with_opportunity_to_drop_job
contract = Contract.find(self.contract_id)
contract.active && contract.work_submitted == false && contract.created_at > 5.days.ago
end
If the creation date is more than 5 days ago, the button disappears -- luckily I have tests that validate this so I do not need to wait around for 5 days :-)