Manually updating attributes mounted by Carrierwave Uploader - ruby

I am unable to use model.update_attribute on an attribute that is mounted by a carrierwave uploader. The SQL statement wont accept the value and adds NULL to the placeholder. If I remove the mount_uploader statement from the model class it works as normal. I am troubleshooting things from the console and trying to add some attributes while seeding the DB and this is thwarting my efforts. Ideas?
Thanks.
Update:
Relevant code:
class Profile < ActiveRecord::Base
belongs_to :user
has_and_belongs_to_many :sports
has_and_belongs_to_many :interests
has_and_belongs_to_many :minors
has_and_belongs_to_many :majors
has_and_belongs_to_many :events
has_and_belongs_to_many :groups
attr_accessible :description, :username, :avatar, :bio, :first_name, :last_name, :major, :minor, :graduation_date, :living_situation, :phone, :major_ids, :minor_ids, :sport_ids
mount_uploader :avatar, AvatarUploader
end
I am simply trying to rewrite the :avatar string from a db seed file and while testing from the rails console like so:
Profile.first.update_attribute(:avatar, 'foo')
Both work when I comment out the mount_uploader line.
Does adding the mount_uploader method freeze the string or make it immutable?

I found a solution to this.
My issue was that I was not able to alter the attribute mounted my the CarrierWave uploader from my seeds.rb file.
This works:
user.profile.update_column(:avatar, 'foobar/image.png')

Related

Modifying a Lib Model

I would like to override a Lib Model in my Models and add a relation.
What is the best way to do it ?
Example of a model in rpush lib:
https://github.com/rpush/rpush/blob/f82cc6a25861612ce118b2661f5a47bceb7ebd86/lib/rpush/client/active_record/app.rb
module Rpush
module Client
module ActiveRecord
class App < ::ActiveRecord::Base
self.table_name = 'rpush_apps'
if Rpush.attr_accessible_available?
attr_accessible :name, :environment, :certificate, :password, :connections, :auth_key, :client_id, :client_secret
end
has_many :notifications, class_name: 'Rpush::Client::ActiveRecord::Notification', dependent: :destroy
validates :name, presence: true, uniqueness: { scope: [:type, :environment] }
end
end
end
end
I would like to add a has_many relation without editing the gem
So I thought creating a models/app.rb with this would be a start:
class Rpush::Client::ActiveRecord::App
has_many :rel_group_apps
has_many :groups, :through => :rel_group_apps
end
I tried this but nothing changed. Maybe my models/app.rb is not called ?:
module Rpush
module Client
module ActiveRecord
module App
def self.included(includer)
includer.class_eval do
has_many :rel_group_apps
has_many :groups, :through => :rel_group_apps
end
end
end
end
end
end
How should I do it ? Is there a way to extend a lib model without removing the original behavior ?
Thanks !
EDIT
I Made it work but only by putting this code directly in config/initializers/rpush.rb
It wasn't working in models/app.rb
class Rpush::Client::ActiveRecord::App
has_many :rel_group_apps
has_many :groups, :through => :rel_group_apps
end
If someone has a nicer idea, I'll take it !
Extend the class with class << self
class Rpush::Client::ActiveRecord::App
class << self
[your methods here]
end
end

Mongoid has_and_belongs_to_many, inverse_of: :nil, store_as

