I'm using react for the client side and rails for the server.
When trying to link the post to its username I get 'undefined'.
If I try user={post.user_id} to get the user_id, it works fine, but I want to show the username.
PostList.jsx
{posts.map((post) => (
<>
<Post
key={post.id}
title={post.title}
content={post.content}
user={post.user.username}
id={post.id}
getPosts={getPosts} />
</>
Post.jsx
const Post = ({title, content, user, id, getPosts}) => {
return (
<div className='post-container'>
<div className='post-header'>
<div className='post-title-user'>
<h2>{title}</h2>
<span>Posted by: #{user}</span>
</div>
</div>
<p>{content}</p>
</div>
)
}
export default Post
schema.rb
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "content"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "user_id", null: false
t.index ["user_id"], name: "index_posts_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "username"
t.string "password_digest"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
user.rb
class User < ApplicationRecord
has_secure_password
has_many :posts
end
post.rb
class Post < ApplicationRecord
belongs_to :user
end
I think you should use active_model_serializers gem
Step1: add gemfile gem 'active_model_serializers'
Step2: bundle
Step3: rails g serializer post
In posts_controller.rb
class PostsController < ApplicationController
def index
posts = Post.all
render json: {
message: 'Get posts',
data: ActiveModel::Serializer::CollectionSerializer.new(posts, each_serializer: PostSerializer)
}
end
end
In post_serializer.rb
class PostSerializer < ActivieModel::Serializer
attributes :id, :title, :content, :username
def username
#You try byebug and check object
object.username
end
end
Related
I try to add a form-control class to an input field of a model-based form in Django, but I get this error message:
AttributeError: 'CharField' object has no attribute 'use_required_attribute'.
How do I fix this?
class in views.py:
class TweetCreate(LoginRequiredMixin, CreateView):
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']
def get_form(self):
form = super().get_form()
form.fields['search_term'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'}))
form.fields['query_type'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'}))
form.fields['start_date'].widget = DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['end_date'].widget = DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['language'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'})),
form.fields['country'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'})),
return form
class in models.py:
class TweetSearch(models.Model):
from datetime import datetime, timedelta
search_term = models.CharField(max_length=200, default='blue bird')
QUERY_CHOICES = (
('t', 'in tweet'),
('h', 'in hashtag'),
('u', 'username'),
)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, blank=True)
query_type = models.CharField(max_length=1, choices=QUERY_CHOICES, blank=True, default='t')
start_default = datetime.now() - timedelta(days=30)
start_date = models.DateTimeField(default=start_default)
end_date = models.DateTimeField(default=datetime.now)
language = models.CharField(max_length=200, default='English')
country = models.CharField(max_length=200, default='USA')
searcher = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
def get_absolute_url(self):
return reverse('tweet_detail', kwargs={'pk': self.pk})
def __str__(self):
return f"Tweets with the word {self.search_term} from {self.start_date} till {self.end_date} written in " \
f"{self.language} in {self.country}."
HTML:
<div class="container" id="searchcontainer" style="text-align: center">
<form action="" method="POST">
{% csrf_token %}
{{form.search_term}}
{{form.query_type}}
{{form.start_date}}
{{form.end_date}}
{{form.language}}
{{form.country}}
<input class="btn btn-primary" type="submit">
</form>
</div>
You are confusing form field with widgets. You should assign a widget like TextInput, not a form field like CharField, like:
class TweetCreateView(LoginRequiredMixin, CreateView):
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']
def get_form(self):
form = super().get_form()
form.fields['search_term'].widget=forms.TextInput(attrs={'class': 'form-control'})
form.fields['query_type'].widget=forms.TextInput(attrs={'class': 'form-control'})
form.fields['start_date'].widget=DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['end_date'].widget=DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['language'].widget=forms.TextInput(attrs={'class': 'form-control'})
form.fields['country'].widget=forms.TextInput(attrs={'class': 'form-control'})
return form
It however here might be better to just plug in a ModelForm, so:
class TweetForm(forms.ModelForm):
class Meta:
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']
widgets = {
'search_term': forms.TextInput(attrs={'class': 'form-control'}),
'query_type': forms.TextInput(attrs={'class': 'form-control'}),
'start_date': DateTimePickerInput(attrs={'class': 'form-control'}),
'end_date': DateTimePickerInput(attrs={'class': 'form-control'}),
'language': forms.TextInput(attrs={'class': 'form-control'}),
'country': forms.TextInput(attrs={'class': 'form-control'}),
}
and plug this into the TweetCreateView:
class TweetCreateView(LoginRequiredMixin, CreateView):
model = TweetSearch
form_class = TweetForm
if you however only want to change the class, you can simplify this with:
class FormControlForm(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
class TweetForm(FormControlForm, forms.ModelForm):
class Meta:
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']
I have method called check_field, purpose of this method is for checking is there multiple value when input form.
I was think maybe I can check with multiple array on rails. I found some code on this link to check duplicate value inside array. So, I implement that method (difference) on my model
, but I got stuck when implement to my Model, the methot won't called.
NoMethodError (undefined method `difference' for ["vvvv", "vvvv", "xxxxxxxxx", "xxxxxxxxx"]:Array):
here my Code.
class Model < ApplicationRecord
has_many :child_models, -> { where(active: true) }, :foreign_key => :model_id, :dependent => :destroy
accepts_nested_attributes_for :child_models, :allow_destroy => false
before_validation :check_field, :before => [:create]
def check_field
all_field = Array.new
child_models.each do |data|
all_field << data.field
end
uniq_field = all_field.uniq
result = uniq_field - all_field.difference(uniq_field)
errors.add(:field, "Field must be Different")
end
def difference(other)
h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
reject { |e| h[e] > 0 && h[e] -= 1 }
end
end
the field that I want to validate is on child_models,
class ChildModel < ApplicationRecord
validates :field, presence: { message: "Field" + I18n.t("sys_err_is_required"), :if => :active?, :scope => [:active] }, :uniqueness => { :message => 'Field is already exist', :if => :active?, :scope => [:active], :case_sensitive => false }
end
I was try to put check_field method on ChildModel, it didn't work, because the parameters can be read on Model class.
so then any solution for this case?
thanks.
you should use self.difference to call your method, because it is a classmethod. see https://dev.to/adamlombard/ruby-class-methods-vs-instance-methods-4aje
...
result = self.difference(uniq_field)
I'm calling an array of recommended products (based on the predictor-gem) and want to exclude the products of the current_user from that set. I think that I'm using the proper condition for it (" != ?") but just not in the correct way. #products_rec should give that final array.
Here's the specific code in my product_controller.rb:
recommender = ProductRecommender.new
products = current_user.products
#product_rec = (recommender.similarities_for("product-#{#product.id}")).map {|el| el.gsub(/(.*\-)[^\d]*/, "")}
#products_rec = Product.find(#product_rec, :conditions => ["id != ?", products.id])
and here's my model, product.rb:
class Product < ActiveRecord::Base
include Reviewing
include PublicActivity::Model
tracked
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
belongs_to :category
belongs_to :benefit
has_many :subscriptions
has_many :users, through: :subscriptions
has_many :benefits
has_many :projects, through: :benefits
belongs_to :user
validates :name, presence: true, length: { maximum: 200 }
validates :gtin, presence: false
validates :content, presence: false, length: { maximum: 2000 }
validates :video, presence: false
validates :tag, presence: false
validates :project, presence: false
validates :category, presence: false
validates :user, presence: false
has_attached_file :image, :styles => { :medium => "680x300>", :thumb => "170x75>" }
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end
I want to exclude the products from the current_user, based on the users through subscriptions (see model).
How can I get this to work, any ideas?
Final code:
Based on the answer of #Humza, I've added the following working code to my product_controller.rb:
recommender = ProductRecommender.new
products = current_user.products.select("id")
#product_rec = (recommender.similarities_for("product-#{#product.id}")).map {|el| el.gsub(/(.*\-)[^\d]*/, "")}
#products_rec_array = Product.find(#product_rec)
#products_rec = Product.where(id: #products_rec_array).where.not(id: products)
To find products with id not in array, you must do this:
array = current_user.products.pluck(:id)
Product.where('id NOT IN (?)', array) # '?' is surrounded by paranthesis
But since a product belongs to a user, you can simply do
Product.where('user_id != ?', current_user.id)
You can also use the not method like so:
Product.where.not(id: array)
Product.where.not(user_id: current_user.id)
Edit:
If you want the base products to be from some other list, this can help:
base_product_ids = some_list.map(&:id) # assuming this is an Array
Product.where(id: base_product_ids).where.not(user_id: current_user.id)
If some_list was an ActiveRecord::Relation, you could have simply done:
some_list.where.not(user_id: current_user.id)
I have a user model with Paperclip for avatars and I need to be able to return the image_url for each size (small, medium, large) using RABL.
In mongoid model i would simply do self.avatar(:original) but now nothing works, I just get an empty response in the attachment
"user" : {
"id" : "50b204e10eae9c55fa000028",
"paperclip::attachment" : {},
"name" : "My Name"
}
/models/user.rb
has_mongoid_attached_file :avatar,
:styles => {
:original => ['1000x1000>', :jpg],
:small => ['64x64#', :jpg],
:medium => ['250x250', :jpg],
:large => ['500x500>', :jpg]
}
/views/posts/base.json.rabl
child :user do
attributes :id, :name
child :avatar do
attributes :original
end
end
Try this:
child :user do
attributes :id, :name
node :avatar_original do |u|
u.avatar(:original)
end
end
I have a problem with how to do validation on GAE. I have read many tutorials and I prepared django form and I wanted to validate it but I dont see eny error messages in my web page code and I dont see any errors when the values are bad.
import cgi
import os
from google.appengine.ext.webapp import template
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext.db import djangoforms
from django import newforms as forms
class SurveyForm(forms.Form):
occupations_choices = (
('0', "Choose one..."),
('1', "Undergraduate student"),
('2', "Postgraduate student (MSc)"),
('3', "Postgraduate student (PhD)"),
('4', "Lab assistant"),
('5', "Technician"),
('6', "Lecturer"),
('7', "Other" )
)
howreach_choices = (
('0', "Choose one..."),
('1', "Typed the URL directly"),
('2', "Site is bookmarked"),
('3', "A search engine"),
('4', "A link from another site"),
('5', "From a book"),
('6', "Other")
)
boxes_choices = (
("des", "Website Design"),
("svr", "Web Server Administration"),
("com", "Electronic Commerce"),
("mkt", "Web Marketing/Advertising"),
("edu", "Web-Related Education")
)
range_choice = (
('1', '1'),
('2', '2'),
('3', '3'),
('4', '4'),
('5', '5')
)
name = forms.CharField(label='Enter your name', max_length=50, required=True)
email = forms.EmailField(label='Your email address')
occupations = forms.ChoiceField(choices=occupations_choices, label='What is your occupation?')
howreach = forms.ChoiceField(choices=howreach_choices, label='How did you reach this site?')
# radio buttons 1-5
rating = forms.ChoiceField(choices=range_choice , label='How would you rate the content of this site?', widget=forms.RadioSelect)
boxes = forms.ChoiceField(choices=boxes_choices, label='Are you involved in any of the following? (check all that apply)', widget=forms.CheckboxSelectMultiple)
comment = forms.CharField(label=('Any other comments?'), widget=forms.Textarea(attrs={'cols': 40, 'rows': 10}), required=False)
class MainHandler(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
if user:
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
userName = user.nickname()
else:
url = users.create_login_url(self.request.uri)
url_linktext = 'Login'
userName = ''
template_values = {
'url' : url,
'url_linktext' : url_linktext,
'userName' : userName,
'form' : SurveyForm(),
}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
def post(self):
user = users.get_current_user()
if user:
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
userName = user.nickname()
#self.response.out.write(index.html)
else:
url = users.create_login_url(self.request.uri)
url_linktext = 'Login'
userName = ''
template_values = {
'url' : url,
'url_linktext' : url_linktext,
'userName' : userName,
'form' : SurveyForm(),
}
form = SurveyForm(self.request.POST)
if self.request.get('submit') == 'Submit the Form':
if form.is_valid():
self.response.out.write("Poprawne dane")
else:
form = SurveyForm()
template_values['form']=form
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
else:
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
Do You know maybe any tutorial - good tutorial how to do it? My index.html:
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Survey</title>
</head>
<body>
{% if userName %}
You are loged in like: {{ userName }} {{ url_linktext }}
<hr><br/><b>Fill in the form: </b><br/>
<form action="/" method="Post">
{{ form.as_p() }}
<input type="submit" name="submit" value="Submit the Form">
</form>
{% else %}
Please, log in: {{ url_linktext }}
{% endif %}
</body>
</html>
How to do it does the validation started to show me errors? And be like "normal validation"? I thought when I will use the framework it will be much more easier and faster for me but I spent 2 days and it is still not working :/ I could write my own validation in this time :/
Can You help me?
Look at {{ form.some_field.errors }}, or if you want all of them, {{ form.errors }}, or if you need non-field errors only, {{ form.non_field_errors }}.
Here is an example of how to do it: http://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template