In my code I have a user class:
class User
include Mongoid::Document
has_and_belongs_to_many :person_record_bookmarks, inverse_of: nil, :class_name => "PersonRecord"
end
now it will generate person_record_bookmarks_ids in my document. This name is too long, is there any way to store it as shorter name in the database? In embed documents we can use store_as:, but seems it doesn't work for references.
foreign_key is what you are looking for
class User
include Mongoid::Document
has_and_belongs_to_many :person_record_bookmarks, inverse_of: nil, :class_name => "PersonRecord", foreign_key :shorter_name
end
then your user will be:
{...shorter_name:[ObjectId("..."),ObjectId("...")]...}
You can user user.shorter_name to retrieve the list of ids or user.person_record_bookmarks to retrieve all PersonRecordBookmarks.where({_id: {$in: shorter_name})

Active record in standalone Ruby

I have standalone Ruby application and want to use it with active record gem. I've made 3 models:
user.rb
require 'active_record'
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
has_many :comments
validates :name, :presence => true
attr_accessible :name, :state
end
post.rb
require 'active_record'
class Post < ActiveRecord::Base
belongs_to :user
has_many :comments
validates :title, :length => { :in => 6..40 }
attr_accessible :title, :content
end
comment.rb
require 'active_record'
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post
validates :content, :presence => true
attr_accessible :content, :user_id
end
Now I want to populate database with one user, one post and one comment for this post and user by issuing this code:
require 'active_record'
require 'sqlite3'
require './models/user'
require './models/post'
require './models/comment'
ActiveRecord::Base.configurations = YAML::load(IO.read('config/database.yml'))
ActiveRecord::Base.establish_connection("development")
user1 = User.create name: "Joe", state: "England"
post1 = user1.posts.create title: "RoR introduction", content: "RoR intro."
comment1 = post1.comments.create content: "This is great article!"
But now it populates database but user_id is null. What am I missing here?
I think that your comment gets associated with a post, and not a user ...
just say do comment1.user = user1 and then comment1.save!
I think the key issue here is that the user making the comment is not necessarily the user who made the original post. If that were the case you could enforce it via the through option. However since a post may be commented upon by any user, then saying post1.comments.create etc. shouldn't automatically pull in the user who created the post right? Since it might be another user ...
I'm not sure but I don't think you want those attr_accessible specifications in an active record class - I think they are interfering with the fields that active record provides automatically - try removing all of them

Look for help on Ruby on Rails

I am new with Ruby on Rails. I just build web application on the existing database. I use rails to generate 2 scaffolds for restaurant and location tables. After that I set relationship for these two tables:
class Restaurant < ActiveRecord::Base
attr_accessible :created, :cuisine_fk, :dish_keywords, :dish_names, :factual_id, :first_name, :last_name, :name, :status
has_many :locations
end
class Location < ActiveRecord::Base
attr_accessible :address1, :address2, :city, :created, :latitude, :longitude, :phone, :restaurant_fk, :state, :status, :url, :zip
belongs_to :restaurant
end
I didn't use "rake db:migrate" after I set up this relationship for these tables, because I was afraid that this action would make changes the existing tables.
When I run this command line
<%= restaurant.location.address1%>
it shows error:
undefined method `location'
" NoMethodError in Restaurants#index
Showing C:/Sites/Dishclips/app/views/restaurants/index.html.erb where line #52 raised:
undefined method `location' for #<Restaurant:0x5853bb8> "
After that I tried to set foreign key for the file:
class Location < ActiveRecord::Base
attr_accessible :address1, :address2, :city, :created, :latitude, :longitude, :phone, :restaurant_fk, :state, :status, :url, :zip
belongs_to :restaurant, :class_name => "Restaurant", :foreign_key => 'restaurant_fk'
end
but it still doen't work.
Is there any way that we can set foreign keys in stead of using "rails db:migrate" after we set up the relationships for tables ? I appreciate your help a lot.
The problem is that you are using location wrongly.
Since the restaurant has_many locations you can't use it the way you mentioned. Because you have an array of locations, actually is a ActiveRecord relationship, so in order to access one of the items assciated you'll have to execute the query and get one of the elements. Here is an example of how to get the first element.
restaurant.locations.first.address1
If the restaurant have only one location, than you should change your model to
class Restaurant < ActiveRecord::Base
attr_accessible :created, :cuisine_fk, :dish_keywords, :dish_names, :factual_id, :first_name, :last_name, :name, :status
has_one :locations
end
and access the property as you are doing:
restaurant.location.address1
Also I'm assuming that your database have the columns you specified, otherwise you'll have to run the migrations.
Regards!
Rails associations are covered very well here in the Rails Guides.
I'll walk you through a basic setup here.
$ rails generate model Restaurant name owner ...
$ rails generate model Location restaurant_id:integer city ...
You then need to migrate your database with rake db:migrate for the database table changes to become effective.
The restaurant_id allows us to set the associations in our models as follows
class Restaurant < ActiveRecord::Base
has_many :locations, dependent: :destroy
attr_accessible :name, :owner
end
class Location < ActiveRecord::Base
belongs_to :restaurant
attr_accessible :city # no restaurant_id here
end
Now you can access your restaurants location as follows.
r = Restaurant.create!(name: '...')
l = Location.create!(city: '...')
# Add association
r.locations << l
r.locations will now return an Array with l in it
l.restaurant will return r
Try to play a little with the different styles of associations, for example by creating new Rails apps quickly and just trying some kind of associations, also some that require a join model.
Now I try this way, then it works. Thank you very much.
<td>
<% restaurant.locations.search(params[:restaurant_fk]).each do |location| %>
<!--address = <%= location.address1 %> + " " + <%= location.address2 %>-->
<%= location.address1 %>
<%= location.address2 %> ,
<%= location.city %> ,
<%= location.state %> ,
<%= location.zip %>
<% end %>
</td>

Rails multiple belongs_to assignment

Given
User:
class User < ActiveRecord::Base
has_many :discussions
has_many :posts
end
Discussions:
class Discussion < ActiveRecord::Base
belongs_to :user
has_many :posts
end
Posts:
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :discussion
end
I am currently initializing Posts in the controller via
#post = current_user.posts.build(params[:post])
My question is, how do I set/save/edit the #post model such that the relationship between the post and the discussion is also set?
Save and edit discussions along with post
Existing Discussion
To associate the post you're building with an existing discussion, just merge the id into the post params
#post = current_user.posts.build(
params[:post].merge(
:discussion_id => existing_discussion.id
)
You will have to have a hidden input for discussion id in the form for #post so the association gets saved.
New Discussion
If you want to build a new discussion along with every post and manage its attributes via the form, use accepts_nested_attributes
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :discussion
accepts_nested_attributes_for :discussion
end
You then have to build the discussion in the controller with build_discussion after you built the post
#post.build_discussion
And in your form, you can include nested fields for discussions
form_for #post do |f|
f.fields_for :discussion do |df|
...etc
This will create a discussion along with the post. For more on nested attributes, watch this excellent railscast
Better Relations
Furthermore, you can use the :through option of the has_many association for a more consistent relational setup:
class User < ActiveRecord::Base
has_many :posts
has_many :discussions, :through => :posts, :source => :discussion
end
class Discussion < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :discussion
end
Like this, the relation of the user to the discussion is maintained only in the Post model, and not in two places.

Resources